* UploadBase and subclasses are the backend of MediaWiki's file uploads.
* The frontends are formed by ApiUpload and SpecialUpload.
*
- * See also includes/docs/upload.txt
- *
* @author Brion Vibber
* @author Bryan Tong Minh
* @author Michael Dale
return array( 'uploadscripted' );
}
if ( $this->mFinalExtension == 'svg' || $mime == 'image/svg+xml' ) {
- if ( $this->detectScriptInSvg( $this->mTempPath ) ) {
+ $svgStatus = $this->detectScriptInSvg( $this->mTempPath );
+ if ( $svgStatus !== false ) {
wfProfileOut( __METHOD__ );
- return array( 'uploadscripted' );
+ return $svgStatus;
}
}
}
// Check dupes against archives
$archivedImage = new ArchivedFile( null, 0, "{$hash}.{$this->mFinalExtension}" );
if ( $archivedImage->getID() > 0 ) {
- $warnings['duplicate-archive'] = $archivedImage->getName();
+ if ( $archivedImage->userCan( File::DELETED_FILE ) ) {
+ $warnings['duplicate-archive'] = $archivedImage->getName();
+ } else {
+ $warnings['duplicate-archive'] = '';
+ }
}
wfProfileOut( __METHOD__ );
# exclamation mark, so restrict file name to 240 bytes.
if ( strlen( $this->mFilteredName ) > 240 ) {
$this->mTitleError = self::FILENAME_TOO_LONG;
- return $this->mTitle = null;
+ $this->mTitle = null;
+ return $this->mTitle;
}
/**
$nt = Title::makeTitleSafe( NS_FILE, $this->mFilteredName );
if ( is_null( $nt ) ) {
$this->mTitleError = self::ILLEGAL_FILENAME;
- return $this->mTitle = null;
+ $this->mTitle = null;
+ return $this->mTitle;
}
$this->mFilteredName = $nt->getDBkey();
if ( $this->mFinalExtension == '' ) {
$this->mTitleError = self::FILETYPE_MISSING;
- return $this->mTitle = null;
+ $this->mTitle = null;
+ return $this->mTitle;
} elseif ( $blackListedExtensions ||
( $wgCheckFileExtensions && $wgStrictFileExtensions &&
!$this->checkFileExtensionList( $ext, $wgFileExtensions ) ) ) {
$this->mBlackListedExtensions = $blackListedExtensions;
$this->mTitleError = self::FILETYPE_BADTYPE;
- return $this->mTitle = null;
+ $this->mTitle = null;
+ return $this->mTitle;
}
// Windows may be broken with special characters, see bug XXX
if ( wfIsWindows() && !preg_match( '/^[\x0-\x7f]*$/', $nt->getText() ) ) {
$this->mTitleError = self::WINDOWS_NONASCII_FILENAME;
- return $this->mTitle = null;
+ $this->mTitle = null;
+ return $this->mTitle;
}
# If there was more than one "extension", reassemble the base
if ( strlen( $partname ) < 1 ) {
$this->mTitleError = self::MIN_LENGTH_PARTNAME;
- return $this->mTitle = null;
+ $this->mTitle = null;
+ return $this->mTitle;
}
- return $this->mTitle = $nt;
+ $this->mTitle = $nt;
+ return $this->mTitle;
}
/**
/**
* @param $filename string
- * @return bool
+ * @return mixed false of the file is verified (does not contain scripts), array otherwise.
*/
protected function detectScriptInSvg( $filename ) {
- $check = new XmlTypeCheck( $filename, array( $this, 'checkSvgScriptCallback' ) );
- return $check->filterMatch;
+ $check = new XmlTypeCheck(
+ $filename,
+ array( $this, 'checkSvgScriptCallback' ),
+ true,
+ array( 'processing_instruction_handler' => 'UploadBase::checkSvgPICallback' )
+ );
+ if ( $check->wellFormed !== true ) {
+ // Invalid xml (bug 58553)
+ return array( 'uploadinvalidxml' );
+ } elseif ( $check->filterMatch ) {
+ return array( 'uploadscripted' );
+ }
+ return false;
+ }
+
+ /**
+ * Callback to filter SVG Processing Instructions.
+ * @param $target string processing instruction name
+ * @param $data string processing instruction attribute and value
+ * @return bool (true if the filter identified something bad)
+ */
+ public static function checkSvgPICallback( $target, $data ) {
+ // Don't allow external stylesheets (bug 57550)
+ if ( preg_match( '/xml-stylesheet/i', $target) ) {
+ return true;
+ }
+ return false;
}
/**