+ // Select an upload module
+ if ( !$this->selectUploadModule() ) {
+ // This is not a true upload, but a status request or similar
+ return;
+ }
+ if ( !isset( $this->mUpload ) ) {
+ $this->dieUsage( 'No upload module set', 'nomodule' );
+ }
+
+ // First check permission to upload
+ $this->checkPermissions( $wgUser );
+
+ // Fetch the file
+ $status = $this->mUpload->fetchFile();
+ if ( !$status->isGood() ) {
+ $errors = $status->getErrorsArray();
+ $error = array_shift( $errors[0] );
+ $this->dieUsage( 'Error fetching file from remote source', $error, 0, $errors[0] );
+ }
+
+ // Check if the uploaded file is sane
+ $this->verifyUpload();
+
+ // Check permission to upload this file
+ $permErrors = $this->mUpload->verifyPermissions( $wgUser );
+ if ( $permErrors !== true ) {
+ // TODO: stash the upload and allow choosing a new name
+ $this->dieUsageMsg( array( 'badaccess-groups' ) );
+ }
+
+ // Prepare the API result
+ $result = array();
+
+ $warnings = $this->getApiWarnings();
+ if ( $warnings ) {
+ $result['result'] = 'Warning';
+ $result['warnings'] = $warnings;
+ // in case the warnings can be fixed with some further user action, let's stash this upload
+ // and return a key they can use to restart it
+ try {
+ $result['sessionkey'] = $this->performStash();
+ } catch ( MWException $e ) {
+ $result['warnings']['stashfailed'] = $e->getMessage();
+ }
+ } elseif ( $this->mParams['stash'] ) {
+ // Some uploads can request they be stashed, so as not to publish them immediately.
+ // In this case, a failure to stash ought to be fatal
+ try {
+ $result['result'] = 'Success';
+ $result['sessionkey'] = $this->performStash();
+ } catch ( MWException $e ) {
+ $this->dieUsage( $e->getMessage(), 'stashfailed' );
+ }
+ } else {
+ // This is the most common case -- a normal upload with no warnings
+ // $result will be formatted properly for the API already, with a status
+ $result = $this->performUpload();
+ }
+
+ if ( $result['result'] === 'Success' ) {
+ $result['imageinfo'] = $this->mUpload->getImageInfo( $this->getResult() );
+ }
+
+ $this->getResult()->addValue( null, $this->getModuleName(), $result );
+
+ // Cleanup any temporary mess
+ $this->mUpload->cleanupTempFile();
+ }
+
+ /**
+ * Stash the file and return the session key
+ * Also re-raises exceptions with slightly more informative message strings (useful for API)
+ * @throws MWException
+ * @return {String} session key
+ */
+ function performStash() {
+ try {
+ $sessionKey = $this->mUpload->stashSessionFile()->getSessionKey();
+ } catch ( MWException $e ) {
+ throw new MWException( 'Stashing temporary file failed: ' . get_class($e) . ' ' . $e->getMessage() );
+ }
+ return $sessionKey;
+ }
+
+
+ /**
+ * Select an upload module and set it to mUpload. Dies on failure. If the
+ * request was a status request and not a true upload, returns false;
+ * otherwise true
+ *
+ * @return bool
+ */
+ protected function selectUploadModule() {
+ global $wgAllowAsyncCopyUploads;
+ $request = $this->getMain()->getRequest();
+