More parameter documentation
[lhc/web/wiklou.git] / includes / upload / UploadBase.php
index 68ec3e1..9549504 100644 (file)
@@ -77,21 +77,13 @@ abstract class UploadBase {
                return true;
        }
 
-       /**
-        * Returns an array of permissions that is required to upload a file
-        * 
-        * @return array
-        */
-       public static function getRequiredPermissions() {
-               return array( 'upload', 'edit' );
-       }
        /**
         * Returns true if the user can use this upload module or else a string
         * identifying the missing permission.
         * Can be overriden by subclasses.
         */
        public static function isAllowed( $user ) {
-               foreach ( self::getRequiredPermissions() as $permission ) {
+               foreach ( array( 'upload', 'edit' ) as $permission ) {
                        if ( !$user->isAllowed( $permission ) ) {
                                return $permission;
                        }
@@ -150,6 +142,14 @@ abstract class UploadBase {
        }
 
        public function __construct() {}
+       
+       /**
+        * Returns the upload type. Should be overridden by child classes
+        * 
+        * @since 1.18
+        * @return string 
+        */
+       public function getSourceType() { return null; }
 
        /**
         * Initialize the path information
@@ -234,11 +234,11 @@ abstract class UploadBase {
                /**
                 * Honor $wgMaxUploadSize
                 */
-               global $wgMaxUploadSize;
-               if( $this->mFileSize > $wgMaxUploadSize ) {
+               $maxSize = self::getMaxUploadSize( $this->getSourceType() );
+               if( $this->mFileSize > $maxSize ) {
                        return array( 
                                'status' => self::FILE_TOO_LARGE,
-                               'max' => $wgMaxUploadSize,
+                               'max' => $maxSize,
                        );
                }
 
@@ -287,6 +287,9 @@ abstract class UploadBase {
                        }
                        if ( $this->mTitleError == self::FILETYPE_BADTYPE ) {
                                $result['finalExt'] = $this->mFinalExtension;
+                               if ( count( $this->mBlackListedExtensions ) ) {
+                                       $result['blacklistedExt'] = $this->mBlackListedExtensions;
+                               }
                        }
                        return $result;
                }
@@ -305,15 +308,16 @@ abstract class UploadBase {
                global $wgVerifyMimeType;
                if ( $wgVerifyMimeType ) {
                        wfDebug ( "\n\nmime: <$mime> extension: <{$this->mFinalExtension}>\n\n");
-                       if ( !$this->verifyExtension( $mime, $this->mFinalExtension ) ) {
-                               return array( 'filetype-mime-mismatch' );
-                       }
-
                        global $wgMimeTypeBlacklist;
                        if ( $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
                                return array( 'filetype-badmime', $mime );
                        }
 
+                       # XXX: Missing extension will be caught by validateName() via getTitle()
+                       if ( $this->mFinalExtension != '' && !$this->verifyExtension( $mime, $this->mFinalExtension ) ) {
+                               return array( 'filetype-mime-mismatch', $this->mFinalExtension, $mime );
+                       }
+
                        # Check IE type
                        $fp = fopen( $this->mTempPath, 'rb' );
                        $chunk = fread( $fp, 256 );
@@ -439,8 +443,6 @@ abstract class UploadBase {
 
                $localFile = $this->getLocalFile();
                $filename = $localFile->getName();
-               $n = strrpos( $filename, '.' );
-               $partname = $n ? substr( $filename, 0, $n ) : $filename;
 
                /**
                 * Check whether the resulting filename is different from the desired one,
@@ -502,7 +504,7 @@ abstract class UploadBase {
         * Really perform the upload. Stores the file in the local repo, watches
         * if necessary and runs the UploadComplete hook.
         *
-        * @return mixed Status indicating the whether the upload succeeded.
+        * @return Status indicating the whether the upload succeeded.
         */
        public function performUpload( $comment, $pageText, $watch, $user ) {
                $status = $this->getLocalFile()->upload( 
@@ -561,17 +563,39 @@ abstract class UploadBase {
                        $this->mFinalExtension = trim( $ext[count( $ext ) - 1] );
                } else {
                        $this->mFinalExtension = '';
+                       
+                       # No extension, try guessing one
+                       $magic = MimeMagic::singleton();
+                       $mime = $magic->guessMimeType( $this->mTempPath );
+                       if ( $mime !== 'unknown/unknown' ) {
+                               # Get a space separated list of extensions
+                               $extList = $magic->getExtensionsForType( $mime );
+                               if ( $extList ) {
+                                       # Set the extension to the canonical extension
+                                       $this->mFinalExtension = strtok( $extList, ' ' );
+                                       
+                                       # Fix up the other variables
+                                       $this->mFilteredName .= ".{$this->mFinalExtension}";
+                                       $nt = Title::makeTitleSafe( NS_FILE, $this->mFilteredName );
+                                       $ext = array( $this->mFinalExtension );
+                               }
+                       }
+                       
                }
 
                /* Don't allow users to override the blacklist (check file extension) */
                global $wgCheckFileExtensions, $wgStrictFileExtensions;
                global $wgFileExtensions, $wgFileBlacklist;
+               
+               $blackListedExtensions = $this->checkFileExtensionList( $ext, $wgFileBlacklist );
+               
                if ( $this->mFinalExtension == '' ) {
                        $this->mTitleError = self::FILETYPE_MISSING;
                        return $this->mTitle = null;
-               } elseif ( $this->checkFileExtensionList( $ext, $wgFileBlacklist ) ||
+               } elseif ( $blackListedExtensions ||
                                ( $wgCheckFileExtensions && $wgStrictFileExtensions &&
                                        !$this->checkFileExtension( $this->mFinalExtension, $wgFileExtensions ) ) ) {
+                       $this->mBlackListedExtensions = $blackListedExtensions;
                        $this->mTitleError = self::FILETYPE_BADTYPE;
                        return $this->mTitle = null;
                }
@@ -633,12 +657,13 @@ abstract class UploadBase {
         * API request to find this stashed file again.
         *
         * @param $key String: (optional) the session key used to find the file info again. If not supplied, a key will be autogenerated.
-        * @return File: stashed file
+        * @return File stashed file
         */
        public function stashSessionFile( $key = null ) { 
-               $stash = new UploadStash();
+               $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash();
                $data = array( 
-                       'mFileProps' => $this->mFileProps
+                       'mFileProps' => $this->mFileProps,
+                       'mSourceType' => $this->getSourceType(),
                );
                $file = $stash->stashFile( $this->mTempPath, $data, $key );
                $this->mLocalFile = $file;
@@ -698,19 +723,14 @@ abstract class UploadBase {
 
        /**
         * Perform case-insensitive match against a list of file extensions.
-        * Returns true if any of the extensions are in the list.
+        * Returns an array of matching extensions.
         *
         * @param $ext Array
         * @param $list Array
         * @return Boolean
         */
        public static function checkFileExtensionList( $ext, $list ) {
-               foreach( $ext as $e ) {
-                       if( in_array( strtolower( $e ), $list ) ) {
-                               return true;
-                       }
-               }
-               return false;
+               return array_intersect( array_map( 'strtolower', $ext ), $list );
        }
 
        /**
@@ -1081,7 +1101,7 @@ abstract class UploadBase {
         * - File exists with normalized extension
         * - The file looks like a thumbnail and the original exists
         *
-        * @param $file The File object to check
+        * @param $file File The File object to check
         * @return mixed False if the file does not exists, else an array
         */
        public static function getExistsWarning( $file ) {
@@ -1179,9 +1199,9 @@ abstract class UploadBase {
         */
        public static function getFilenamePrefixBlacklist() {
                $blacklist = array();
-               $message = wfMsgForContent( 'filename-prefix-blacklist' );
-               if( $message && !( wfEmptyMsg( 'filename-prefix-blacklist', $message ) || $message == '-' ) ) {
-                       $lines = explode( "\n", $message );
+               $message = wfMessage( 'filename-prefix-blacklist' )->inContentLanguage();
+               if( !$message->isDisabled() ) {
+                       $lines = explode( "\n", $message->plain() );
                        foreach( $lines as $line ) {
                                // Remove comment lines
                                $comment = substr( trim( $line ), 0, 1 );
@@ -1213,13 +1233,13 @@ abstract class UploadBase {
                $file = $this->getLocalFile();
                // TODO This cries out for refactoring. We really want to say $file->getAllInfo(); here. 
                // Perhaps "info" methods should be moved into files, and the API should just wrap them in queries.
-               if ( is_a( $file, 'UploadStashFile' ) ) { 
+               if ( $file instanceof UploadStashFile ) {
                        $imParam = ApiQueryStashImageInfo::getPropertyNames();
                        $info = ApiQueryStashImageInfo::getInfo( $file, array_flip( $imParam ), $result );
                } else {
                        $imParam = ApiQueryImageInfo::getPropertyNames();
                        $info = ApiQueryImageInfo::getInfo( $file, array_flip( $imParam ), $result );
-               } 
+               }
                return $info;
        }
 
@@ -1229,4 +1249,19 @@ abstract class UploadBase {
                unset( $code['status'] );
                return Status::newFatal( $this->getVerificationErrorCode( $code ), $error );
        }
+       
+       public static function getMaxUploadSize( $forType = null ) {
+               global $wgMaxUploadSize;
+               
+               if ( is_array( $wgMaxUploadSize ) ) {
+                       if ( !is_null( $forType) && isset( $wgMaxUploadSize[$forType] ) ) {
+                               return $wgMaxUploadSize[$forType];
+                       } else {
+                               return $wgMaxUploadSize['*'];
+                       }
+               } else {
+                       return intval( $wgMaxUploadSize );
+               }
+               
+       }
 }