r55613 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r55612‎ | r55613 | r55614 >
Date:19:38, 26 August 2009
Author:btongminh
Status:ok (Comments)
Tags:
Comment:
* Cleanup ApiUpload
* UploadBase::verifyUpload now always returns a status array
* Disabled async upload by url because wfShellBackgroundExec is broken
Modified paths:
  • /trunk/phase3/includes/GlobalFunctions.php (modified) (history)
  • /trunk/phase3/includes/api/ApiBase.php (modified) (history)
  • /trunk/phase3/includes/api/ApiUpload.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialUpload.php (modified) (history)
  • /trunk/phase3/includes/upload/UploadBase.php (modified) (history)
  • /trunk/phase3/includes/upload/UploadFromChunks.php (modified) (history)
  • /trunk/phase3/includes/upload/UploadFromUrl.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/upload/UploadFromUrl.php
@@ -62,11 +62,6 @@
6363 * @param $request Object: WebRequest object
6464 */
6565 public function initializeFromRequest( &$request ) {
66 -
67 - // set dl mode if not set:
68 - if( !$this->dl_mode )
69 - $this->dl_mode = Http::SYNC_DOWNLOAD;
70 -
7166 $desiredDestName = $request->getText( 'wpDestFile' );
7267 if( !$desiredDestName )
7368 $desiredDestName = $request->getText( 'wpUploadFile' );
Index: trunk/phase3/includes/upload/UploadBase.php
@@ -18,6 +18,7 @@
1919 protected $mDesiredDestName, $mDestName, $mRemoveTempFile, $mSourceType;
2020 protected $mTitle = false, $mTitleError = 0;
2121 protected $mFilteredName, $mFinalExtension;
 22+ protected $mLocalFile;
2223
2324 const SUCCESS = 0;
2425 const OK = 0;
@@ -175,17 +176,19 @@
176177 if( $verification !== true ) {
177178 if( !is_array( $verification ) )
178179 $verification = array( $verification );
179 - $verification['status'] = self::VERIFICATION_ERROR;
180 - return $verification;
 180+ return array( 'status' => self::VERIFICATION_ERROR,
 181+ 'details' => $verification );
 182+
181183 }
182184
183185 $error = '';
184186 if( !wfRunHooks( 'UploadVerification',
185187 array( $this->mDestName, $this->mTempPath, &$error ) ) ) {
 188+ // This status needs another name...
186189 return array( 'status' => self::UPLOAD_VERIFICATION_ERROR, 'error' => $error );
187190 }
188191
189 - return self::OK;
 192+ return array( 'status' => self::OK );
190193 }
191194
192195 /**
@@ -202,7 +205,7 @@
203206
204207 #magically determine mime type
205208 $magic = MimeMagic::singleton();
206 - $mime = $magic->guessMimeType( $this->mTempFile, false );
 209+ $mime = $magic->guessMimeType( $this->mTempPath, false );
207210
208211 #check mime type, if desired
209212 global $wgVerifyMimeType;
@@ -212,11 +215,11 @@
213216 return array( 'filetype-badmime', $mime );
214217
215218 # Check IE type
216 - $fp = fopen( $this->mTempFile, 'rb' );
 219+ $fp = fopen( $this->mTempPath, 'rb' );
217220 $chunk = fread( $fp, 256 );
218221 fclose( $fp );
219222 $extMime = $magic->guessTypesForExtension( $this->mFinalExtension );
220 - $ieTypes = $magic->getIEMimeTypes( $tmpfile, $chunk, $extMime );
 223+ $ieTypes = $magic->getIEMimeTypes( $this->mTempPath, $chunk, $extMime );
221224 foreach ( $ieTypes as $ieType ) {
222225 if ( $this->checkFileExtension( $ieType, $wgMimeTypeBlacklist ) ) {
223226 return array( 'filetype-bad-ie-mime', $ieType );
@@ -225,11 +228,11 @@
226229 }
227230
228231 #check for htmlish code and javascript
229 - if( self::detectScript( $tmpfile, $mime, $this->mFinalExtension ) ) {
 232+ if( self::detectScript( $this->mTempPath, $mime, $this->mFinalExtension ) ) {
230233 return 'uploadscripted';
231234 }
232235 if( $this->mFinalExtension == 'svg' || $mime == 'image/svg+xml' ) {
233 - if( self::detectScriptInSvg( $tmpfile ) ) {
 236+ if( self::detectScriptInSvg( $this->mTempPath ) ) {
234237 return 'uploadscripted';
235238 }
236239 }
@@ -237,7 +240,7 @@
238241 /**
239242 * Scan the uploaded file for viruses
240243 */
241 - $virus = $this->detectVirus( $tmpfile );
 244+ $virus = $this->detectVirus( $this->mTempPath );
