Merge r63621 and r63636 from REL1_16:
authorBryan Tong Minh <btongminh@users.mediawiki.org>
Fri, 12 Mar 2010 18:26:12 +0000 (18:26 +0000)
committerBryan Tong Minh <btongminh@users.mediawiki.org>
Fri, 12 Mar 2010 18:26:12 +0000 (18:26 +0000)
* Rollback chunked uploading support for 1.16
*  Pass $sessionKey as parameter to UploadFromStash::initialize.

includes/AutoLoader.php
includes/api/ApiBase.php
includes/api/ApiUpload.php
includes/upload/UploadFromChunks.php [deleted file]
includes/upload/UploadFromStash.php

index b6b6f45..be13746 100644 (file)
@@ -236,7 +236,6 @@ $wgAutoloadLocalClasses = array(
        'UploadFromStash' => 'includes/upload/UploadFromStash.php',
        'UploadFromFile' => 'includes/upload/UploadFromFile.php',
        'UploadFromUrl' => 'includes/upload/UploadFromUrl.php',
-       'UploadFromChunks' => 'includes/upload/UploadFromChunks.php',
        'User' => 'includes/User.php',
        'UserArray' => 'includes/UserArray.php',
        'UserArrayFromResult' => 'includes/UserArray.php',
index 419d64c..7fd2dcf 100644 (file)
@@ -927,8 +927,6 @@ abstract class ApiBase {
                'invalid-session-key' => array( 'code' => 'invalid-session-key', 'info' => 'Not a valid session key' ),
                'nouploadmodule' => array( 'code' => 'nouploadmodule', 'info' => 'No upload module set' ),
                'uploaddisabled' => array( 'code' => 'uploaddisabled', 'info' => 'Uploads are not enabled.  Make sure $wgEnableUploads is set to true in LocalSettings.php and the PHP ini setting file_uploads is true' ),
-               'chunked-error' => array( 'code' => 'chunked-error', 'info' => 'There was a problem initializing the chunked upload.' ),
-               'chunk-init-error' => array( 'code' => 'chunk-init-error', 'info' => 'Insufficient information for initialization.' ),
        );
 
        /**
index 585909a..e49cc96 100644 (file)
@@ -53,25 +53,9 @@ class ApiUpload extends ApiBase {
 
                // One and only one of the following parameters is needed
                $this->requireOnlyOneParameter( $this->mParams,
-                       'sessionkey', 'file', 'url', 'enablechunks' );
-
-               // Initialize $this->mUpload
-               if ( $this->mParams['enablechunks'] ) {
-                       $this->mUpload = new UploadFromChunks();
-
-                       $this->mUpload->initialize(
-                               $request->getVal( 'done', null ),
-                               $request->getVal( 'filename', null ),
-                               $request->getVal( 'chunksession', null ),
-                               $request->getFileTempName( 'chunk' ),
-                               $request->getFileSize( 'chunk' ),
-                               $request->getSessionData( 'wsUploadData' )
-                       );
-
-                       if ( !$this->mUpload->status->isOK() ) {
-                               $this->dieUsageMsg( $this->mUpload->status->getErrorsArray() );
-                       }
-               } elseif ( $this->mParams['sessionkey'] ) {
+                       'sessionkey', 'file', 'url' );
+
+               if ( $this->mParams['sessionkey'] ) {
                        /**
                         * Upload stashed in a previous request
                         */
@@ -82,6 +66,7 @@ class ApiUpload extends ApiBase {
 
                        $this->mUpload = new UploadFromStash();
                        $this->mUpload->initialize( $this->mParams['filename'],
+                               $this->mParams['sessionkey'],
                                $_SESSION['wsUploadData'][$this->mParams['sessionkey']] );
                } elseif ( isset( $this->mParams['filename'] ) ) {
                        /**
@@ -139,16 +124,7 @@ class ApiUpload extends ApiBase {
                // Cleanup any temporary mess
                $this->mUpload->cleanupTempFile();
 
-               if ( isset( $result['chunked-output'] ) ) {
-                       foreach ( $result['chunked-output'] as $key => $value ) {
-                               if ( $value === null ) {
-                                       $value = '';
-                               }
-                               $this->getResult()->addValue( null, $key, $value );
-                       }
-               } else {
-                       $this->getResult()->addValue( null, $this->getModuleName(), $result );
-               }
+               $this->getResult()->addValue( null, $this->getModuleName(), $result );
        }
 
        protected function performUpload() {
@@ -252,8 +228,6 @@ class ApiUpload extends ApiBase {
                        $this->getResult()->setIndexedTagName( $result['details'], 'error' );
 
                        $this->dieUsage( 'An internal error occurred', 'internal-error', 0, $error );
-               } elseif ( $this->mParams['enablechunks'] ) {
-                       return array( 'chunked-output' => $status->value );
                }
 
                $file = $this->mUpload->getLocalFile();
@@ -283,10 +257,6 @@ class ApiUpload extends ApiBase {
                        'watch' => false,
                        'ignorewarnings' => false,
                        'file' => null,
-                       'enablechunks' => false,
-                       'chunksession' => null,
-                       'chunk' => null,
-                       'done' => false,
                        'url' => null,
                        'sessionkey' => null,
                );
@@ -306,10 +276,6 @@ class ApiUpload extends ApiBase {
                        'watch' => 'Watch the page',
                        'ignorewarnings' => 'Ignore any warnings',
                        'file' => 'File contents',
-                       'enablechunks' => 'Set to use chunk mode; see http://firefogg.org/dev/chunk_post.html for protocol',
-                       'chunksession' => 'The session key, established on the first contact during the chunked upload',
-                       'chunk' => 'The data in this chunk of a chunked upload',
-                       'done' => 'Set to 1 on the last chunk of a chunked upload',
                        'url' => 'Url to fetch the file from',
                        'sessionkey' => array(
                                'Session key returned by a previous upload that failed due to warnings',
@@ -321,11 +287,10 @@ class ApiUpload extends ApiBase {
                return array(
                        'Upload a file, or get the status of pending uploads. Several methods are available:',
                        ' * Upload file contents directly, using the "file" parameter',
-                       ' * Upload a file in chunks, using the "enablechunks",',
                        ' * Have the MediaWiki server fetch a file from a URL, using the "url" parameter',
                        ' * Complete an earlier upload that failed due to warnings, using the "sessionkey" parameter',
                        'Note that the HTTP POST must be done as a file upload (i.e. using multipart/form-data) when',
-                       'sending the "file" or "chunk" parameters. Note also that queries using session keys must be',
+                       'sending the "file". Note also that queries using session keys must be',
                        'done in the same login session as the query that originally returned the key (i.e. do not',
                        'log out and then log back in). Also you must get and send an edit token before doing any upload stuff.'
                );
@@ -362,8 +327,6 @@ class ApiUpload extends ApiBase {
                        '    api.php?action=upload&filename=Wiki.png&url=http%3A//upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png',
                        'Complete an upload that failed due to warnings:',
                        '    api.php?action=upload&filename=Wiki.png&sessionkey=sessionkey&ignorewarnings=1',
-                       'Begin a chunked upload:',
-                       '    api.php?action=upload&filename=Wiki.png&enablechunks=1'
                );
        }
 
diff --git a/includes/upload/UploadFromChunks.php b/includes/upload/UploadFromChunks.php
deleted file mode 100644 (file)
index 4e3e1df..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-<?php
-/**
- * @file
- * @ingroup upload
- *
- * First, destination checks are made, and, if ignorewarnings is not
- * checked, errors / warning is returned.
- *
- * 1. We return the uploadUrl.
- * 2. We then accept chunk uploads from the client.
- * 3. Return chunk id on each POSTED chunk.
- * 4. Once the client posts "done=1", the files are concatenated together.
- *
- * (More info at: http://firefogg.org/dev/chunk_post.html)
- */
-class UploadFromChunks extends UploadBase {
-
-       const INIT = 1;
-       const CHUNK = 2;
-       const DONE = 3;
-
-       protected $chunkMode; // INIT, CHUNK, DONE
-       protected $sessionKey;
-       protected $comment;
-       protected $repoPath;
-       protected $pageText;
-       protected $watch;
-
-       public $status;
-
-       // Parent class requires this function even though it is only
-       // used from SpecialUpload.php and we don't do chunked uploading
-       // from SpecialUpload -- best to raise an exception for
-       // now.
-       public function initializeFromRequest( &$request ) {
-               throw new MWException( 'not implemented' );
-       }
-
-       public function initialize( $done, $filename, $sessionKey, $path, $fileSize, $sessionData ) {
-               $this->status = Status::newGood();
-
-               $this->initializePathInfo( $filename, $path, 0, true );
-               if ( $sessionKey !== null ) {
-                       $this->initFromSessionKey( $sessionKey, $sessionData, $fileSize );
-
-                       if ( $done ) {
-                               $this->chunkMode = self::DONE;
-                       } else {
-                               $this->mTempPath = $path;
-                               $this->chunkMode = self::CHUNK;
-                       }
-               } else {
-                       // session key not set, init the chunk upload system:
-                       $this->chunkMode = self::INIT;
-               }
-
-               if ( $this->status->isOk()
-                       && ( $this->mDesiredDestName === null || $this->mFileSize === null ) ) {
-                       $this->status = Status::newFatal( 'chunk-init-error' );
-               }
-       }
-
-       /**
-        * Set session information for chunked uploads and allocate a unique key.
-        * @param $comment string
-        * @param $pageText string
-        * @param $watch boolean
-        *
-        * @returns string the session key for this chunked upload
-        */
-       protected function setupChunkSession( $comment, $pageText, $watch ) {
-               if ( !isset( $this->sessionKey ) ) {
-                       $this->sessionKey = $this->getSessionKey();
-               }
-               foreach ( array( 'mFilteredName', 'repoPath', 'mFileSize', 'mDesiredDestName' )
-                               as $key ) {
-                       if ( isset( $this->$key ) ) {
-                               $_SESSION['wsUploadData'][$this->sessionKey][$key] = $this->$key;
-                       }
-               }
-               if ( isset( $comment ) ) {
-                       $_SESSION['wsUploadData'][$this->sessionKey]['commment'] = $comment;
-               }
-               if ( isset( $pageText ) ) {
-                       $_SESSION['wsUploadData'][$this->sessionKey]['pageText'] = $pageText;
-               }
-               if ( isset( $watch ) ) {
-                       $_SESSION['wsUploadData'][$this->sessionKey]['watch'] = $watch;
-               }
-               $_SESSION['wsUploadData'][$this->sessionKey]['version'] = self::SESSION_VERSION;
-
-               return $this->sessionKey;
-       }
-
-       /**
-        * Initialize a continuation of a chunked upload from a session key
-        * @param $sessionKey string
-        * @param $request WebRequest
-        * @param $fileSize int Size of this chunk
-        *
-        * @returns void
-        */
-       protected function initFromSessionKey( $sessionKey, $sessionData, $fileSize ) {
-               // testing against null because we don't want to cause obscure
-               // bugs when $sessionKey is full of "0"
-               $this->sessionKey = $sessionKey;
-
-               if ( isset( $sessionData[$this->sessionKey]['version'] )
-                       && $sessionData[$this->sessionKey]['version'] == self::SESSION_VERSION )
-               {
-                       foreach ( array( 'comment', 'pageText', 'watch', 'mFilteredName', 'repoPath', 'mFileSize', 'mDesiredDestName' )
-                                       as $key ) {
-                               if ( isset( $sessionData[$this->sessionKey][$key] ) ) {
-                                       $this->$key = $sessionData[$this->sessionKey][$key];
-                               }
-                       }
-
-                       $this->mFileSize += $fileSize;
-               } else {
-                       $this->status = Status::newFatal( 'invalid-session-key' );
-               }
-       }
-
-       /**
-        * Handle a chunk of the upload.  Overrides the parent method
-        * because Chunked Uploading clients (i.e. Firefogg) require
-        * specific API responses.
-        * @see UploadBase::performUpload
-        */
-       public function performUpload( $comment, $pageText, $watch, $user ) {
-               wfDebug( "\n\n\performUpload(chunked): comment:" . $comment . ' pageText: ' . $pageText . ' watch:' . $watch );
-               global $wgUser, $wgOut;
-
-               if ( $this->chunkMode == self::INIT ) {
-                       // firefogg expects a specific result per:
-                       // http://www.firefogg.org/dev/chunk_post.html
-
-                       // it's okay to return the token here because
-                       // a) the user must have requested the token to get here and
-                       // b) should only happen over POST
-                       // c) we need the token to validate chunks are coming from a non-xss request
-                       return Status::newGood(
-                               array( 'uploadUrl' => wfExpandUrl( wfScript( 'api' ) ) . "?" .
-                                       wfArrayToCGI( array(
-                                               'action' => 'upload',
-                                               'token' => $wgUser->editToken(),
-                                               'format' => 'json',
-                                               'filename' => $this->mDesiredDestName,
-                                               'enablechunks' => 'true',
-                                               'chunksession' =>
-                                               $this->setupChunkSession( $comment, $pageText, $watch ) ) ) ) );
-               } else if ( $this->chunkMode == self::CHUNK ) {
-                       $this->setupChunkSession();
-                       $this->appendChunk();
-                       if ( !$this->status->isOK() ) {
-                               return $this->status;
-                       }
-                       // return success:
-                       // firefogg expects a specific result
-                       // http://www.firefogg.org/dev/chunk_post.html
-                       return Status::newGood(
-                               array( 'result' => 1, 'filesize' => $this->mFileSize )
-                       );
-               } else if ( $this->chunkMode == self::DONE ) {
-                       $this->finalizeFile();
-                       // We ignore the passed-in parameters because these were set on the first contact.
-                       $status = parent::performUpload( $this->comment, $this->pageText, $this->watch, $user );
-
-                       if ( !$status->isGood() ) {
-                               return $status;
-                       }
-                       $file = $this->getLocalFile();
-
-                       // firefogg expects a specific result
-                       // http://www.firefogg.org/dev/chunk_post.html
-                       return Status::newGood(
-                               array( 'result' => 1, 'done' => 1, 'resultUrl' => wfExpandUrl( $file->getDescriptionUrl() ) )
-                       );
-               }
-
-               return Status::newGood();
-       }
-
-       /**
-        * Append a chunk to the Repo file
-        *
-        * @param string $srcPath Path to file to append from
-        * @param string $toAppendPath Path to file to append to
-        * @return Status Status
-        */
-       protected function appendToUploadFile( $srcPath, $toAppendPath ) {
-               $repo = RepoGroup::singleton()->getLocalRepo();
-               $status = $repo->append( $srcPath, $toAppendPath );
-               return $status;
-       }
-
-       /**
-        * Append a chunk to the temporary file.
-        *
-        * @return void
-        */
-       protected function appendChunk() {
-               global $wgMaxUploadSize;
-
-               if ( !$this->repoPath ) {
-                       $this->status = $this->saveTempUploadedFile( $this->mDesiredDestName, $this->mTempPath );
-
-                       if ( $this->status->isOK() ) {
-                               $this->repoPath = $this->status->value;
-                               $_SESSION['wsUploadData'][$this->sessionKey]['repoPath'] = $this->repoPath;
-                       }
-                       return;
-               }
-               if ( $this->getRealPath( $this->repoPath ) ) {
-                       $this->status = $this->appendToUploadFile( $this->repoPath, $this->mTempPath );
-
-                       if ( $this->mFileSize > $wgMaxUploadSize )
-                               $this->status = Status::newFatal( 'largefileserver' );
-
-               } else {
-                       $this->status = Status::newFatal( 'filenotfound', $this->repoPath );
-               }
-       }
-
-       /**
-        * Append the final chunk and ready file for parent::performUpload()
-        * @return void
-        */
-       protected function finalizeFile() {
-               $this->appendChunk();
-               $this->mTempPath = $this->getRealPath( $this->repoPath );
-       }
-
-       public function verifyUpload() {
-               if ( $this->chunkMode != self::DONE ) {
-                       return array( 'status' => UploadBase::OK );
-               }
-               return parent::verifyUpload();
-       }
-
-       public function checkWarnings() {
-               if ( $this->chunkMode != self::DONE ) {
-                       return null;
-               }
-               return parent::checkWarnings();
-       }
-
-       public function getImageInfo( $result ) {
-               if ( $this->chunkMode != self::DONE ) {
-                       return null;
-               }
-               return parent::getImageInfo( $result );
-       }
-}
index 37789bd..17e922b 100644 (file)
@@ -24,10 +24,8 @@ class UploadFromStash extends UploadBase {
                        $sessionData
                );
        }
-       /*
-        * some $na vars for uploadBase method compatibility.
-        */
-       public function initialize( $name, $sessionData, $na=false, $na2=false ) {
+
+       public function initialize( $name, $sessionKey, $sessionData ) {
                        /**
                         * Confirming a temporarily stashed upload.
                         * We don't want path names to be forged, so we keep
@@ -40,19 +38,20 @@ class UploadFromStash extends UploadBase {
                                $sessionData['mFileSize'],
                                false
                        );
-
+                       
+                       $this->mSessionKey = $sessionKey;
                        $this->mVirtualTempPath = $sessionData['mTempPath'];
                        $this->mFileProps = $sessionData['mFileProps'];
        }
 
        public function initializeFromRequest( &$request ) {
-               $this->mSessionKey = $request->getInt( 'wpSessionKey' );
+               $sessionKey = $request->getInt( 'wpSessionKey' );
                $sessionData = $request->getSessionData('wsUploadData');
 
                $desiredDestName = $request->getText( 'wpDestFile' );
                if( !$desiredDestName )
                        $desiredDestName = $request->getText( 'wpUploadFile' );
-               return $this->initialize( $desiredDestName, $sessionData[$this->mSessionKey], false );
+               return $this->initialize( $desiredDestName, $sessionKey, $sessionData[$sessionKey] );
        }
 
        /**