/** * Get an associative array containing information about * a file with the given storage path. * * Resulting array fields include: * - fileExists * - size (filesize in bytes) * - mime (as major/minor) * - media_type (value to be used with the MEDIATYPE_xxx constants) * - metadata (handler specific) * - sha1 (in base 36) * - width * - height * - bits (bitrate) * - file-mime * - major_mime * - minor_mime * * @param string $path Filesystem path to a file * @param string|bool $ext The file extension, or true to extract it from the filename. * Set it to false to ignore the extension. * @return array * @since 1.28 */ public function getPropsFromPath($path, $ext) { $fsFile = new FSFile($path); $info = $this->newPlaceholderProps(); $info['fileExists'] = $fsFile->exists(); if ($info['fileExists']) { $info['size'] = $fsFile->getSize(); // bytes $info['sha1'] = $fsFile->getSha1Base36(); # MIME type according to file contents $info['file-mime'] = $this->magic->guessMimeType($path, false); # Logical MIME type $ext = $ext === true ? FileBackend::extensionFromPath($path) : $ext; $info['mime'] = $this->magic->improveTypeFromExtension($info['file-mime'], $ext); list($info['major_mime'], $info['minor_mime']) = File::splitMime($info['mime']); $info['media_type'] = $this->magic->getMediaType($path, $info['mime']); # Height, width and metadata $handler = MediaHandler::getHandler($info['mime']); if ($handler) { $info['metadata'] = $handler->getMetadata($fsFile, $path); /** @noinspection PhpMethodParametersCountMismatchInspection */ $gis = $handler->getImageSize($fsFile, $path, $info['metadata']); if (is_array($gis)) { $info = $this->extractImageSizeInfo($gis) + $info; } } } return $info; }
/** * Get a MediaHandler instance for this file * * @return MediaHandler */ function getHandler() { if (!isset($this->handler)) { $this->handler = MediaHandler::getHandler($this->getMimeType()); } return $this->handler; }
/** * Get an associative array containing information about a file in the local filesystem. * * @param string $path Absolute local filesystem path * @param mixed $ext The file extension, or true to extract it from the filename. * Set it to false to ignore the extension. */ static function getPropsFromPath($path, $ext = true) { wfProfileIn(__METHOD__); wfDebug(__METHOD__ . ": Getting file info for {$path}\n"); $info = array('fileExists' => file_exists($path) && !is_dir($path)); $gis = false; if ($info['fileExists']) { $magic = MimeMagic::singleton(); $info['mime'] = $magic->guessMimeType($path, $ext); list($info['major_mime'], $info['minor_mime']) = self::splitMime($info['mime']); $info['media_type'] = $magic->getMediaType($path, $info['mime']); # Get size in bytes $info['size'] = filesize($path); # Height, width and metadata $handler = MediaHandler::getHandler($info['mime']); if ($handler) { $tempImage = (object) array(); $info['metadata'] = $handler->getMetadata($tempImage, $path); $gis = $handler->getImageSize($tempImage, $path, $info['metadata']); } else { $gis = false; $info['metadata'] = ''; } $info['sha1'] = self::sha1Base36($path); wfDebug(__METHOD__ . ": {$path} loaded, {$info['size']} bytes, {$info['mime']}.\n"); } else { $info['mime'] = NULL; $info['media_type'] = MEDIATYPE_UNKNOWN; $info['metadata'] = ''; $info['sha1'] = ''; wfDebug(__METHOD__ . ": {$path} NOT FOUND!\n"); } if ($gis) { # NOTE: $gis[2] contains a code for the image type. This is no longer used. $info['width'] = $gis[0]; $info['height'] = $gis[1]; if (isset($gis['bits'])) { $info['bits'] = $gis['bits']; } else { $info['bits'] = 0; } } else { $info['width'] = 0; $info['height'] = 0; $info['bits'] = 0; } wfProfileOut(__METHOD__); return $info; }
/** * Upload a file and record it in the DB * @param string $srcPath Source storage path, virtual URL, or filesystem path * @param string $comment Upload description * @param string $pageText Text to use for the new description page, * if a new description page is created * @param int|bool $flags Flags for publish() * @param array|bool $props File properties, if known. This can be used to * reduce the upload time when uploading virtual URLs for which the file * info is already known * @param string|bool $timestamp Timestamp for img_timestamp, or false to use the * current time * @param User|null $user User object or null to use $wgUser * * @return FileRepoStatus object. On success, the value member contains the * archive name, or an empty string if it was a new file. */ function upload($srcPath, $comment, $pageText, $flags = 0, $props = false, $timestamp = false, $user = null) { global $wgContLang; if ($this->getRepo()->getReadOnlyReason() !== false) { return $this->readOnlyFatalStatus(); } if (!$props) { wfProfileIn(__METHOD__ . '-getProps'); if ($this->repo->isVirtualUrl($srcPath) || FileBackend::isStoragePath($srcPath)) { $props = $this->repo->getFileProps($srcPath); } else { $props = FSFile::getPropsFromPath($srcPath); } wfProfileOut(__METHOD__ . '-getProps'); } $options = array(); $handler = MediaHandler::getHandler($props['mime']); if ($handler) { $options['headers'] = $handler->getStreamHeaders($props['metadata']); } else { $options['headers'] = array(); } // Trim spaces on user supplied text $comment = trim($comment); // truncate nicely or the DB will do it for us // non-nicely (dangling multi-byte chars, non-truncated version in cache). $comment = $wgContLang->truncate($comment, 255); $this->lock(); // begin $status = $this->publish($srcPath, $flags, $options); if ($status->successCount > 0) { # Essentially we are displacing any existing current file and saving # a new current file at the old location. If just the first succeeded, # we still need to displace the current DB entry and put in a new one. if (!$this->recordUpload2($status->value, $comment, $pageText, $props, $timestamp, $user)) { $status->fatal('filenotfound', $srcPath); } } $this->unlock(); // done return $status; }
/** * Verifies that it's ok to include the uploaded file * * @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; } $this->mFileProps = FSFile::getPropsFromPath($this->mTempPath, $this->mFinalExtension); $mime = $this->mFileProps['file-mime']; if ($wgVerifyMimeType) { # 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; }
/** * Upload a file and record it in the DB * @param string $srcPath Source storage path, virtual URL, or filesystem path * @param string $comment Upload description * @param string $pageText Text to use for the new description page, * if a new description page is created * @param int|bool $flags Flags for publish() * @param array|bool $props File properties, if known. This can be used to * reduce the upload time when uploading virtual URLs for which the file * info is already known * @param string|bool $timestamp Timestamp for img_timestamp, or false to use the * current time * @param User|null $user User object or null to use $wgUser * @param string[] $tags Change tags to add to the log entry and page revision. * (This doesn't check $user's permissions.) * @return FileRepoStatus On success, the value member contains the * archive name, or an empty string if it was a new file. */ function upload($srcPath, $comment, $pageText, $flags = 0, $props = false, $timestamp = false, $user = null, $tags = array()) { global $wgContLang; if ($this->getRepo()->getReadOnlyReason() !== false) { return $this->readOnlyFatalStatus(); } if (!$props) { if ($this->repo->isVirtualUrl($srcPath) || FileBackend::isStoragePath($srcPath)) { $props = $this->repo->getFileProps($srcPath); } else { $props = FSFile::getPropsFromPath($srcPath); } } $options = array(); $handler = MediaHandler::getHandler($props['mime']); if ($handler) { $options['headers'] = $handler->getStreamHeaders($props['metadata']); } else { $options['headers'] = array(); } // Trim spaces on user supplied text $comment = trim($comment); // Truncate nicely or the DB will do it for us // non-nicely (dangling multi-byte chars, non-truncated version in cache). $comment = $wgContLang->truncate($comment, 255); $this->lock(); // begin $status = $this->publish($srcPath, $flags, $options); if ($status->successCount >= 2) { // There will be a copy+(one of move,copy,store). // The first succeeding does not commit us to updating the DB // since it simply copied the current version to a timestamped file name. // It is only *preferable* to avoid leaving such files orphaned. // Once the second operation goes through, then the current version was // updated and we must therefore update the DB too. $oldver = $status->value; if (!$this->recordUpload2($oldver, $comment, $pageText, $props, $timestamp, $user, $tags)) { $status->fatal('filenotfound', $srcPath); } } $this->unlock(); // done return $status; }
echo " Failed to load comment file {$f}, using default comment. "; } } } if (!$commentText) { $commentText = $comment; } } # Import the file if (isset($options['dry'])) { echo " publishing {$file} by '" . $wgUser->getName() . "', comment '{$commentText}'... "; } else { $props = FSFile::getPropsFromPath($file); $flags = 0; $publishOptions = array(); $handler = MediaHandler::getHandler($props['mime']); if ($handler) { $publishOptions['headers'] = $handler->getStreamHeaders($props['metadata']); } else { $publishOptions['headers'] = array(); } $archive = $image->publish($file, $flags, $publishOptions); if (!$archive->isGood()) { echo "failed. (" . $archive->getWikiText() . ")\n"; $failed++; continue; } } $commentText = SpecialUpload::getInitialPageText($commentText, $license); if (!isset($options['summary'])) { $summary = $commentText;
/** * Get the thumbnail extension and MIME type for a given source MIME type * @return array thumbnail extension and MIME type */ static function getThumbType($ext, $mime) { $handler = MediaHandler::getHandler($mime); if ($handler) { return $handler->getThumbType($ext, $mime); } else { return array($ext, $mime); } }
/** * Verifies that it's ok to include the uploaded file * * @return mixed true of the file is verified, array otherwise. */ protected function verifyFile() { # get the title, even though we are doing nothing with it, because # we need to populate mFinalExtension $this->getTitle(); $this->mFileProps = File::getPropsFromPath($this->mTempPath, $this->mFinalExtension); $this->checkMacBinary(); # check mime type, if desired $mime = $this->mFileProps['file-mime']; $status = $this->verifyMimeType($mime); if ($status !== true) { return $status; } # check for htmlish code and javascript if (self::detectScript($this->mTempPath, $mime, $this->mFinalExtension)) { return array('uploadscripted'); } if ($this->mFinalExtension == 'svg' || $mime == 'image/svg+xml') { if ($this->detectScriptInSvg($this->mTempPath)) { return array('uploadscripted'); } } /** * Scan the uploaded file for viruses */ $virus = $this->detectVirus($this->mTempPath); if ($virus) { return array('uploadvirus', $virus); } $handler = MediaHandler::getHandler($mime); if ($handler) { $handlerStatus = $handler->verifyUpload($this->mTempPath); if (!$handlerStatus->isOK()) { $errors = $handlerStatus->getErrorsArray(); return reset($errors); } } wfRunHooks('UploadVerifyFile', array($this, $mime, &$status)); if ($status !== true) { return $status; } wfDebug(__METHOD__ . ": all clear; passing.\n"); return true; }
/** * Verifies that it's ok to include the uploaded file * * @return mixed True of the file is verified, array otherwise. */ protected function verifyFile() { global $wgVerifyMimeType, $wgDisableUploadScriptChecks; $status = $this->verifyPartialFile(); if ($status !== true) { return $status; } $mwProps = new MWFileProps(MimeMagic::singleton()); $this->mFileProps = $mwProps->getPropsFromPath($this->mTempPath, $this->mFinalExtension); $mime = $this->mFileProps['mime']; if ($wgVerifyMimeType) { # XXX: Missing extension will be caught by validateName() via getTitle() if ($this->mFinalExtension != '' && !$this->verifyExtension($mime, $this->mFinalExtension)) { return ['filetype-mime-mismatch', $this->mFinalExtension, $mime]; } } # check for htmlish code and javascript if (!$wgDisableUploadScriptChecks) { if ($this->mFinalExtension == 'svg' || $mime == 'image/svg+xml') { $svgStatus = $this->detectScriptInSvg($this->mTempPath, false); if ($svgStatus !== false) { return $svgStatus; } } } $handler = MediaHandler::getHandler($mime); if ($handler) { $handlerStatus = $handler->verifyUpload($this->mTempPath); if (!$handlerStatus->isOK()) { $errors = $handlerStatus->getErrorsArray(); return reset($errors); } } $error = true; Hooks::run('UploadVerifyFile', [$this, $mime, &$error]); if ($error !== true) { if (!is_array($error)) { $error = [$error]; } return $error; } wfDebug(__METHOD__ . ": all clear; passing.\n"); return true; }
/** * Get an associative array containing information about * a file with the given storage path. * * @param $ext Mixed: the file extension, or true to extract it from the filename. * Set it to false to ignore the extension. * * @return array */ public function getProps($ext = true) { wfProfileIn(__METHOD__); wfDebug(__METHOD__ . ": Getting file info for {$this->path}\n"); $info = self::placeholderProps(); $info['fileExists'] = $this->exists(); if ($info['fileExists']) { $magic = MimeMagic::singleton(); # get the file extension if ($ext === true) { $ext = self::extensionFromPath($this->path); } # mime type according to file contents $info['file-mime'] = $this->getMimeType(); # logical mime type $info['mime'] = $magic->improveTypeFromExtension($info['file-mime'], $ext); list($info['major_mime'], $info['minor_mime']) = File::splitMime($info['mime']); $info['media_type'] = $magic->getMediaType($this->path, $info['mime']); # Get size in bytes $info['size'] = $this->getSize(); # Height, width and metadata $handler = MediaHandler::getHandler($info['mime']); if ($handler) { $tempImage = (object) array(); $info['metadata'] = $handler->getMetadata($tempImage, $this->path); $gis = $handler->getImageSize($tempImage, $this->path, $info['metadata']); if (is_array($gis)) { $info = $this->extractImageSizeInfo($gis) + $info; } } $info['sha1'] = $this->getSha1Base36(); wfDebug(__METHOD__ . ": {$this->path} loaded, {$info['size']} bytes, {$info['mime']}.\n"); } else { wfDebug(__METHOD__ . ": {$this->path} NOT FOUND!\n"); } wfProfileOut(__METHOD__); return $info; }
static function outputHook($outputPage, $parserOutput, $data) { $instance = MediaHandler::getHandler('application/ogg'); if ($instance) { $instance->setHeaders($outputPage); } }
function execute() { global $wgUploadBaseUrl, $wgUploadPath, $wgScriptPath, $wgServer; // Determine URI if ( $_SERVER['REQUEST_URI'][0] == '/' ) { $url = ( !empty( $_SERVER['HTTPS'] ) ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; } else { $url = $_SERVER['REQUEST_URI']; } if ( $wgUploadBaseUrl ) { $thumbBase = $wgUploadBaseUrl . $wgUploadPath . '/thumb'; } else { $thumbBase = $wgServer . $wgUploadPath . '/thumb'; } if ( substr( $url, 0, strlen( $thumbBase ) ) != $thumbBase ) { // Not a thumbnail URL header( 'X-Debug: not thumb' ); $this->real404(); return true; } $rel = substr( $url, strlen( $thumbBase ) + 1 ); // plus one for slash // Check for path traversal if ( !$this->validateFilename( $rel ) ) { header( 'X-Debug: invalid path traversal' ); $this->real404(); return false; } if ( !preg_match( '!^(\w)/(\w\w)/([^/]*)/([^/]*)$!', $rel, $parts ) ) { header( 'X-Debug: regex mismatch' ); $this->real404(); return false; } list( $all, $hash1, $hash2, $filename, $thumbName ) = $parts; $srcNamePos = strrpos( $thumbName, $filename ); if ( $srcNamePos === false ) { header( 'X-Debug: filename/fn2 mismatch' ); $this->real404(); return false; } $extraExt = substr( $thumbName, $srcNamePos + strlen( $filename ) ); if ( $extraExt != '' && $extraExt[0] != '.' ) { header( "X-Debug: invalid trailing characters in filename: $extraExt" ); $this->real404(); return false; } // Determine MIME type $extPos = strrpos( $filename, '.' ); $srcExt = $extPos === false ? '' : substr( $filename, $extPos + 1 ); $magic = MimeMagic::singleton(); $mime = $magic->guessTypesForExtension( $srcExt ); $handler = MediaHandler::getHandler( $mime ); if ( !$handler ) { header( 'X-Debug: no handler' ); $this->real404(); return false; } // Parse parameter string $paramString = substr( $thumbName, 0, $srcNamePos - 1 ); $params = $handler->parseParamString( $paramString ); if ( !$params ) { header( "X-Debug: handler for $mime says param string is invalid" ); $this->real404(); return false; } // Open the destination temporary file $dstPath = "{$this->publicDir}/thumb/$rel"; $tmpPath = "$dstPath.temp.MW_WebStore"; $tmpFile = @fopen( $tmpPath, 'a+' ); if ( !$tmpFile ) { $this->htmlError( 500, 'webstore_temp_open', $tmpPath ); return false; } // Get an exclusive lock if ( !flock( $tmpFile, LOCK_EX | LOCK_NB ) ) { wfDebug( "Waiting for shared lock..." ); if ( !flock( $tmpFile, LOCK_SH ) ) { wfDebug( "failed\n" ); $this->htmlError( 500, 'webstore_temp_lock' ); return false; } wfDebug( "OK\n" ); // Close it and see if it appears at $dstPath fclose( $tmpFile ); if ( $this->windows ) { // Rename happens after unlock on windows, so we have to wait for it usleep( 200000 ); } if ( file_exists( $dstPath ) ) { // Stream it out $magic = MimeMagic::singleton(); $type = $magic->guessMimeType( $dstPath ); $dstFile = fopen( $dstPath, 'r' ); if ( !$dstFile ) { $this->htmlError( 500, 'webstore_dest_open' ); return false; } $this->streamFile( $dstFile, $type ); fclose( $dstFile ); return true; } else { // Something went wrong, only the forwarding process knows what $this->real404(); return true; } } // Send an image scaling request to a host in the scaling cluster $error = false; $errno = false; $tmpUnlinkDone = false; do { $scalerUrl = "$wgServer$wgScriptPath/extensions/WebStore/inplace-scaler.php"; // Pick a server $servers = $this->scalerServers; shuffle( $servers ); foreach( $servers as $server ) { if ( strpos( $server, ':' ) === false ) { $server .= ':80'; } $post = WebStorePostFile::post( $scalerUrl, 'data', "{$this->publicDir}/$hash1/$hash2/$filename", $params, $server, $tmpFile, $this->httpConnectTimeout, $this->httpOverallTimeout ); // Try next server unless that one was successful if ( !$post->errno ) { break; } } if ( $post->errno ) { break; } if ( $post->responseCode != 200 ) { # Pass through image scaler errors (but don't keep the file) $info = self::$httpErrors[$post->responseCode]; header( "HTTP/1.1 {$post->responseCode} $info" ); $this->streamFile( $tmpFile ); break; } fseek( $tmpFile, 0, SEEK_END ); if ( ftell( $tmpFile ) == 0 ) { $this->htmlError( 500, 'webstore_scaler_empty_response' ); break; } // Report PHP errors if ( count( $this->phpErrors ) ) { $errors = '<ul>'; foreach ( $this->phpErrors as $error ) { $errors .= "<li>$error</li>"; } $errors .= '</ul>'; $info = self::$httpErrors[500]; header( "HTTP/1.1 500 $info" ); echo $this->dtd(); $msg = wfMsgHtml( 'webstore_php_error' ); echo <<<EOT <html><head><title>500 $info</title></head> <body> <h1>500 $info</h1> <p>$msg</p> $errors </body> </html> EOT; restore_error_handler(); break; } // Request completed successfully. // Move the file to its destination if ( $this->windows ) { fclose( $tmpFile ); // Wait for other processes to close the file if rename fails for ( $i = 0; $i < 10; $i++ ) { if ( !rename( $tmpPath, $dstPath ) ) { usleep( 50000 ); } else { break; } } $tmpFile = fopen( $dstPath, 'r' ); if ( !$tmpFile ) { $this->htmlError( 500, 'webstore_dest_open' ); } $tmpUnlinkDone = true; } else { rename( $tmpPath, $dstPath ); // Unlock so that other processes can start streaming the file out flock( $tmpFile, LOCK_UN ); $tmpUnlinkDone = true; } header( "HTTP/1.1 200 OK" ); // Stream it ourselves $this->streamFile( $tmpFile, $post->contentType ); } while (false); if ( $tmpFile ) { if ( !$tmpUnlinkDone ) { $this->closeAndDelete( $tmpFile, $tmpPath ); } else { fclose( $tmpFile ); } } if ( $post->errno ) { $this->htmlError( 500, 'webstore_curl', $post->error ); return false; } return true; }
/** * sucks we have to maintain two version of Ogg doTransform but it proved difficult to integrate them. * in the future we should have a concept of "derivatives" and greatly simplify the media handlers. */ function doTransform( $file, $dstPath, $dstUrl, $params, $flags = 0 ) { global $wgEnabledDerivatives, $wgFFmpegLocation, $wgOut; $width = $params['width']; $srcWidth = $file->getWidth(); $srcHeight = $file->getHeight(); $height = $srcWidth == 0 ? $srcHeight : $width * $srcHeight / $srcWidth; $length = $this->getLength( $file ); //make sure we have all the output classes of oggHandler loaded by the autoLoader: $oggHandle = MediaHandler::getHandler( 'application/ogg' ); //add the oggHandler js: $oggHandle->setHeaders( $wgOut ); //do some arbitrary derivative selection logic: $encodeKey = WikiAtHome::getTargetDerivative($width, $file); //see if we have that encoding profile already: //get the job manager .. check status and output current state or defer to oggHanndler_body for output $wjm = WahJobManager::newFromFile( $file , $encodeKey ); //check for the derivative file: //$fTitle = Title::newFromText( $wjm->getTitle(), $wjm->getNamespace() ); //$oggFile = wfLocalFile( $fTitle ); $thumbPath = $file->getThumbPath( $wjm->getEncodeKey() ); $oggThumbUrl = $file->getThumbUrl( $wjm->getEncodeKey() . '.ogg'); //check that we have the requested theora derivative if( is_file ( "{$thumbPath}.ogg" )){ //get the thumb time: $thumbTime = false; if ( isset( $params['thumbtime'] ) ) { $thumbTime = $this->parseTimeString( $params['thumbtime'], $length ); } if ( $thumbTime === false ) { # Seek to midpoint by default, it tends to be more interesting than the start $thumbTime = $length / 2; } wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ); if(!is_file($dstPath)){ $cmd = wfEscapeShellArg( $wgFFmpegLocation ) . ' -ss ' . intval( $thumbTime ) . ' ' . ' -i ' . wfEscapeShellArg( $file->getPath() ) . # MJPEG, that's the same as JPEG except it's supported by the windows build of ffmpeg # No audio, one frame ' -f mjpeg -an -vframes 1 ' . wfEscapeShellArg( $dstPath ) . ' 2>&1'; $retval = 0; $returnText = wfShellExec( $cmd, $retval ); //if Bad file return error: if ( $this->removeBadFile( $dstPath, $retval ) || $retval ) { $lines = explode( "\n", str_replace( "\r\n", "\n", $returnText ) ); return new MediaTransformError( 'thumbnail_error', $width, $height, implode( "\n", $lines ) ); } } return new OggTransformOutput( $file, $oggThumbUrl, $dstUrl, $width, $height, $length, $dstPath, $noIcon=false, $offset=0, 0); }else{ //output our current progress return new MediaQueueTransformOutput($file, null, $width, $height, $wjm->getDonePerc() ); } }
/** * Verifies that it's ok to include the uploaded file * * @return mixed true of the file is verified, array otherwise. */ protected function verifyFile() { global $wgAllowJavaUploads, $wgDisableUploadScriptChecks; # get the title, even though we are doing nothing with it, because # we need to populate mFinalExtension $this->getTitle(); $this->mFileProps = FSFile::getPropsFromPath($this->mTempPath, $this->mFinalExtension); # check mime type, if desired $mime = $this->mFileProps['file-mime']; $status = $this->verifyMimeType($mime); if ($status !== true) { return $status; } # check for htmlish code and javascript if (!$wgDisableUploadScriptChecks) { if (self::detectScript($this->mTempPath, $mime, $this->mFinalExtension)) { return array('uploadscripted'); } if ($this->mFinalExtension == 'svg' || $mime == 'image/svg+xml') { if ($this->detectScriptInSvg($this->mTempPath)) { return array('uploadscripted'); } } } # Check for Java applets, which if uploaded can bypass cross-site # restrictions. if (!$wgAllowJavaUploads) { $this->mJavaDetected = false; $zipStatus = ZipDirectoryReader::read($this->mTempPath, array($this, 'zipEntryCallback')); if (!$zipStatus->isOK()) { $errors = $zipStatus->getErrorsArray(); $error = reset($errors); if ($error[0] !== 'zip-wrong-format') { return $error; } } if ($this->mJavaDetected) { return array('uploadjava'); } } # Scan the uploaded file for viruses $virus = $this->detectVirus($this->mTempPath); if ($virus) { return array('uploadvirus', $virus); } $handler = MediaHandler::getHandler($mime); if ($handler) { $handlerStatus = $handler->verifyUpload($this->mTempPath); if (!$handlerStatus->isOK()) { $errors = $handlerStatus->getErrorsArray(); return reset($errors); } } wfRunHooks('UploadVerifyFile', array($this, $mime, &$status)); if ($status !== true) { return $status; } wfDebug(__METHOD__ . ": all clear; passing.\n"); return true; }