242245 if ( $virus ) {
243246 return array( 'uploadvirus', $virus );
244247 }
Index: trunk/phase3/includes/upload/UploadFromChunks.php
@@ -79,7 +79,7 @@
8080 function verifyUpload() {
8181 // no checks on chunk upload mode:
8282 if( $this->chunk_mode == UploadFromChunks::INIT )
83 - return self::OK;
 83+ return array( 'status' => self::OK );
8484
8585 // verify on init and last chunk request
8686 if( $this->chunk_mode == UploadFromChunks::CHUNK ||
Index: trunk/phase3/includes/GlobalFunctions.php
@@ -2348,6 +2348,8 @@
23492349 /**
23502350 * Executes a shell command in the background. Passes back the PID of the operation
23512351 *
 2352+ * FIXME: Does not work on Windows; does not work at all (See CodeReview r55575)
 2353+ *
23522354 * @param $cmd String
23532355 */
23542356 function wfShellBackgroundExec( $cmd ){
Index: trunk/phase3/includes/api/ApiBase.php
@@ -862,7 +862,8 @@
863863 'undo-failure' => array('code' => 'undofailure', 'info' => 'Undo failed due to conflicting intermediate edits'),
864864
865865 //uploadMsgs
866 - 'invalid-session-key' => array( 'code' => 'invalid-session-key', 'info'=>'Not a valid session key' ),
 866+ 'invalid-session-key' => array( 'code' => 'invalid-session-key', 'info' => 'Not a valid session key' ),
 867+ 'nouploadmodule' => array( 'code' => 'nouploadmodule', 'info' => 'No upload module set' ),
867868 );
868869
869870 /**
Index: trunk/phase3/includes/api/ApiUpload.php
@@ -30,7 +30,8 @@
3131 * @ingroup API
3232 */
3333 class ApiUpload extends ApiBase {
34 - var $mUpload = null;
 34+ protected $mUpload = null;
 35+ protected $mParams;
3536
3637 public function __construct( $main, $action ) {
3738 parent::__construct( $main, $action );
@@ -44,9 +45,9 @@
4546 $request = $this->getMain()->getRequest();
4647
4748 // do token checks:
48 - if( is_null( $this->mParams['token'] ) )
 49+ if ( is_null( $this->mParams['token'] ) )
4950 $this->dieUsageMsg( array( 'missingparam', 'token' ) );
50 - if( !$wgUser->matchEditToken( $this->mParams['token'] ) )
 51+ if ( !$wgUser->matchEditToken( $this->mParams['token'] ) )
5152 $this->dieUsageMsg( array( 'sessionfailure' ) );
5253
5354
@@ -54,24 +55,23 @@
5556 $this->mParams['file'] = $request->getFileName( 'file' );
5657
5758 // Check whether upload is enabled
58 - if( !UploadBase::isEnabled() )
 59+ if ( !UploadBase::isEnabled() )
5960 $this->dieUsageMsg( array( 'uploaddisabled' ) );
6061
61 - wfDebug( __METHOD__ . "running require param\n" );
6262 // One and only one of the following parameters is needed
6363 $this->requireOnlyOneParameter( $this->mParams,
6464 'sessionkey', 'file', 'url', 'enablechunks' );
6565
66 - if( $this->mParams['enablechunks'] ){
 66+ if ( $this->mParams['enablechunks'] ) {
6767 // chunks upload enabled
6868 $this->mUpload = new UploadFromChunks();
69 - $this->mUpload->initializeFromParams( $this->mParams, $request );
 69+ $status = $this->mUpload->initializeFromParams( $this->mParams, $request );
7070
71 - //if getAPIresult did not exit report the status error:
72 - if( isset( $this->mUpload->status['error'] ) )
73 - $this->dieUsageMsg( $this->mUpload->status['error'] );
 71+ if( isset( $status['error'] ) )
 72+ $this->dieUsageMsg( $status['error'] );
7473
75 - } else if( $this->mParams['internalhttpsession'] ){
 74+ } elseif ( $this->mParams['internalhttpsession'] ) {
 75+ // TODO: Move to subclass
7676 $sd = & $_SESSION['wsDownload'][ $this->mParams['internalhttpsession'] ];
7777
7878 wfDebug("InternalHTTP:: " . print_r($this->mParams, true));
@@ -83,56 +83,60 @@
8484 filesize( $sd['target_file_path'] )
8585 );
8686
87 - if( !isset( $this->mUpload ) )
88 - $this->dieUsage( 'No upload module set', 'nomodule' );
89 -
90 - } else if( $this->mParams['httpstatus'] && $this->mParams['sessionkey'] ){
 87+ } elseif ( $this->mParams['httpstatus'] && $this->mParams['sessionkey'] ) {
9188 // return the status of the given upload session_key:
92 - if( !isset( $_SESSION['wsDownload'][ $this->mParams['sessionkey'] ] ) ){
 89+
 90+ // Check the session key
 91+ if( !isset( $_SESSION['wsDownload'][$this->mParams['sessionkey']] ) )
9392 return $this->dieUsageMsg( array( 'invalid-session-key' ) );
94 - }
95 - $sd = & $_SESSION['wsDownload'][$this->mParams['sessionkey']];
 93+
 94+ $sd =& $_SESSION['wsDownload'][$this->mParams['sessionkey']];
9695 // keep passing down the upload sessionkey
9796 $statusResult = array(
9897 'upload_session_key' => $this->mParams['sessionkey']
9998 );
10099
101100 // put values into the final apiResult if available
102 - if( isset( $sd['apiUploadResult'] ) ) $statusResult['apiUploadResult'] = $sd['apiUploadResult'];
103 - if( isset( $sd['loaded'] ) ) $statusResult['loaded'] = $sd['loaded'];
104 - if( isset( $sd['content_length'] ) ) $statusResult['content_length'] = $sd['content_length'];
 101+ if( isset( $sd['apiUploadResult'] ) )
 102+ $statusResult['apiUploadResult'] = $sd['apiUploadResult'];
 103+ if( isset( $sd['loaded'] ) )
 104+ $statusResult['loaded'] = $sd['loaded'];
 105+ if( isset( $sd['content_length'] ) )
 106+ $statusResult['content_length'] = $sd['content_length'];
105107
106 - return $this->getResult()->addValue( null, $this->getModuleName(),
107 - $statusResult
108 - );
 108+ return $this->getResult()->addValue( null,
 109+ $this->getModuleName(), $statusResult);
 110+
109111 } else if( $this->mParams['sessionkey'] ) {
110112 // Stashed upload
111113 $this->mUpload = new UploadFromStash();
112 - $this->mUpload->initialize( $this->mParams['filename'], $_SESSION['wsUploadData'][$this->mParams['sessionkey']] );
 114+ $this->mUpload->initialize( $this->mParams['filename'],
 115+ $_SESSION['wsUploadData'][$this->mParams['sessionkey']] );
113116 } else {
114117 // Upload from url or file
115118 // Parameter filename is required
116 - if( !isset( $this->mParams['filename'] ) )
 119+ if ( !isset( $this->mParams['filename'] ) )
117120 $this->dieUsageMsg( array( 'missingparam', 'filename' ) );
118121
119122 // Initialize $this->mUpload
120 - if( isset( $this->mParams['file'] ) ) {
 123+ if ( isset( $this->mParams['file'] ) ) {
121124 $this->mUpload = new UploadFromFile();
122125 $this->mUpload->initialize(
123126 $request->getFileName( 'file' ),
124127 $request->getFileTempName( 'file' ),
125128 $request->getFileSize( 'file' )
126129 );
127 - } elseif( isset( $this->mParams['url'] ) ) {
128 -
 130+ } elseif ( isset( $this->mParams['url'] ) ) {
129131 $this->mUpload = new UploadFromUrl();
130 - $this->mUpload->initialize( $this->mParams['filename'], $this->mParams['url'], $this->mParams['asyncdownload'] );
 132+ $this->mUpload->initialize( $this->mParams['filename'],
 133+ $this->mParams['url'], $this->mParams['asyncdownload'] );
131134
132135 $status = $this->mUpload->fetchFile();
133136 if( !$status->isOK() ){
134137 return $this->dieUsage( 'fetchfileerror', $status->getWikiText() );
135138 }
136 - //check if we doing a async request set session info and return the upload_session_key)
 139+
 140+ // check if we doing a async request set session info and return the upload_session_key)
137141 if( $this->mUpload->isAsync() ){
138142 $upload_session_key = $status->value;
139143 // update the session with anything with the params we will need to finish up the upload later on:
@@ -159,7 +163,7 @@
160164 $this->doExecUpload();
161165 }
162166
163 - function doExecUpload(){
 167+ protected function doExecUpload(){
164168 global $wgUser;
165169 // Check whether the user has the appropriate permissions to upload anyway
166170 $permission = $this->mUpload->isAllowed( $wgUser );
@@ -177,57 +181,55 @@
178182 $this->getResult()->addValue( null, $this->getModuleName(), $result );
179183 }
180184
181 - private function performUpload() {
 185+ protected function performUpload() {
182186 global $wgUser;
183187 $result = array();
184 - $resultDetails = null;
185188 $permErrors = $this->mUpload->verifyPermissions( $wgUser );
186189 if( $permErrors !== true ) {
187 - $result['result'] = 'Failure';
188 - $result['error'] = 'permission-denied';
189 - return $result;
 190+ $this->dieUsageMsg( array( 'baddaccess-groups' ) );
190191 }
191 - $verification = $this->mUpload->verifyUpload( $resultDetails );
192 - if( $verification != UploadBase::OK ) {
 192+
 193+ // TODO: Move them to ApiBase's message map
 194+ $verification = $this->mUpload->verifyUpload();
 195+ if( $verification['status'] !== UploadBase::OK ) {
193196 $result['result'] = 'Failure';
194 - switch( $verification ) {
 197+ switch( $verification['status'] ) {
195198 case UploadBase::EMPTY_FILE:
196 - $result['error'] = 'empty-file';
 199+ $this->dieUsage( 'The file you submitted was empty', 'empty-file' );
197200 break;
198201 case UploadBase::FILETYPE_MISSING:
199 - $result['error'] = 'filetype-missing';
 202+ $this->dieUsage( 'The file is missing an extension', 'filetype-missing' );
200203 break;
201204 case UploadBase::FILETYPE_BADTYPE:
202205 global $wgFileExtensions;
203 - $result['error'] = 'filetype-banned';
204 - $result['filetype'] = $resultDetails['finalExt'];
205 - $result['allowed-filetypes'] = $wgFileExtensions;
 206+ $this->dieUsage( 'This type of file is banned', 'filetype-banned',
 207+ 0, array(
 208+ 'filetype' => $verification['finalExt'],
 209+ 'allowed' => $wgFileExtensions
 210+ ) );
206211 break;
207212 case UploadBase::MIN_LENGHT_PARTNAME:
208 - $result['error'] = 'filename-tooshort';
 213+ $this->dieUsage( 'The filename is too short', 'filename-tooshort' );
209214 break;
210215 case UploadBase::ILLEGAL_FILENAME:
211 - $result['error'] = 'illegal-filename';
212 - $result['filename'] = $resultDetails['filtered'];
 216+ $this->dieUsage( 'The filename is not allowed', 'illegal-filename',
 217+ 0, array( 'filename' => $verification['filtered'] ) );
213218 break;
214219 case UploadBase::OVERWRITE_EXISTING_FILE:
215 - $result['error'] = 'overwrite';
 220+ $this->dieUsage( 'Overwriting an existing file is not allowed', 'overwrite' );
216221 break;
217222 case UploadBase::VERIFICATION_ERROR:
218 - $result['error'] = 'verification-error';
219 - $args = $resultDetails['veri'];
220 - $code = array_shift( $args );
221 - $result['verification-error'] = $code;
222 - $result['args'] = $args;
223 - $this->getResult()->setIndexedTagName( $result['args'], 'arg' );
 223+ $this->getResult()->setIndexedTagName( $verification['details'], 'detail' );
 224+ $this->dieUsage( 'This file did not pass file verification', 'verification-error',
 225+ 0, array( 'details' => $verification['details'] ) );
224226 break;
225227 case UploadBase::UPLOAD_VERIFICATION_ERROR:
226 - $result['error'] = 'upload-verification-error';
227 - $result['upload-verification-error'] = $resultDetails['error'];
 228+ $this->dieUsage( "The modification you tried to make was aborted by an extension hook",
 229+ 'hookaborted', 0, array( 'error' => $verification['error'] ) );
228230 break;
229231 default:
230 - $result['error'] = 'unknown-error';
231 - $result['code'] = $verification;
 232+ $this->dieUsage( 'An unknown error occurred', 'unknown-error',
 233+ 0, array( 'code' => $verification['status'] ) );
232234 break;
233235 }
234236 return $result;
@@ -236,36 +238,39 @@
237239 if( !$this->mParams['ignorewarnings'] ) {
238240 $warnings = $this->mUpload->checkWarnings();
239241 if( $warnings ) {
 242+
 243+ // Add indices
240244 $this->getResult()->setIndexedTagName( $warnings, 'warning' );
241 - //also add index to duplicate:
242 - if(isset($warnings['duplicate']))
 245+
 246+ if( isset( $warnings['duplicate'] ) )
243247 $this->getResult()->setIndexedTagName( $warnings['duplicate'], 'duplicate');
244248
245 - if(isset($warnings['exists']))
246 - $this->getResult()->setIndexedTagName( $warnings['exists'], 'exists');
247 -
 249+ if( isset( $warnings['exists'] ) )
 250+ $this->getResult()->setIndexedTagName( $warnings['exists'], 'exists' );
 251+
 252+ if( isset( $warnings['filewasdeleted'] ) )
 253+ $warnings['filewasdeleted'] = $warnings['filewasdeleted']->getDBkey();
 254+
248255 $result['result'] = 'Warning';
249256 $result['warnings'] = $warnings;
250 - if( isset( $result['filewasdeleted'] ) )
251 - $result['filewasdeleted'] = $result['filewasdeleted']->getDBkey();
252257
253258 $sessionKey = $this->mUpload->stashSession();
254 - if( $sessionKey )
255 - $result['sessionkey'] = $sessionKey;
 259+ if ( !$sessionKey )
 260+ $this->dieUsage( 'Stashing temporary file failed', 'stashfailed' );
 261+ $result['sessionkey'] = $sessionKey;
256262 return $result;
257263 }
258264 }
259265
260 - // do the upload
 266+ // No errors, no warnings: do the upload
261267 $status = $this->mUpload->performUpload( $this->mParams['comment'],
262268 $this->mParams['comment'], $this->mParams['watch'], $wgUser );
263269
264270 if( !$status->isGood() ) {
265 - $result['result'] = 'Failure';
266 - $result['error'] = 'internal-error';
267 - $result['details'] = $status->getErrorsArray();
 271+ $error = $status->getErrorsArray();
268272 $this->getResult()->setIndexedTagName( $result['details'], 'error' );
269 - return $result;
 273+
 274+ $this->dieUsage( 'An internal error occurred', 'internal-error', 0, $error );
270275 }
271276
272277 $file = $this->mUpload->getLocalFile();
@@ -277,10 +282,8 @@
278283 //get all the image properties:
279284 $imParam = ApiQueryImageInfo::getPropertyNames();
280285 $result['imageinfo'] = ApiQueryImageInfo::getInfo( $file,
281 - array_flip( $imParam ),
282 - $this->getResult() );
 286+ array_flip( $imParam ), $this->getResult() );
283287
284 -
285288 return $result;
286289 }
287290
@@ -307,7 +310,7 @@
308311 'chunk' => null,
309312 'done' => false,
310313 'url' => null,
311 - 'asyncdownload' => false,
 314+ /*'asyncdownload' => false,*/ // btongminh: Disabled pending fixing wfShellBackgroundExec
312315 'httpstatus' => false,
313316 'sessionkey' => null,
314317 'internalhttpsession' => null,
Index: trunk/phase3/includes/specials/SpecialUpload.php
@@ -226,8 +226,8 @@
227227
228228 case UploadBase::VERIFICATION_ERROR:
229229 unset( $details['status'] );
230 - $code = array_shift( $details );
231 - $this->uploadError( wfMsgExt( $code, 'parseinline', $details ) );
 230+ $code = array_shift( $details['details'] );
 231+ $this->uploadError( wfMsgExt( $code, 'parseinline', $details['details'] ) );
232232 break;
233233
234234 case UploadBase::UPLOAD_VERIFICATION_ERROR:
@@ -284,7 +284,7 @@
285285
286286 // Check whether this is a sane upload
287287 $result = $this->mUpload->verifyUpload();
288 - if( $result != UploadBase::OK )
 288+ if( $result['status'] != UploadBase::OK )
289289 return $result;
290290
291291 $this->mLocalFile = $this->mUpload->getLocalFile();

Follow-up revisions

RevisionCommit summaryAuthorDate
r58549Follow-up r55613: Fix typo. I guess that 'baddaccess-groups' was a typo becau...raymond16:07, 4 November 2009

Comments

#Comment by Catrope (talk | contribs)   20:25, 26 August 2009
+			if( isset( $sd['apiUploadResult'] ) ) 
+				$statusResult['apiUploadResult'] = $sd['apiUploadResult'];
+			if( isset( $sd['loaded'] ) ) 
+				$statusResult['loaded'] = $sd['loaded'];
+			if( isset( $sd['content_length'] ) ) 
+				$statusResult['content_length'] = $sd['content_length'];

Any reason not to do $statusResult = $sd; or $statusResult += $sd;?

Otherwise, this is awesome, thanks for doing my work dude! ;)

#Comment by Bryan (talk | contribs)   20:42, 26 August 2009

You will want to filter it out so that only those parameters are returned. Could use array_intersect.

#Comment by Siebrand (talk | contribs)   14:10, 27 August 2009

Could this come from this commit? PHP Notice: Undefined property: UploadFromFile::$mLocalFile in /var/www/w/includes/upload/UploadBase.php on line 455 uploading a PDF - in this case to translatewiki.net.

#Comment by Bryan (talk | contribs)   19:24, 27 August 2009

TranslateWiki used to run r55611 according to Nikerabit. This revision has fixed this notice.

#Comment by Mdale (talk | contribs)   14:54, 27 August 2009

added wgEnableAsyncDownload configuration var in r55622 / r55623... hopefully this is just temporary while someone figures out something for windows? Or windows can just be limited to download what it can in the allocated php execution time...

#Comment by Brion VIBBER (talk | contribs)   17:28, 27 August 2009

Do we have a convenient script to test API uploads?

#Comment by Bryan (talk | contribs)   19:22, 27 August 2009

I just added upload api support to mwclient (http://mwclient.sf.net/) and the basic functionality I tested seems to work. I could hack up a test script probably.

#Comment by Bryan (talk | contribs)   20:29, 27 August 2009
#Comment by Brion VIBBER (talk | contribs)   17:49, 27 August 2009

(marking ok for now as it doesn't break regular uploads :D)

Status & tagging log