Update formatting of includes/upload/

Change-Id: I8cf59cd3bb6dd8de2ed6509b7bc2ef9ff7c5caf1
This commit is contained in:
Siebrand Mazeland 2014-05-09 16:53:19 +02:00
parent 79fa6f546a
commit 69a2ecfe3e
6 changed files with 176 additions and 49 deletions

View file

@ -120,6 +120,7 @@ abstract class UploadBase {
return $permission;
}
}
return true;
}
@ -167,6 +168,7 @@ abstract class UploadBase {
$handler = new $className;
$handler->initializeFromRequest( $request );
return $handler;
}
@ -179,7 +181,8 @@ abstract class UploadBase {
return false;
}
public function __construct() {}
public function __construct() {
}
/**
* Returns the upload type. Should be overridden by child classes
@ -267,6 +270,7 @@ abstract class UploadBase {
$path = $srcPath;
}
wfProfileOut( __METHOD__ );
return $path;
}
@ -282,6 +286,7 @@ abstract class UploadBase {
*/
if ( $this->isEmptyFile() ) {
wfProfileOut( __METHOD__ );
return array( 'status' => self::EMPTY_FILE );
}
@ -291,6 +296,7 @@ abstract class UploadBase {
$maxSize = self::getMaxUploadSize( $this->getSourceType() );
if ( $this->mFileSize > $maxSize ) {
wfProfileOut( __METHOD__ );
return array(
'status' => self::FILE_TOO_LARGE,
'max' => $maxSize,
@ -305,6 +311,7 @@ abstract class UploadBase {
$verification = $this->verifyFile();
if ( $verification !== true ) {
wfProfileOut( __METHOD__ );
return array(
'status' => self::VERIFICATION_ERROR,
'details' => $verification
@ -317,6 +324,7 @@ abstract class UploadBase {
$result = $this->validateName();
if ( $result !== true ) {
wfProfileOut( __METHOD__ );
return $result;
}
@ -325,10 +333,12 @@ abstract class UploadBase {
array( $this->mDestName, $this->mTempPath, &$error ) )
) {
wfProfileOut( __METHOD__ );
return array( 'status' => self::HOOK_ABORTED, 'error' => $error );
}
wfProfileOut( __METHOD__ );
return array( 'status' => self::OK );
}
@ -351,6 +361,7 @@ abstract class UploadBase {
$result['blacklistedExt'] = $this->mBlackListedExtensions;
}
}
return $result;
}
$this->mDestName = $this->getLocalFile()->getName();
@ -374,6 +385,7 @@ abstract class UploadBase {
global $wgMimeTypeBlacklist;
if ( $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
wfProfileOut( __METHOD__ );
return array( 'filetype-badmime', $mime );
}
@ -388,12 +400,14 @@ abstract class UploadBase {
foreach ( $ieTypes as $ieType ) {
if ( $this->checkFileExtension( $ieType, $wgMimeTypeBlacklist ) ) {
wfProfileOut( __METHOD__ );
return array( 'filetype-bad-ie-mime', $ieType );
}
}
}
wfProfileOut( __METHOD__ );
return true;
}
@ -409,6 +423,7 @@ abstract class UploadBase {
$status = $this->verifyPartialFile();
if ( $status !== true ) {
wfProfileOut( __METHOD__ );
return $status;
}
@ -419,6 +434,7 @@ abstract class UploadBase {
# 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 );
}
}
@ -429,6 +445,7 @@ abstract class UploadBase {
if ( !$handlerStatus->isOK() ) {
$errors = $handlerStatus->getErrorsArray();
wfProfileOut( __METHOD__ );
return reset( $errors );
}
}
@ -436,11 +453,13 @@ abstract class UploadBase {
wfRunHooks( 'UploadVerifyFile', array( $this, $mime, &$status ) );
if ( $status !== true ) {
wfProfileOut( __METHOD__ );
return $status;
}
wfDebug( __METHOD__ . ": all clear; passing.\n" );
wfProfileOut( __METHOD__ );
return true;
}
@ -466,6 +485,7 @@ abstract class UploadBase {
$status = $this->verifyMimeType( $mime );
if ( $status !== true ) {
wfProfileOut( __METHOD__ );
return $status;
}
@ -473,12 +493,14 @@ abstract class UploadBase {
if ( !$wgDisableUploadScriptChecks ) {
if ( self::detectScript( $this->mTempPath, $mime, $this->mFinalExtension ) ) {
wfProfileOut( __METHOD__ );
return array( 'uploadscripted' );
}
if ( $this->mFinalExtension == 'svg' || $mime == 'image/svg+xml' ) {
$svgStatus = $this->detectScriptInSvg( $this->mTempPath );
if ( $svgStatus !== false ) {
wfProfileOut( __METHOD__ );
return $svgStatus;
}
}
@ -495,11 +517,13 @@ abstract class UploadBase {
$error = reset( $errors );
if ( $error[0] !== 'zip-wrong-format' ) {
wfProfileOut( __METHOD__ );
return $error;
}
}
if ( $this->mJavaDetected ) {
wfProfileOut( __METHOD__ );
return array( 'uploadjava' );
}
}
@ -508,10 +532,12 @@ abstract class UploadBase {
$virus = $this->detectVirus( $this->mTempPath );
if ( $virus ) {
wfProfileOut( __METHOD__ );
return array( 'uploadvirus', $virus );
}
wfProfileOut( __METHOD__ );
return true;
}
@ -581,6 +607,7 @@ abstract class UploadBase {
if ( $permErrors || $permErrorsUpload || $permErrorsCreate ) {
$permErrors = array_merge( $permErrors, wfArrayDiff2( $permErrorsUpload, $permErrors ) );
$permErrors = array_merge( $permErrors, wfArrayDiff2( $permErrorsCreate, $permErrors ) );
return $permErrors;
}
@ -670,6 +697,7 @@ abstract class UploadBase {
}
wfProfileOut( __METHOD__ );
return $warnings;
}
@ -705,6 +733,7 @@ abstract class UploadBase {
}
wfProfileOut( __METHOD__ );
return $status;
}
@ -733,6 +762,7 @@ abstract class UploadBase {
if ( strlen( $this->mFilteredName ) > 240 ) {
$this->mTitleError = self::FILENAME_TOO_LONG;
$this->mTitle = null;
return $this->mTitle;
}
@ -747,6 +777,7 @@ abstract class UploadBase {
if ( is_null( $nt ) ) {
$this->mTitleError = self::ILLEGAL_FILENAME;
$this->mTitle = null;
return $this->mTitle;
}
$this->mFilteredName = $nt->getDBkey();
@ -789,13 +820,16 @@ abstract class UploadBase {
if ( $this->mFinalExtension == '' ) {
$this->mTitleError = self::FILETYPE_MISSING;
$this->mTitle = null;
return $this->mTitle;
} elseif ( $blackListedExtensions ||
( $wgCheckFileExtensions && $wgStrictFileExtensions &&
!$this->checkFileExtension( $this->mFinalExtension, $wgFileExtensions ) ) ) {
( $wgCheckFileExtensions && $wgStrictFileExtensions &&
!$this->checkFileExtension( $this->mFinalExtension, $wgFileExtensions ) )
) {
$this->mBlackListedExtensions = $blackListedExtensions;
$this->mTitleError = self::FILETYPE_BADTYPE;
$this->mTitle = null;
return $this->mTitle;
}
@ -803,6 +837,7 @@ abstract class UploadBase {
if ( wfIsWindows() && !preg_match( '/^[\x0-\x7f]*$/', $nt->getText() ) ) {
$this->mTitleError = self::WINDOWS_NONASCII_FILENAME;
$this->mTitle = null;
return $this->mTitle;
}
@ -817,10 +852,12 @@ abstract class UploadBase {
if ( strlen( $partname ) < 1 ) {
$this->mTitleError = self::MIN_LENGTH_PARTNAME;
$this->mTitle = null;
return $this->mTitle;
}
$this->mTitle = $nt;
return $this->mTitle;
}
@ -834,6 +871,7 @@ abstract class UploadBase {
$nt = $this->getTitle();
$this->mLocalFile = is_null( $nt ) ? null : wfLocalFile( $nt );
}
return $this->mLocalFile;
}
@ -858,6 +896,7 @@ abstract class UploadBase {
$this->mLocalFile = $file;
wfProfileOut( __METHOD__ );
return $file;
}
@ -906,6 +945,7 @@ abstract class UploadBase {
public static function splitExtensions( $filename ) {
$bits = explode( '.', $filename );
$basename = array_shift( $bits );
return array( $basename, $bits );
}
@ -947,10 +987,12 @@ abstract class UploadBase {
if ( !$magic->isRecognizableExtension( $extension ) ) {
wfDebug( __METHOD__ . ": passing file with unknown detected mime type; " .
"unrecognized extension '$extension', can't verify\n" );
return true;
} else {
wfDebug( __METHOD__ . ": rejecting file with unknown detected mime type; " .
"recognized extension '$extension', so probably invalid file\n" );
return false;
}
}
@ -960,9 +1002,11 @@ abstract class UploadBase {
if ( $match === null ) {
if ( $magic->getTypesForExtension( $extension ) !== null ) {
wfDebug( __METHOD__ . ": No extension known for $mime, but we know a mime for $extension\n" );
return false;
} else {
wfDebug( __METHOD__ . ": no file extension known for mime type $mime, passing file\n" );
return true;
}
} elseif ( $match === true ) {
@ -970,9 +1014,9 @@ abstract class UploadBase {
#TODO: if it's a bitmap, make sure PHP or ImageMagic resp. can handle it!
return true;
} else {
wfDebug( __METHOD__ . ": mime type $mime mismatches file extension $extension, rejecting file\n" );
return false;
}
}
@ -1007,6 +1051,7 @@ abstract class UploadBase {
if ( !$chunk ) {
wfProfileOut( __METHOD__ );
return false;
}
@ -1031,6 +1076,7 @@ abstract class UploadBase {
# check for HTML doctype
if ( preg_match( "/<!DOCTYPE *X?HTML/i", $chunk ) ) {
wfProfileOut( __METHOD__ );
return true;
}
@ -1039,6 +1085,7 @@ abstract class UploadBase {
if ( $extension == 'svg' || strpos( $mime, 'image/svg' ) === 0 ) {
if ( self::checkXMLEncodingMissmatch( $file ) ) {
wfProfileOut( __METHOD__ );
return true;
}
}
@ -1062,7 +1109,7 @@ abstract class UploadBase {
'<a href',
'<body',
'<head',
'<html', #also in safari
'<html', #also in safari
'<img',
'<pre',
'<script', #also in safari
@ -1077,6 +1124,7 @@ abstract class UploadBase {
if ( false !== strpos( $chunk, $tag ) ) {
wfDebug( __METHOD__ . ": found something that may make it be mistaken for html: $tag\n" );
wfProfileOut( __METHOD__ );
return true;
}
}
@ -1092,6 +1140,7 @@ abstract class UploadBase {
if ( preg_match( '!type\s*=\s*[\'"]?\s*(?:\w*/)?(?:ecma|java)!sim', $chunk ) ) {
wfDebug( __METHOD__ . ": found script types\n" );
wfProfileOut( __METHOD__ );
return true;
}
@ -1099,6 +1148,7 @@ abstract class UploadBase {
if ( preg_match( '!(?:href|src|data)\s*=\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) {
wfDebug( __METHOD__ . ": found html-style script urls\n" );
wfProfileOut( __METHOD__ );
return true;
}
@ -1106,11 +1156,13 @@ abstract class UploadBase {
if ( preg_match( '!url\s*\(\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) {
wfDebug( __METHOD__ . ": found css-style script urls\n" );
wfProfileOut( __METHOD__ );
return true;
}
wfDebug( __METHOD__ . ": no scripts found\n" );
wfProfileOut( __METHOD__ );
return false;
}
@ -1131,16 +1183,19 @@ abstract class UploadBase {
&& !in_array( strtoupper( $encMatch[1] ), self::$safeXmlEncodings )
) {
wfDebug( __METHOD__ . ": Found unsafe XML encoding '{$encMatch[1]}'\n" );
return true;
}
} elseif ( preg_match( "!<\?xml\b!si", $contents ) ) {
// Start of XML declaration without an end in the first $wgSVGMetadataCutoff
// bytes. There shouldn't be a legitimate reason for this to happen.
wfDebug( __METHOD__ . ": Unmatched XML declaration start\n" );
return true;
} elseif ( substr( $contents, 0, 4 ) == "\x4C\x6F\xA7\x94" ) {
// EBCDIC encoded XML
wfDebug( __METHOD__ . ": EBCDIC Encoded XML\n" );
return true;
}
@ -1151,17 +1206,19 @@ abstract class UploadBase {
wfSuppressWarnings();
$str = iconv( $encoding, 'UTF-8', $contents );
wfRestoreWarnings();
if ( $str != '' && preg_match( "!<\?xml\b(.*?)\?>!si", $str, $matches ) ) {
if ( $str != '' && preg_match( "!<\?xml\b(.*?)\?>!si", $str, $matches ) ) {
if ( preg_match( $encodingRegex, $matches[1], $encMatch )
&& !in_array( strtoupper( $encMatch[1] ), self::$safeXmlEncodings )
) {
wfDebug( __METHOD__ . ": Found unsafe XML encoding '{$encMatch[1]}'\n" );
return true;
}
} elseif ( $str != '' && preg_match( "!<\?xml\b!si", $str ) ) {
// Start of XML declaration without an end in the first $wgSVGMetadataCutoff
// bytes. There shouldn't be a legitimate reason for this to happen.
wfDebug( __METHOD__ . ": Unmatched XML declaration start\n" );
return true;
}
}
@ -1188,8 +1245,10 @@ abstract class UploadBase {
if ( $this->mSVGNSError ) {
return array( 'uploadscriptednamespace', $this->mSVGNSError );
}
return array( 'uploadscripted' );
}
return false;
}
@ -1204,6 +1263,7 @@ abstract class UploadBase {
if ( preg_match( '/xml-stylesheet/i', $target ) ) {
return true;
}
return false;
}
@ -1257,6 +1317,7 @@ abstract class UploadBase {
wfDebug( __METHOD__ . ": Non-svg namespace '$namespace' in uploaded file.\n" );
// @TODO return a status object to a closure in XmlTypeCheck, for MW1.21+
$this->mSVGNSError = $namespace;
return true;
}
@ -1265,24 +1326,28 @@ abstract class UploadBase {
*/
if ( $strippedElement == 'script' ) {
wfDebug( __METHOD__ . ": Found script element '$element' in uploaded file.\n" );
return true;
}
# e.g., <svg xmlns="http://www.w3.org/2000/svg"> <handler xmlns:ev="http://www.w3.org/2001/xml-events" ev:event="load">alert(1)</handler> </svg>
if ( $strippedElement == 'handler' ) {
wfDebug( __METHOD__ . ": Found scriptable element '$element' in uploaded file.\n" );
return true;
}
# SVG reported in Feb '12 that used xml:stylesheet to generate javascript block
if ( $strippedElement == 'stylesheet' ) {
wfDebug( __METHOD__ . ": Found scriptable element '$element' in uploaded file.\n" );
return true;
}
# Block iframes, in case they pass the namespace check
if ( $strippedElement == 'iframe' ) {
wfDebug( __METHOD__ . ": iframe in uploaded file.\n" );
return true;
}
@ -1292,48 +1357,56 @@ abstract class UploadBase {
if ( substr( $stripped, 0, 2 ) == 'on' ) {
wfDebug( __METHOD__ . ": Found event-handler attribute '$attrib'='$value' in uploaded file.\n" );
return true;
}
# href with javascript target
if ( $stripped == 'href' && strpos( strtolower( $value ), 'javascript:' ) !== false ) {
wfDebug( __METHOD__ . ": Found script in href attribute '$attrib'='$value' in uploaded file.\n" );
return true;
}
# href with embedded svg as target
if ( $stripped == 'href' && preg_match( '!data:[^,]*image/svg[^,]*,!sim', $value ) ) {
wfDebug( __METHOD__ . ": Found href to embedded svg \"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
return true;
}
# href with embedded (text/xml) svg as target
if ( $stripped == 'href' && preg_match( '!data:[^,]*text/xml[^,]*,!sim', $value ) ) {
wfDebug( __METHOD__ . ": Found href to embedded svg \"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
return true;
}
# use set/animate to add event-handler attribute to parent
if ( ( $strippedElement == 'set' || $strippedElement == 'animate' ) && $stripped == 'attributename' && substr( $value, 0, 2 ) == 'on' ) {
wfDebug( __METHOD__ . ": Found svg setting event-handler attribute with \"<$strippedElement $stripped='$value'...\" in uploaded file.\n" );
return true;
}
# use set to add href attribute to parent element
if ( $strippedElement == 'set' && $stripped == 'attributename' && strpos( $value, 'href' ) !== false ) {
wfDebug( __METHOD__ . ": Found svg setting href attribute '$value' in uploaded file.\n" );
return true;
}
# use set to add a remote / data / script target to an element
if ( $strippedElement == 'set' && $stripped == 'to' && preg_match( '!(http|https|data|script):!sim', $value ) ) {
wfDebug( __METHOD__ . ": Found svg setting attribute to '$value' in uploaded file.\n" );
return true;
}
# use handler attribute with remote / data / script
if ( $stripped == 'handler' && preg_match( '!(http|https|data|script):!sim', $value ) ) {
wfDebug( __METHOD__ . ": Found svg setting handler with remote/data/script '$attrib'='$value' in uploaded file.\n" );
return true;
}
@ -1343,6 +1416,7 @@ abstract class UploadBase {
foreach ( $matches[1] as $match ) {
if ( !preg_match( '!(?:font|clip-path|fill|filter|marker|marker-end|marker-mid|marker-start|mask|stroke)\s*:\s*url\s*\(\s*(#|\'#|"#)!sim', $match ) ) {
wfDebug( __METHOD__ . ": Found svg setting a style with remote url '$attrib'='$value' in uploaded file.\n" );
return true;
}
}
@ -1351,9 +1425,9 @@ abstract class UploadBase {
# image filters can pull in url, which could be svg that executes scripts
if ( $strippedElement == 'image' && $stripped == 'filter' && preg_match( '!url\s*\(!sim', $value ) ) {
wfDebug( __METHOD__ . ": Found image filter with url: \"<$strippedElement $stripped='$value'...\" in uploaded file.\n" );
return true;
}
}
return false; //No scripts detected
@ -1369,6 +1443,7 @@ abstract class UploadBase {
$parts = explode( ':', strtolower( $element ) );
$name = array_pop( $parts );
$ns = implode( ':', $parts );
return array( $ns, $name );
}
@ -1379,6 +1454,7 @@ abstract class UploadBase {
private function stripXmlNamespace( $name ) {
// 'http://www.w3.org/2000/svg:script' -> 'script'
$parts = explode( ':', strtolower( $name ) );
return array_pop( $parts );
}
@ -1399,6 +1475,7 @@ abstract class UploadBase {
if ( !$wgAntivirus ) {
wfDebug( __METHOD__ . ": virus scanner disabled\n" );
wfProfileOut( __METHOD__ );
return null;
}
@ -1407,6 +1484,7 @@ abstract class UploadBase {
$wgOut->wrapWikiMsg( "<div class=\"error\">\n$1\n</div>",
array( 'virus-badscanner', $wgAntivirus ) );
wfProfileOut( __METHOD__ );
return wfMessage( 'virus-unknownscanner' )->text() . " $wgAntivirus";
}
@ -1478,6 +1556,7 @@ abstract class UploadBase {
}
wfProfileOut( __METHOD__ );
return $output;
}
@ -1589,7 +1668,7 @@ abstract class UploadBase {
// Check for files with the same name but a different extension
$similarFiles = RepoGroup::singleton()->getLocalRepo()->findFilesByPrefix(
"{$partname}.", 1 );
"{$partname}.", 1 );
if ( count( $similarFiles ) ) {
return array(
'warning' => 'exists-normalized',
@ -1639,11 +1718,12 @@ abstract class UploadBase {
public static function isThumbName( $filename ) {
$n = strrpos( $filename, '.' );
$partname = $n ? substr( $filename, 0, $n ) : $filename;
return (
substr( $partname, 3, 3 ) == 'px-' ||
substr( $partname, 2, 3 ) == 'px-'
) &&
preg_match( "/[0-9]{2}/", substr( $partname, 0, 2 ) );
substr( $partname, 3, 3 ) == 'px-' ||
substr( $partname, 2, 3 ) == 'px-'
) &&
preg_match( "/[0-9]{2}/", substr( $partname, 0, 2 ) );
}
/**
@ -1670,6 +1750,7 @@ abstract class UploadBase {
$blacklist[] = trim( $line );
}
}
return $blacklist;
}
@ -1694,6 +1775,7 @@ abstract class UploadBase {
$imParam = ApiQueryImageInfo::getPropertyNames();
$info = ApiQueryImageInfo::getInfo( $file, array_flip( $imParam ), $result );
}
return $info;
}
@ -1704,6 +1786,7 @@ abstract class UploadBase {
public function convertVerifyErrorToStatus( $error ) {
$code = $error['status'];
unset( $code['status'] );
return Status::newFatal( $this->getVerificationErrorCode( $code ), $error );
}

View file

@ -87,6 +87,7 @@ class UploadFromChunks extends UploadFromFile {
// Update db table to reflect initial "chunk" state
$this->updateChunkStatus();
return $this->mLocalFile;
}
@ -154,6 +155,7 @@ class UploadFromChunks extends UploadFromFile {
if ( $ret['status'] !== UploadBase::OK ) {
wfDebugLog( 'fileconcatenate', "Verification failed for chunked upload" );
$status->fatal( $this->getVerificationErrorCode( $ret['status'] ) );
return $status;
}
@ -178,6 +180,7 @@ class UploadFromChunks extends UploadFromFile {
*/
public function performUpload( $comment, $pageText, $watch, $user ) {
$rv = parent::performUpload( $comment, $pageText, $watch, $user );
return $rv;
}
@ -188,11 +191,11 @@ class UploadFromChunks extends UploadFromFile {
*/
function getVirtualChunkLocation( $index ) {
return $this->repo->getVirtualUrl( 'temp' ) .
'/' .
$this->repo->getHashPath(
$this->getChunkFileKey( $index )
) .
$this->getChunkFileKey( $index );
'/' .
$this->repo->getHashPath(
$this->getChunkFileKey( $index )
) .
$this->getChunkFileKey( $index );
}
/**
@ -234,6 +237,7 @@ class UploadFromChunks extends UploadFromFile {
$status = Status::newFatal( 'invalid-chunk-offset' );
}
}
return $status;
}
@ -242,7 +246,7 @@ class UploadFromChunks extends UploadFromFile {
*/
private function updateChunkStatus() {
wfDebug( __METHOD__ . " update chunk status for {$this->mFileKey} offset:" .
$this->getOffset() . ' inx:' . $this->getChunkIndex() . "\n" );
$this->getOffset() . ' inx:' . $this->getChunkIndex() . "\n" );
$dbw = $this->repo->getMasterDb();
// Use a quick transaction since we will upload the full temp file into shared
@ -294,6 +298,7 @@ class UploadFromChunks extends UploadFromFile {
if ( $this->mChunkIndex !== null ) {
return $this->mChunkIndex;
}
return 0;
}
@ -305,6 +310,7 @@ class UploadFromChunks extends UploadFromFile {
if ( $this->mOffset !== null ) {
return $this->mOffset;
}
return 0;
}
@ -325,19 +331,20 @@ class UploadFromChunks extends UploadFromFile {
$this->repo->getZonePath( 'temp' ) . "/{$hashPath}{$fileKey}" );
// Check for error in stashing the chunk:
if ( ! $storeStatus->isOK() ) {
if ( !$storeStatus->isOK() ) {
$error = $storeStatus->getErrorsArray();
$error = reset( $error );
if ( ! count( $error ) ) {
if ( !count( $error ) ) {
$error = $storeStatus->getWarningsArray();
$error = reset( $error );
if ( ! count( $error ) ) {
if ( !count( $error ) ) {
$error = array( 'unknown', 'no error recorded' );
}
}
throw new UploadChunkFileException( "Error storing file in '$chunkPath': " .
implode( '; ', $error ) );
}
return $storeStatus;
}
@ -345,6 +352,7 @@ class UploadFromChunks extends UploadFromFile {
if ( $index === null ) {
$index = $this->getChunkIndex();
}
return $this->mFileKey . '.' . $index;
}

View file

@ -28,7 +28,6 @@
* @author Bryan Tong Minh
*/
class UploadFromFile extends UploadBase {
/**
* @var WebRequestUpload
*/

View file

@ -157,6 +157,7 @@ class UploadFromStash extends UploadBase {
// replace mLocalFile with an instance of UploadStashFile, which adds some methods
// that are useful for stashed files.
$this->mLocalFile = parent::stashFile( $user );
return $this->mLocalFile;
}
@ -187,6 +188,7 @@ class UploadFromStash extends UploadBase {
public function performUpload( $comment, $pageText, $watch, $user ) {
$rv = parent::performUpload( $comment, $pageText, $watch, $user );
$this->unsaveUploadedFile();
return $rv;
}
}

View file

@ -49,6 +49,7 @@ class UploadFromUrl extends UploadBase {
if ( !$user->isAllowed( 'upload_by_url' ) ) {
return 'upload_by_url';
}
return parent::isAllowed( $user );
}
@ -58,6 +59,7 @@ class UploadFromUrl extends UploadBase {
*/
public static function isEnabled() {
global $wgAllowCopyUploads;
return $wgAllowCopyUploads && parent::isEnabled();
}
@ -103,6 +105,7 @@ class UploadFromUrl extends UploadBase {
}
*/
}
return $valid;
}
@ -118,6 +121,7 @@ class UploadFromUrl extends UploadBase {
wfRunHooks( 'IsUploadAllowedFromUrl', array( $url, &$allowed ) );
self::$allowedUrls[$url] = $allowed;
}
return self::$allowedUrls[$url];
}
@ -169,6 +173,7 @@ class UploadFromUrl extends UploadBase {
global $wgUser;
$url = $request->getVal( 'wpUploadFileURL' );
return !empty( $url )
&& Http::isValidURI( $url )
&& $wgUser->isAllowed( 'upload_by_url' );
@ -202,6 +207,7 @@ class UploadFromUrl extends UploadBase {
if ( !$this->mAsync ) {
return $this->reallyFetchFile( $httpOptions );
}
return Status::newGood();
}
@ -213,6 +219,7 @@ class UploadFromUrl extends UploadBase {
protected function makeTemporaryFile() {
$tmpFile = TempFSFile::factory( 'URL' );
$tmpFile->bind( $this );
return $tmpFile->getPath();
}
@ -259,12 +266,12 @@ class UploadFromUrl extends UploadBase {
$this->mRemoveTempFile = true;
$this->mFileSize = 0;
$options = $httpOptions + array(
'followRedirects' => true,
);
$options = $httpOptions + array( 'followRedirects' => true );
if ( $wgCopyUploadProxy !== false ) {
$options['proxy'] = $wgCopyUploadProxy;
}
if ( $wgCopyUploadTimeout && !isset( $options['timeout'] ) ) {
$options['timeout'] = $wgCopyUploadTimeout;
}
@ -297,6 +304,7 @@ class UploadFromUrl extends UploadBase {
if ( $this->mAsync ) {
return array( 'status' => UploadBase::OK );
}
return parent::verifyUpload();
}
@ -308,8 +316,10 @@ class UploadFromUrl extends UploadBase {
public function checkWarnings() {
if ( $this->mAsync ) {
$this->mIgnoreWarnings = false;
return array();
}
return parent::checkWarnings();
}
@ -323,6 +333,7 @@ class UploadFromUrl extends UploadBase {
if ( $this->mAsync ) {
return true;
}
return parent::verifyTitlePermissions( $user );
}
@ -367,7 +378,7 @@ class UploadFromUrl extends UploadBase {
) );
$job->initializeSessionData();
JobQueueGroup::singleton()->push( $job );
return $sessionKey;
}
}

View file

@ -26,7 +26,7 @@
* - enable applications to temporarily stash files without publishing them to the wiki.
* - Several parts of MediaWiki do this in similar ways: UploadBase, UploadWizard, and FirefoggChunkedExtension
* And there are several that reimplement stashing from scratch, in idiosyncratic ways. The idea is to unify them all here.
* Mostly all of them are the same except for storing some custom fields, which we subsume into the data array.
* Mostly all of them are the same except for storing some custom fields, which we subsume into the data array.
* - enable applications to find said files later, as long as the db table or temp files haven't been purged.
* - enable the uploading user (and *ONLY* the uploading user) to access said files, and thumbnails of said files, via a URL.
* We accomplish this using a database table, with ownership checking as you might expect. See SpecialUploadStash, which
@ -42,7 +42,6 @@
* @ingroup Upload
*/
class UploadStash {
// Format of the key for files -- has to be suitable as a filename itself (e.g. ab12cd34ef.jpg)
const KEY_FORMAT_REGEX = '/^[\w-\.]+\.\w*$/';
@ -106,7 +105,7 @@ class UploadStash {
* @return UploadStashFile
*/
public function getFile( $key, $noAuth = false ) {
if ( ! preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
if ( !preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
throw new UploadStashBadPathException( "key '$key' is not in a proper format" );
}
@ -138,7 +137,7 @@ class UploadStash {
}
}
if ( ! $this->files[$key]->exists() ) {
if ( !$this->files[$key]->exists() ) {
wfDebug( __METHOD__ . " tried to get file at $key, but it doesn't exist\n" );
throw new UploadStashBadPathException( "path doesn't exist" );
}
@ -160,6 +159,7 @@ class UploadStash {
*/
public function getMetadata( $key ) {
$this->getFile( $key );
return $this->fileMetadata[$key];
}
@ -171,6 +171,7 @@ class UploadStash {
*/
public function getFileProps( $key ) {
$this->getFile( $key );
return $this->fileProps[$key];
}
@ -215,7 +216,7 @@ class UploadStash {
$this->fileProps[$key] = $fileProps;
if ( ! preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
if ( !preg_match( self::KEY_FORMAT_REGEX, $key ) ) {
throw new UploadStashBadPathException( "key '$key' is not in a proper format" );
}
@ -224,7 +225,7 @@ class UploadStash {
// if not already in a temporary area, put it there
$storeStatus = $this->repo->storeTemp( basename( $pathWithGoodExtension ), $path );
if ( ! $storeStatus->isOK() ) {
if ( !$storeStatus->isOK() ) {
// It is a convention in MediaWiki to only return one error per API exception, even if multiple errors
// are available. We use reset() to pick the "first" thing that was wrong, preferring errors to warnings.
// This is a bit lame, as we may have more info in the $storeStatus and we're throwing it away, but to fix it means
@ -232,10 +233,10 @@ class UploadStash {
// $storeStatus->value just contains the virtual URL (if anything) which is probably useless to the caller
$error = $storeStatus->getErrorsArray();
$error = reset( $error );
if ( ! count( $error ) ) {
if ( !count( $error ) ) {
$error = $storeStatus->getWarningsArray();
$error = reset( $error );
if ( ! count( $error ) ) {
if ( !count( $error ) ) {
$error = array( 'unknown', 'no error recorded' );
}
}
@ -451,6 +452,7 @@ class UploadStash {
// put it in a web accesible directory.
return '';
}
return $extension;
}
@ -502,6 +504,7 @@ class UploadStash {
throw new UploadStashZeroLengthFileException( "File is zero length" );
}
$this->files[$key] = $file;
return true;
}
}
@ -528,17 +531,17 @@ class UploadStashFile extends UnregisteredLocalFile {
if ( $repo->isVirtualUrl( $path ) ) {
$path = $repo->resolveVirtualUrl( $path );
} else {
// check if path appears to be sane, no parent traversals, and is in this repo's temp zone.
$repoTempPath = $repo->getZonePath( 'temp' );
if ( ( ! $repo->validateFilename( $path ) ) ||
( strpos( $path, $repoTempPath ) !== 0 ) ) {
if ( ( !$repo->validateFilename( $path ) ) ||
( strpos( $path, $repoTempPath ) !== 0 )
) {
wfDebug( "UploadStash: tried to construct an UploadStashFile from a file that should already exist at '$path', but path is not valid\n" );
throw new UploadStashBadPathException( 'path is not valid' );
}
// check if path exists! and is a plain file.
if ( ! $repo->fileExists( $path ) ) {
if ( !$repo->fileExists( $path ) ) {
wfDebug( "UploadStash: tried to construct an UploadStashFile from a file that should already exist at '$path', but path is not found\n" );
throw new UploadStashFileNotFoundException( 'cannot find path, or not a plain file' );
}
@ -574,6 +577,7 @@ class UploadStashFile extends UnregisteredLocalFile {
if ( $thumbName !== false ) {
$path .= "/$thumbName";
}
return $path;
}
@ -610,6 +614,7 @@ class UploadStashFile extends UnregisteredLocalFile {
*/
public function getThumbUrl( $thumbName = false ) {
wfDebug( __METHOD__ . " getting for $thumbName \n" );
return $this->getSpecialUrl( 'thumb/' . $this->getUrlName() . '/' . $thumbName );
}
@ -620,9 +625,10 @@ class UploadStashFile extends UnregisteredLocalFile {
* @return string Base url name, like '120px-123456.jpg'
*/
public function getUrlName() {
if ( ! $this->urlName ) {
if ( !$this->urlName ) {
$this->urlName = $this->fileKey;
}
return $this->urlName;
}
@ -636,6 +642,7 @@ class UploadStashFile extends UnregisteredLocalFile {
if ( !isset( $this->url ) ) {
$this->url = $this->getSpecialUrl( 'file/' . $this->getUrlName() );
}
return $this->url;
}
@ -674,15 +681,32 @@ class UploadStashFile extends UnregisteredLocalFile {
public function exists() {
return $this->repo->fileExists( $this->path );
}
}
class UploadStashException extends MWException {};
class UploadStashNotAvailableException extends UploadStashException {};
class UploadStashFileNotFoundException extends UploadStashException {};
class UploadStashBadPathException extends UploadStashException {};
class UploadStashFileException extends UploadStashException {};
class UploadStashZeroLengthFileException extends UploadStashException {};
class UploadStashNotLoggedInException extends UploadStashException {};
class UploadStashWrongOwnerException extends UploadStashException {};
class UploadStashNoSuchKeyException extends UploadStashException {};
class UploadStashException extends MWException {
}
class UploadStashNotAvailableException extends UploadStashException {
}
class UploadStashFileNotFoundException extends UploadStashException {
}
class UploadStashBadPathException extends UploadStashException {
}
class UploadStashFileException extends UploadStashException {
}
class UploadStashZeroLengthFileException extends UploadStashException {
}
class UploadStashNotLoggedInException extends UploadStashException {
}
class UploadStashWrongOwnerException extends UploadStashException {
}
class UploadStashNoSuchKeyException extends UploadStashException {
}