summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Schmitz <pierre@archlinux.de>2013-05-22 00:45:21 +0200
committerPierre Schmitz <pierre@archlinux.de>2013-05-22 00:45:21 +0200
commit393e0d71f4c5478bea53ff62ff818aebbabb3e40 (patch)
treea40f0a205ee71a5c61fec5bf23557b7d1813340a
parent953618714cb41a89b1f1078325f94579fc154b8a (diff)
Update to MediaWiki 1.20.6
-rw-r--r--RELEASE-NOTES-1.2012
-rw-r--r--includes/AutoLoader.php1
-rw-r--r--includes/DefaultSettings.php2
-rw-r--r--includes/MessageBlobStore.php220
-rw-r--r--includes/api/ApiUpload.php7
-rw-r--r--includes/resourceloader/ResourceLoader.php20
-rw-r--r--includes/resourceloader/ResourceLoaderFileModule.php22
-rw-r--r--includes/upload/UploadBase.php75
-rw-r--r--includes/upload/UploadFromChunks.php41
-rw-r--r--includes/upload/UploadFromStash.php9
-rw-r--r--includes/upload/UploadStash.php11
-rw-r--r--resources/mediawiki/mediawiki.user.js20
-rw-r--r--skins/common/wikibits.js2
-rw-r--r--skins/monobook/FF2Fixes.css4
14 files changed, 272 insertions, 174 deletions
diff --git a/RELEASE-NOTES-1.20 b/RELEASE-NOTES-1.20
index 80b200d6..d4f399a0 100644
--- a/RELEASE-NOTES-1.20
+++ b/RELEASE-NOTES-1.20
@@ -3,6 +3,18 @@
Security reminder: MediaWiki does not require PHP's register_globals
setting since version 1.2.0. If you have it on, turn it '''off''' if you can.
+
+== MediaWiki 1.20.6 ==
+
+This is a security and maintenance release of the MediaWiki 1.20 branch.
+
+=== Changes since 1.20.5 ===
+* (bug 48306) SECURITY: Run file validation checks on chunked uploads, and chunks
+ of upload, during the upload process.
+* (bug 44327) mediawiki.user: Use session ID instead of 1-year cross-session cookies
+* (bug 47202) wikibits: FF2Fixes.css should not be loaded in Firefox 20.
+* (bug 31044) Make ResourceLoader behave in read-only mode
+
== MediaWiki 1.20.5 ==
This is a security and maintenance release of the MediaWiki 1.20 branch.
diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php
index 9bdfcd29..a8b22027 100644
--- a/includes/AutoLoader.php
+++ b/includes/AutoLoader.php
@@ -965,6 +965,7 @@ $wgAutoloadLocalClasses = array(
'UnwatchedpagesPage' => 'includes/specials/SpecialUnwatchedpages.php',
'UploadChunkFileException' => 'includes/upload/UploadFromChunks.php',
'UploadChunkZeroLengthFileException' => 'includes/upload/UploadFromChunks.php',
+ 'UploadChunkVerificationException' => 'includes/upload/UploadFromChunks.php',
'UploadForm' => 'includes/specials/SpecialUpload.php',
'UploadSourceField' => 'includes/specials/SpecialUpload.php',
'UserrightsPage' => 'includes/specials/SpecialUserrights.php',
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php
index 6abc2b10..710605ad 100644
--- a/includes/DefaultSettings.php
+++ b/includes/DefaultSettings.php
@@ -59,7 +59,7 @@ if( !defined( 'MEDIAWIKI' ) ) {
$wgConf = new SiteConfiguration;
/** MediaWiki version number */
-$wgVersion = '1.20.5';
+$wgVersion = '1.20.6';
/** Name of the site. It must be changed in LocalSettings.php */
$wgSitename = 'MediaWiki';
diff --git a/includes/MessageBlobStore.php b/includes/MessageBlobStore.php
index 34014e1b..c96ea56e 100644
--- a/includes/MessageBlobStore.php
+++ b/includes/MessageBlobStore.php
@@ -80,42 +80,45 @@ class MessageBlobStore {
return false;
}
- $dbw = wfGetDB( DB_MASTER );
- $success = $dbw->insert( 'msg_resource', array(
- 'mr_lang' => $lang,
- 'mr_resource' => $name,
- 'mr_blob' => $blob,
- 'mr_timestamp' => $dbw->timestamp()
- ),
- __METHOD__,
- array( 'IGNORE' )
- );
-
- if ( $success ) {
- if ( $dbw->affectedRows() == 0 ) {
- // Blob was already present, fetch it
- $blob = $dbw->selectField( 'msg_resource', 'mr_blob', array(
- 'mr_resource' => $name,
- 'mr_lang' => $lang,
- ),
- __METHOD__
- );
- } else {
- // Update msg_resource_links
- $rows = array();
+ try {
+ $dbw = wfGetDB( DB_MASTER );
+ $success = $dbw->insert( 'msg_resource', array(
+ 'mr_lang' => $lang,
+ 'mr_resource' => $name,
+ 'mr_blob' => $blob,
+ 'mr_timestamp' => $dbw->timestamp()
+ ),
+ __METHOD__,
+ array( 'IGNORE' )
+ );
- foreach ( $module->getMessages() as $key ) {
- $rows[] = array(
- 'mrl_resource' => $name,
- 'mrl_message' => $key
+ if ( $success ) {
+ if ( $dbw->affectedRows() == 0 ) {
+ // Blob was already present, fetch it
+ $blob = $dbw->selectField( 'msg_resource', 'mr_blob', array(
+ 'mr_resource' => $name,
+ 'mr_lang' => $lang,
+ ),
+ __METHOD__
+ );
+ } else {
+ // Update msg_resource_links
+ $rows = array();
+
+ foreach ( $module->getMessages() as $key ) {
+ $rows[] = array(
+ 'mrl_resource' => $name,
+ 'mrl_message' => $key
+ );
+ }
+ $dbw->insert( 'msg_resource_links', $rows,
+ __METHOD__, array( 'IGNORE' )
);
}
- $dbw->insert( 'msg_resource_links', $rows,
- __METHOD__, array( 'IGNORE' )
- );
}
+ } catch ( Exception $e ) {
+ wfDebug( __METHOD__ . " failed to update DB: $e\n" );
}
-
return $blob;
}
@@ -140,49 +143,52 @@ class MessageBlobStore {
// Save the old and new blobs for later
$oldBlob = $row->mr_blob;
$newBlob = self::generateMessageBlob( $module, $lang );
-
- $newRow = array(
- 'mr_resource' => $name,
- 'mr_lang' => $lang,
- 'mr_blob' => $newBlob,
- 'mr_timestamp' => $dbw->timestamp()
- );
- $dbw->replace( 'msg_resource',
- array( array( 'mr_resource', 'mr_lang' ) ),
- $newRow, __METHOD__
- );
-
- // Figure out which messages were added and removed
- $oldMessages = array_keys( FormatJson::decode( $oldBlob, true ) );
- $newMessages = array_keys( FormatJson::decode( $newBlob, true ) );
- $added = array_diff( $newMessages, $oldMessages );
- $removed = array_diff( $oldMessages, $newMessages );
+ try {
+ $newRow = array(
+ 'mr_resource' => $name,
+ 'mr_lang' => $lang,
+ 'mr_blob' => $newBlob,
+ 'mr_timestamp' => $dbw->timestamp()
+ );
- // Delete removed messages, insert added ones
- if ( $removed ) {
- $dbw->delete( 'msg_resource_links', array(
- 'mrl_resource' => $name,
- 'mrl_message' => $removed
- ), __METHOD__
+ $dbw->replace( 'msg_resource',
+ array( array( 'mr_resource', 'mr_lang' ) ),
+ $newRow, __METHOD__
);
- }
- $newLinksRows = array();
+ // Figure out which messages were added and removed
+ $oldMessages = array_keys( FormatJson::decode( $oldBlob, true ) );
+ $newMessages = array_keys( FormatJson::decode( $newBlob, true ) );
+ $added = array_diff( $newMessages, $oldMessages );
+ $removed = array_diff( $oldMessages, $newMessages );
- foreach ( $added as $message ) {
- $newLinksRows[] = array(
- 'mrl_resource' => $name,
- 'mrl_message' => $message
- );
- }
+ // Delete removed messages, insert added ones
+ if ( $removed ) {
+ $dbw->delete( 'msg_resource_links', array(
+ 'mrl_resource' => $name,
+ 'mrl_message' => $removed
+ ), __METHOD__
+ );
+ }
- if ( $newLinksRows ) {
- $dbw->insert( 'msg_resource_links', $newLinksRows, __METHOD__,
- array( 'IGNORE' ) // just in case
- );
- }
+ $newLinksRows = array();
+
+ foreach ( $added as $message ) {
+ $newLinksRows[] = array(
+ 'mrl_resource' => $name,
+ 'mrl_message' => $message
+ );
+ }
+ if ( $newLinksRows ) {
+ $dbw->insert( 'msg_resource_links', $newLinksRows, __METHOD__,
+ array( 'IGNORE' ) // just in case
+ );
+ }
+ } catch ( Exception $e ) {
+ wfDebug( __METHOD__ . " failed to update DB: $e\n" );
+ }
return $newBlob;
}
@@ -192,50 +198,58 @@ class MessageBlobStore {
* @param $key String: message key
*/
public static function updateMessage( $key ) {
- $dbw = wfGetDB( DB_MASTER );
-
- // Keep running until the updates queue is empty.
- // Due to update conflicts, the queue might not be emptied
- // in one iteration.
- $updates = null;
- do {
- $updates = self::getUpdatesForMessage( $key, $updates );
-
- foreach ( $updates as $k => $update ) {
- // Update the row on the condition that it
- // didn't change since we fetched it by putting
- // the timestamp in the WHERE clause.
- $success = $dbw->update( 'msg_resource',
- array(
- 'mr_blob' => $update['newBlob'],
- 'mr_timestamp' => $dbw->timestamp() ),
- array(
- 'mr_resource' => $update['resource'],
- 'mr_lang' => $update['lang'],
- 'mr_timestamp' => $update['timestamp'] ),
- __METHOD__
- );
+ try {
+ $dbw = wfGetDB( DB_MASTER );
+
+ // Keep running until the updates queue is empty.
+ // Due to update conflicts, the queue might not be emptied
+ // in one iteration.
+ $updates = null;
+ do {
+ $updates = self::getUpdatesForMessage( $key, $updates );
+
+ foreach ( $updates as $k => $update ) {
+ // Update the row on the condition that it
+ // didn't change since we fetched it by putting
+ // the timestamp in the WHERE clause.
+ $success = $dbw->update( 'msg_resource',
+ array(
+ 'mr_blob' => $update['newBlob'],
+ 'mr_timestamp' => $dbw->timestamp() ),
+ array(
+ 'mr_resource' => $update['resource'],
+ 'mr_lang' => $update['lang'],
+ 'mr_timestamp' => $update['timestamp'] ),
+ __METHOD__
+ );
- // Only requeue conflicted updates.
- // If update() returned false, don't retry, for
- // fear of getting into an infinite loop
- if ( !( $success && $dbw->affectedRows() == 0 ) ) {
- // Not conflicted
- unset( $updates[$k] );
+ // Only requeue conflicted updates.
+ // If update() returned false, don't retry, for
+ // fear of getting into an infinite loop
+ if ( !( $success && $dbw->affectedRows() == 0 ) ) {
+ // Not conflicted
+ unset( $updates[$k] );
+ }
}
- }
- } while ( count( $updates ) );
+ } while ( count( $updates ) );
- // No need to update msg_resource_links because we didn't add
- // or remove any messages, we just changed their contents.
+ // No need to update msg_resource_links because we didn't add
+ // or remove any messages, we just changed their contents.
+ } catch ( Exception $e ) {
+ wfDebug( __METHOD__ . " failed to update DB: $e\n" );
+ }
}
public static function clear() {
// TODO: Give this some more thought
// TODO: Is TRUNCATE better?
- $dbw = wfGetDB( DB_MASTER );
- $dbw->delete( 'msg_resource', '*', __METHOD__ );
- $dbw->delete( 'msg_resource_links', '*', __METHOD__ );
+ try {
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->delete( 'msg_resource', '*', __METHOD__ );
+ $dbw->delete( 'msg_resource_links', '*', __METHOD__ );
+ } catch ( Exception $e ) {
+ wfDebug( __METHOD__ . " failed to update DB: $e\n" );
+ }
}
/**
diff --git a/includes/api/ApiUpload.php b/includes/api/ApiUpload.php
index 3a9b5c56..e7a7849b 100644
--- a/includes/api/ApiUpload.php
+++ b/includes/api/ApiUpload.php
@@ -187,7 +187,12 @@ class ApiUpload extends ApiBase {
$chunkPath = $request->getFileTempname( 'chunk' );
$chunkSize = $request->getUpload( 'chunk' )->getSize();
if ($this->mParams['offset'] == 0) {
- $result['filekey'] = $this->performStash();
+ try {
+ $result['filekey'] = $this->performStash();
+ } catch ( MWException $e ) {
+ // FIXME: Error handling here is wrong/different from rest of this
+ $this->dieUsage( $e->getMessage(), 'stashfailed' );
+ }
} else {
$status = $this->mUpload->addChunk($chunkPath, $chunkSize,
$this->mParams['offset']);
diff --git a/includes/resourceloader/ResourceLoader.php b/includes/resourceloader/ResourceLoader.php
index 3b48a266..7b87f9d4 100644
--- a/includes/resourceloader/ResourceLoader.php
+++ b/includes/resourceloader/ResourceLoader.php
@@ -176,6 +176,7 @@ class ResourceLoader {
} catch ( Exception $exception ) {
// Return exception as a comment
$result = $this->makeComment( $exception->__toString() );
+ $this->hasErrors = true;
}
wfProfileOut( __METHOD__ );
@@ -434,6 +435,7 @@ class ResourceLoader {
wfProfileIn( __METHOD__ );
$errors = '';
+ $this->hasErrors = false;
// Split requested modules into two groups, modules and missing
$modules = array();
@@ -445,6 +447,7 @@ class ResourceLoader {
// This is a security issue, see bug 34907.
if ( $module->getGroup() === 'private' ) {
$errors .= $this->makeComment( "Cannot show private module \"$name\"" );
+ $this->hasErrors = true;
continue;
}
$modules[$name] = $this->getModule( $name );
@@ -459,6 +462,7 @@ class ResourceLoader {
} catch( Exception $e ) {
// Add exception to the output as a comment
$errors .= $this->makeComment( $e->__toString() );
+ $this->hasErrors = true;
}
wfProfileIn( __METHOD__.'-getModifiedTime' );
@@ -476,14 +480,12 @@ class ResourceLoader {
} catch ( Exception $e ) {
// Add exception to the output as a comment
$errors .= $this->makeComment( $e->__toString() );
+ $this->hasErrors = true;
}
}
wfProfileOut( __METHOD__.'-getModifiedTime' );
- // Send content type and cache related headers
- $this->sendResponseHeaders( $context, $mtime );
-
// If there's an If-Modified-Since header, respond with a 304 appropriately
if ( $this->tryRespondLastModified( $context, $mtime ) ) {
wfProfileOut( __METHOD__ );
@@ -500,6 +502,7 @@ class ResourceLoader {
// response in a comment if we're in debug mode.
if ( $context->getDebug() && strlen( $warnings = ob_get_contents() ) ) {
$response = $this->makeComment( $warnings ) . $response;
+ $this->hasErrors = true;
}
// Save response to file cache unless there are errors
@@ -514,6 +517,9 @@ class ResourceLoader {
}
}
+ // Send content type and cache related headers
+ $this->sendResponseHeaders( $context, $mtime, $this->hasErrors );
+
// Remove the output buffer and output the response
ob_end_clean();
echo $response;
@@ -525,13 +531,15 @@ class ResourceLoader {
* Send content type and last modified headers to the client.
* @param $context ResourceLoaderContext
* @param $mtime string TS_MW timestamp to use for last-modified
+ * @param $error bool Whether there are commented-out errors in the response
* @return void
*/
- protected function sendResponseHeaders( ResourceLoaderContext $context, $mtime ) {
+ protected function sendResponseHeaders( ResourceLoaderContext $context, $mtime, $errors ) {
global $wgResourceLoaderMaxage;
// If a version wasn't specified we need a shorter expiry time for updates
// to propagate to clients quickly
- if ( is_null( $context->getVersion() ) ) {
+ // If there were errors, we also need a shorter expiry time so we can recover quickly
+ if ( is_null( $context->getVersion() ) || $errors ) {
$maxage = $wgResourceLoaderMaxage['unversioned']['client'];
$smaxage = $wgResourceLoaderMaxage['unversioned']['server'];
// If a version was specified we can use a longer expiry time since changing
@@ -679,6 +687,7 @@ class ResourceLoader {
} catch ( Exception $e ) {
// Add exception to the output as a comment
$exceptions .= $this->makeComment( $e->__toString() );
+ $this->hasErrors = true;
}
} else {
$blobs = array();
@@ -784,6 +793,7 @@ class ResourceLoader {
} catch ( Exception $e ) {
// Add exception to the output as a comment
$exceptions .= $this->makeComment( $e->__toString() );
+ $this->hasErrors = true;
// Register module as missing
$missing[] = $name;
diff --git a/includes/resourceloader/ResourceLoaderFileModule.php b/includes/resourceloader/ResourceLoaderFileModule.php
index d0c56ae8..8b9b7277 100644
--- a/includes/resourceloader/ResourceLoaderFileModule.php
+++ b/includes/resourceloader/ResourceLoaderFileModule.php
@@ -308,15 +308,19 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
// Collect referenced files
$this->localFileRefs = array_unique( $this->localFileRefs );
// If the list has been modified since last time we cached it, update the cache
- if ( $this->localFileRefs !== $this->getFileDependencies( $context->getSkin() ) && !wfReadOnly() ) {
- $dbw = wfGetDB( DB_MASTER );
- $dbw->replace( 'module_deps',
- array( array( 'md_module', 'md_skin' ) ), array(
- 'md_module' => $this->getName(),
- 'md_skin' => $context->getSkin(),
- 'md_deps' => FormatJson::encode( $this->localFileRefs ),
- )
- );
+ try {
+ if ( $this->localFileRefs !== $this->getFileDependencies( $context->getSkin() ) ) {
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->replace( 'module_deps',
+ array( array( 'md_module', 'md_skin' ) ), array(
+ 'md_module' => $this->getName(),
+ 'md_skin' => $context->getSkin(),
+ 'md_deps' => FormatJson::encode( $this->localFileRefs ),
+ )
+ );
+ }
+ } catch ( Exception $e ) {
+ wfDebug( __METHOD__ . " failed to update DB: $e\n" );
}
return $styles;
}
diff --git a/includes/upload/UploadBase.php b/includes/upload/UploadBase.php
index 3a5733ca..0848780f 100644
--- a/includes/upload/UploadBase.php
+++ b/includes/upload/UploadBase.php
@@ -345,6 +345,8 @@ abstract class UploadBase {
/**
* Verify the mime type
*
+ * @note Only checks that it is not an evil mime. The does it have
+ * correct extension given its mime type check is in verifyFile.
* @param $mime string representing the mime
* @return mixed true if the file is verified, an array otherwise
*/
@@ -359,12 +361,6 @@ abstract class UploadBase {
return array( 'filetype-badmime', $mime );
}
- # XXX: Missing extension will be caught by validateName() via getTitle()
- if ( $this->mFinalExtension != '' && !$this->verifyExtension( $mime, $this->mFinalExtension ) ) {
- wfProfileOut( __METHOD__ );
- return array( 'filetype-mime-mismatch', $this->mFinalExtension, $mime );
- }
-
# Check IE type
$fp = fopen( $this->mTempPath, 'rb' );
$chunk = fread( $fp, 256 );
@@ -391,6 +387,56 @@ abstract class UploadBase {
* @return mixed true of the file is verified, array otherwise.
*/
protected function verifyFile() {
+ global $wgVerifyMimeType;
+ wfProfileIn( __METHOD__ );
+
+ $status = $this->verifyPartialFile();
+ if ( $status !== true ) {
+ wfProfileOut( __METHOD__ );
+ return $status;
+ }
+
+ if ( $wgVerifyMimeType ) {
+ $this->mFileProps = FSFile::getPropsFromPath( $this->mTempPath, $this->mFinalExtension );
+ $mime = $this->mFileProps['file-mime'];
+
+ # XXX: Missing extension will be caught by validateName() via getTitle()
+ if ( $this->mFinalExtension != '' && !$this->verifyExtension( $mime, $this->mFinalExtension ) ) {
+ wfProfileOut( __METHOD__ );
+ return array( 'filetype-mime-mismatch', $this->mFinalExtension, $mime );
+ }
+ }
+
+ $handler = MediaHandler::getHandler( $mime );
+ if ( $handler ) {
+ $handlerStatus = $handler->verifyUpload( $this->mTempPath );
+ if ( !$handlerStatus->isOK() ) {
+ $errors = $handlerStatus->getErrorsArray();
+ wfProfileOut( __METHOD__ );
+ return reset( $errors );
+ }
+ }
+
+ wfRunHooks( 'UploadVerifyFile', array( $this, $mime, &$status ) );
+ if ( $status !== true ) {
+ wfProfileOut( __METHOD__ );
+ return $status;
+ }
+
+ wfDebug( __METHOD__ . ": all clear; passing.\n" );
+ wfProfileOut( __METHOD__ );
+ return true;
+ }
+
+ /**
+ * A verification routine suitable for partial files
+ *
+ * Runs the blacklist checks, but not any checks that may
+ * assume the entire file is present.
+ *
+ * @return Mixed true for valid or array with error message key.
+ */
+ protected function verifyPartialFile() {
global $wgAllowJavaUploads, $wgDisableUploadScriptChecks;
wfProfileIn( __METHOD__ );
@@ -449,23 +495,6 @@ abstract class UploadBase {
return array( 'uploadvirus', $virus );
}
- $handler = MediaHandler::getHandler( $mime );
- if ( $handler ) {
- $handlerStatus = $handler->verifyUpload( $this->mTempPath );
- if ( !$handlerStatus->isOK() ) {
- $errors = $handlerStatus->getErrorsArray();
- wfProfileOut( __METHOD__ );
- return reset( $errors );
- }
- }
-
- wfRunHooks( 'UploadVerifyFile', array( $this, $mime, &$status ) );
- if ( $status !== true ) {
- wfProfileOut( __METHOD__ );
- return $status;
- }
-
- wfDebug( __METHOD__ . ": all clear; passing.\n" );
wfProfileOut( __METHOD__ );
return true;
}
diff --git a/includes/upload/UploadFromChunks.php b/includes/upload/UploadFromChunks.php
index 0542bba5..531f7be4 100644
--- a/includes/upload/UploadFromChunks.php
+++ b/includes/upload/UploadFromChunks.php
@@ -69,6 +69,8 @@ class UploadFromChunks extends UploadFromFile {
// Stash file is the called on creating a new chunk session:
$this->mChunkIndex = 0;
$this->mOffset = 0;
+
+ $this->verifyChunk();
// Create a local stash target
$this->mLocalFile = parent::stashFile();
// Update the initial file offset ( based on file size )
@@ -127,9 +129,18 @@ class UploadFromChunks extends UploadFromFile {
if( !$status->isOk() ){
return $status;
}
+
+ $this->mTempPath = $tmpPath; // file system path
+ $this->mFileSize = filesize( $this->mTempPath ); //Since this was set for the last chunk previously
+ $ret = $this->verifyUpload();
+ if ( $ret['status'] !== UploadBase::OK ) {
+ wfDebugLog( 'fileconcatenate', "Verification failed for chunked upload" );
+ $status->fatal( $this->getVerificationErrorCode( $ret['status'] ) );
+ return $status;
+ }
+
// Update the mTempPath and mLocalFile
// ( for FileUpload or normal Stash to take over )
- $this->mTempPath = $tmpPath; // file system path
$this->mLocalFile = parent::stashFile();
return $status;
@@ -181,6 +192,15 @@ class UploadFromChunks extends UploadFromFile {
if ( $preAppendOffset == $offset ) {
// Update local chunk index for the current chunk
$this->mChunkIndex++;
+ try {
+ # For some reason mTempPath is set to first part
+ $oldTemp = $this->mTempPath;
+ $this->mTempPath = $chunkPath;
+ $this->verifyChunk();
+ $this->mTempPath = $oldTemp;
+ } catch ( UploadChunkVerificationException $e ) {
+ return Status::newFatal( $e->getMessage() );
+ }
$status = $this->outputChunk( $chunkPath );
if( $status->isGood() ){
// Update local offset:
@@ -300,7 +320,26 @@ class UploadFromChunks extends UploadFromFile {
}
return $this->mFileKey . '.' . $index ;
}
+
+ /**
+ * Verify that the chunk isn't really an evil html file
+ *
+ * @throws UploadChunkVerificationException
+ */
+ private function verifyChunk() {
+ // Rest mDesiredDestName here so we verify the name as if it were mFileKey
+ $oldDesiredDestName = $this->mDesiredDestName;
+ $this->mDesiredDestName = $this->mFileKey;
+ $this->mTitle = false;
+ $res = $this->verifyPartialFile();
+ $this->mDesiredDestName = $oldDesiredDestName;
+ $this->mTitle = false;
+ if( is_array( $res ) ) {
+ throw new UploadChunkVerificationException( $res[0] );
+ }
+ }
}
class UploadChunkZeroLengthFileException extends MWException {};
class UploadChunkFileException extends MWException {};
+class UploadChunkVerificationException extends MWException {};
diff --git a/includes/upload/UploadFromStash.php b/includes/upload/UploadFromStash.php
index 607965f3..d79641ce 100644
--- a/includes/upload/UploadFromStash.php
+++ b/includes/upload/UploadFromStash.php
@@ -129,14 +129,9 @@ class UploadFromStash extends UploadBase {
return $this->mSourceType;
}
- /**
- * File has been previously verified so no need to do so again.
- *
- * @return bool
+ /*
+ * protected function verifyFile() inherited
*/
- protected function verifyFile() {
- return true;
- }
/**
* Stash the file.
diff --git a/includes/upload/UploadStash.php b/includes/upload/UploadStash.php
index c7fd23a9..53a90582 100644
--- a/includes/upload/UploadStash.php
+++ b/includes/upload/UploadStash.php
@@ -422,6 +422,7 @@ class UploadStash {
* @return string
*/
public static function getExtensionForPath( $path ) {
+ global $wgFileBlacklist;
// Does this have an extension?
$n = strrpos( $path, '.' );
$extension = null;
@@ -441,7 +442,15 @@ class UploadStash {
throw new UploadStashFileException( "extension is null" );
}
- return File::normalizeExtension( $extension );
+ $extension = File::normalizeExtension( $extension );
+ if ( in_array( $extension, $wgFileBlacklist ) ) {
+ // The file should already be checked for being evil.
+ // However, if somehow we got here, we definitely
+ // don't want to give it an extension of .php and
+ // put it in a web accesible directory.
+ return '';
+ }
+ return $extension;
}
/**
diff --git a/resources/mediawiki/mediawiki.user.js b/resources/mediawiki/mediawiki.user.js
index 5c5c87e2..e64d2e84 100644
--- a/resources/mediawiki/mediawiki.user.js
+++ b/resources/mediawiki/mediawiki.user.js
@@ -122,30 +122,16 @@
};
/**
- * Gets the current user's name or a random ID automatically generated and kept in a cookie.
- *
- * This ID is persistent for anonymous users, staying in their browser up to 1 year. The
- * expiration time is reset each time the ID is queried, so in most cases this ID will
- * persist until the browser's cookies are cleared or the user doesn't visit for 1 year.
+ * Gets the current user's name or the session ID
*
* @return String: User name or random session ID
*/
this.id = function() {
- var id,
- name = user.getName();
+ var name = user.getName();
if ( name ) {
return name;
}
- id = $.cookie( 'mediaWiki.user.id' );
- if ( typeof id === 'undefined' || id === null ) {
- id = generateId();
- }
- // Set cookie if not set, or renew it if already set
- $.cookie( 'mediaWiki.user.id', id, {
- expires: 365,
- path: '/'
- } );
- return id;
+ return user.sessionId();
};
/**
diff --git a/skins/common/wikibits.js b/skins/common/wikibits.js
index cae08af9..05efb4a9 100644
--- a/skins/common/wikibits.js
+++ b/skins/common/wikibits.js
@@ -123,8 +123,6 @@ if ( mw.config.get( 'skin' ) === 'monobook' ) {
importStylesheetURI( skinpath + '/Opera7Fixes.css' );
} else if ( opera95_bugs ) {
importStylesheetURI( skinpath + '/Opera9Fixes.css' );
- } else if ( ff2_bugs ) {
- importStylesheetURI( skinpath + '/FF2Fixes.css' );
}
}
diff --git a/skins/monobook/FF2Fixes.css b/skins/monobook/FF2Fixes.css
deleted file mode 100644
index c8b65f50..00000000
--- a/skins/monobook/FF2Fixes.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.rtl .external, a.feedlink {
- padding: 0 !important;
- background: none !important;
-}