BUG#1402 Make link color of tab subject page link on talk page indicate whether artic...
[lhc/web/wiklou.git] / includes / SpecialUpload.php
index 5a01331..1ac4a48 100644 (file)
@@ -32,7 +32,7 @@ class UploadForm {
        var $mUploadSaveName, $mUploadTempName, $mUploadSize, $mUploadOldVersion;
        var $mUploadCopyStatus, $mUploadSource, $mReUpload, $mAction, $mUpload;
        var $mOname, $mSessionKey;
-       /**#@- */
+       /**#@-*/
 
        /**
         * Constructor : initialise object
@@ -127,6 +127,13 @@ class UploadForm {
                global $wgUploadDirectory;
                global $wgUseCopyrightUpload, $wgCheckCopyrightUpload;
 
+               /**
+                * If there was no filename or a zero size given, give up quick.
+                */
+               if( ( trim( $this->mOname ) == '' ) || empty( $this->mUploadSize ) ) {
+                       return $this->mainUploadForm('<li>'.wfMsg( 'emptyfile' ).'</li>');
+               }
+               
                /**
                 * When using detailed copyright, if user filled field, assume he
                 * confirmed the upload
@@ -142,26 +149,25 @@ class UploadForm {
 
                /** User need to confirm his upload */
                if( !$this->mUploadAffirm ) {
-                       $this->mainUploadForm( WfMsg( 'noaffirmation' ) );
+                       $this->mainUploadForm( wfMsg( 'noaffirmation' ) );
                        return;
                }
 
-               if ( $this->mOname == '' && !isset($this->mUploadSaveName) ) {
-                       // no filename given!
-                       return $this->uploadError('<li>'.wfMsg( 'emptyfile' ).'</li>');
-               }
-               
                # Chop off any directories in the given filename
                $basename = basename( $this->mOname );
 
-               if( preg_match( '/^(.*)\.([^.]*)$/', $basename, $matches ) ) {
-                       $partname = $matches[1];
-                       $ext      = $matches[2];
+               /**
+                * We'll want to blacklist against *any* 'extension', and use
+                * only the final one for the whitelist.
+                */
+               list( $partname, $ext ) = $this->splitExtensions( $basename );
+               if( count( $ext ) ) {
+                       $finalExt = $ext[count( $ext ) - 1];
                } else {
-                   $partname = $basename;
-                   $ext = '';
+                       $finalExt = '';
                }
-
+               $fullExt = implode( '.', $ext );
+               
                if ( strlen( $partname ) < 3 ) {
                        $this->mainUploadForm( wfMsg( 'minlength' ) );
                        return;
@@ -171,12 +177,12 @@ class UploadForm {
                 * Filter out illegal characters, and try to make a legible name
                 * out of it. We'll strip some silently that Title would die on.
                 */
-               $filtered = preg_replace ( "/[^".Title::legalChars()."]/", '-', $basename );
+               $filtered = preg_replace ( "/[^".Title::legalChars()."]|:/", '-', $basename );
                $nt = Title::newFromText( $filtered );
                if( is_null( $nt ) ) {
                        return $this->uploadError( wfMsg( 'illegalfilename', htmlspecialchars( $filtered ) ) );
                }
-               $nt->setNamespace( NS_IMAGE );
+               $nt =& Title::makeTitle( NS_IMAGE, $nt->getDBkey() );
                $this->mUploadSaveName = $nt->getDBkey();
                
                /**
@@ -190,9 +196,10 @@ class UploadForm {
                /* Don't allow users to override the blacklist */
                global $wgStrictFileExtensions;
                global $wgFileExtensions, $wgFileBlacklist;
-               if( $this->checkFileExtension( $ext, $wgFileBlacklist ) ||
-                       ($wgStrictFileExtensions && !$this->checkFileExtension( $ext, $wgFileExtensions ) ) ) {
-                       return $this->uploadError( wfMsg( 'badfiletype', htmlspecialchars( $ext ) ) );
+               if( $this->checkFileExtensionList( $ext, $wgFileBlacklist ) ||
+                       ($wgStrictFileExtensions &&
+                               !$this->checkFileExtension( $finalExt, $wgFileExtensions ) ) ) {
+                       return $this->uploadError( wfMsg( 'badfiletype', htmlspecialchars( $fullExt ) ) );
                }
                
                /**
@@ -200,7 +207,7 @@ class UploadForm {
                 * type but it's corrupt or data of the wrong type, we should
                 * probably not accept it.
                 */
-               if( !$this->verify( $this->mUploadTempName, $ext ) ) {
+               if( !$this->verify( $this->mUploadTempName, $finalExt ) ) {
                        return $this->uploadError( wfMsg( 'uploadcorrupt' ) );
                }
                
@@ -215,8 +222,8 @@ class UploadForm {
        
                        global $wgCheckFileExtensions;
                        if ( $wgCheckFileExtensions ) {
-                               if ( ! $this->checkFileExtension( $ext, $wgFileExtensions ) ) {
-                                       $warning .= '<li>'.wfMsg( 'badfiletype', htmlspecialchars( $ext ) ).'</li>';
+                               if ( ! $this->checkFileExtension( $finalExt, $wgFileExtensions ) ) {
+                                       $warning .= '<li>'.wfMsg( 'badfiletype', htmlspecialchars( $fullExt ) ).'</li>';
                                }
                        }
        
@@ -401,7 +408,7 @@ class UploadForm {
                global $wgOut;
                $sub = wfMsg( 'uploadwarning' );
                $wgOut->addHTML( "<h2>{$sub}</h2>\n" );
-               $wgOut->addHTML( "<h4 style='error'>{$error}</h4>\n" );
+               $wgOut->addHTML( "<h4 class='error'>{$error}</h4>\n" );
        }
 
        /**
@@ -449,6 +456,7 @@ class UploadForm {
        <input type=hidden name=\"wpUploadAffirm\" value=\"1\" />
        <input type=hidden name=\"wpIgnoreWarning\" value=\"1\" />
        <input type=hidden name=\"wpSessionKey\" value=\"" . htmlspecialchars( $this->mSessionKey ) . "\" />
+       <input type=hidden name=\"wpUploadDescription\" value=\"" . htmlspecialchars( $this->mUploadDescription ) . "\" />
        {$copyright}
        <table border='0'><tr>
        <tr><td align='right'>
@@ -473,7 +481,7 @@ class UploadForm {
                if ( '' != $msg ) {
                        $sub = wfMsg( 'uploaderror' );
                        $wgOut->addHTML( "<h2>{$sub}</h2>\n" .
-                         "<h4 style='error'>{$msg}</h4>\n" );
+                         "<h4 class='error'>{$msg}</h4>\n" );
                } else {
                        $sub = wfMsg( 'uploadfile' );
                        $wgOut->addHTML( "<h2>{$sub}</h2>\n" );
@@ -531,6 +539,20 @@ class UploadForm {
        
        /* -------------------------------------------------------------- */
 
+       /**
+        * Split a file into a base name and all dot-delimited 'extensions'
+        * on the end. Some web server configurations will fall back to
+        * earlier pseudo-'extensions' to determine type and execute
+        * scripts, so the blacklist needs to check them all.
+        *
+        * @return array
+        */
+       function splitExtensions( $filename ) {
+               $bits = explode( '.', $filename );
+               $basename = array_shift( $bits );
+               return array( $basename, $bits );
+       }
+       
        /**
         * Perform case-insensitive match against a list of file extensions.
         * Returns true if the extension is in the list.
@@ -543,6 +565,23 @@ class UploadForm {
                return in_array( strtolower( $ext ), $list );
        }
 
+       /**
+        * Perform case-insensitive match against a list of file extensions.
+        * Returns true if any of the extensions are in the list.
+        *
+        * @param array $ext
+        * @param array $list
+        * @return bool
+        */
+       function checkFileExtensionList( $ext, $list ) {
+               foreach( $ext as $e ) {
+                       if( in_array( strtolower( $e ), $list ) ) {
+                               return true;
+                       }
+               }
+               return false;
+       }
+       
        /**
         * Returns false if the file is of a known type but can't be recognized,
         * indicating a corrupt file.