]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/api/ApiUpload.php
MediaWiki 1.16.0
[autoinstallsdev/mediawiki.git] / includes / api / ApiUpload.php
1 <?php
2 /*
3  * Created on Aug 21, 2008
4  * API for MediaWiki 1.8+
5  *
6  * Copyright (C) 2008 - 2010 Bryan Tong Minh <Bryan.TongMinh@Gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  * http://www.gnu.org/copyleft/gpl.html
22  */
23
24 if ( !defined( 'MEDIAWIKI' ) ) {
25         // Eclipse helper - will be ignored in production
26         require_once( "ApiBase.php" );
27 }
28
29 /**
30  * @ingroup API
31  */
32 class ApiUpload extends ApiBase {
33         protected $mUpload = null;
34         protected $mParams;
35
36         public function __construct( $main, $action ) {
37                 parent::__construct( $main, $action );
38         }
39
40         public function execute() {
41                 global $wgUser, $wgAllowCopyUploads;
42
43                 // Check whether upload is enabled
44                 if ( !UploadBase::isEnabled() )
45                         $this->dieUsageMsg( array( 'uploaddisabled' ) );
46
47                 $this->mParams = $this->extractRequestParams();
48                 $request = $this->getMain()->getRequest();
49
50                 // Add the uploaded file to the params array
51                 $this->mParams['file'] = $request->getFileName( 'file' );
52
53                 // One and only one of the following parameters is needed
54                 $this->requireOnlyOneParameter( $this->mParams,
55                         'sessionkey', 'file', 'url' );
56
57                 if ( $this->mParams['sessionkey'] ) {
58                         /**
59                          * Upload stashed in a previous request
60                          */
61                         // Check the session key
62                         if ( !isset( $_SESSION['wsUploadData'][$this->mParams['sessionkey']] ) )
63                                 $this->dieUsageMsg( array( 'invalid-session-key' ) );
64
65                         $this->mUpload = new UploadFromStash();
66                         $this->mUpload->initialize( $this->mParams['filename'],
67                                 $this->mParams['sessionkey'],
68                                 $_SESSION['wsUploadData'][$this->mParams['sessionkey']] );
69                 } elseif ( isset( $this->mParams['filename'] ) ) {
70                         /**
71                          * Upload from url, etc
72                          * Parameter filename is required
73                          */
74
75                         if ( isset( $this->mParams['file'] ) ) {
76                                 $this->mUpload = new UploadFromFile();
77                                 $this->mUpload->initialize(
78                                         $this->mParams['filename'],
79                                         $request->getFileTempName( 'file' ),
80                                         $request->getFileSize( 'file' )
81                                 );
82                         } elseif ( isset( $this->mParams['url'] ) ) {
83                                 // make sure upload by url is enabled:
84                                 if ( !$wgAllowCopyUploads )
85                                         $this->dieUsageMsg( array( 'uploaddisabled' ) );
86
87                                 // make sure the current user can upload
88                                 if ( ! $wgUser->isAllowed( 'upload_by_url' ) )
89                                         $this->dieUsageMsg( array( 'badaccess-groups' ) );
90
91                                 $this->mUpload = new UploadFromUrl();
92                                 $this->mUpload->initialize( $this->mParams['filename'],
93                                                 $this->mParams['url'] );
94
95                                 $status = $this->mUpload->fetchFile();
96                                 if ( !$status->isOK() ) {
97                                         $this->dieUsage( $status->getWikiText(),  'fetchfileerror' );
98                                 }
99                         }
100                 } else $this->dieUsageMsg( array( 'missingparam', 'filename' ) );
101
102                 if ( !isset( $this->mUpload ) )
103                         $this->dieUsage( 'No upload module set', 'nomodule' );
104
105                 // Check whether the user has the appropriate permissions to upload anyway
106                 $permission = $this->mUpload->isAllowed( $wgUser );
107
108                 if ( $permission !== true ) {
109                         if ( !$wgUser->isLoggedIn() )
110                                 $this->dieUsageMsg( array( 'mustbeloggedin', 'upload' ) );
111                         else
112                                 $this->dieUsageMsg( array( 'badaccess-groups' ) );
113                 }
114                 // Perform the upload
115                 $result = $this->performUpload();
116
117                 // Cleanup any temporary mess
118                 $this->mUpload->cleanupTempFile();
119
120                 $this->getResult()->addValue( null, $this->getModuleName(), $result );
121         }
122
123         protected function performUpload() {
124                 global $wgUser;
125                 $result = array();
126                 $permErrors = $this->mUpload->verifyPermissions( $wgUser );
127                 if ( $permErrors !== true ) {
128                         $this->dieUsageMsg( array( 'badaccess-groups' ) );
129                 }
130
131                 // TODO: Move them to ApiBase's message map
132                 $verification = $this->mUpload->verifyUpload();
133                 if ( $verification['status'] !== UploadBase::OK ) {
134                         $result['result'] = 'Failure';
135                         switch( $verification['status'] ) {
136                                 case UploadBase::EMPTY_FILE:
137                                         $this->dieUsage( 'The file you submitted was empty', 'empty-file' );
138                                         break;
139                                 case UploadBase::FILETYPE_MISSING:
140                                         $this->dieUsage( 'The file is missing an extension', 'filetype-missing' );
141                                         break;
142                                 case UploadBase::FILETYPE_BADTYPE:
143                                         global $wgFileExtensions;
144                                         $this->dieUsage( 'This type of file is banned', 'filetype-banned',
145                                                         0, array(
146                                                                 'filetype' => $verification['finalExt'],
147                                                                 'allowed' => $wgFileExtensions
148                                                         ) );
149                                         break;
150                                 case UploadBase::MIN_LENGTH_PARTNAME:
151                                         $this->dieUsage( 'The filename is too short', 'filename-tooshort' );
152                                         break;
153                                 case UploadBase::ILLEGAL_FILENAME:
154                                         $this->dieUsage( 'The filename is not allowed', 'illegal-filename',
155                                                         0, array( 'filename' => $verification['filtered'] ) );
156                                         break;
157                                 case UploadBase::OVERWRITE_EXISTING_FILE:
158                                         $this->dieUsage( 'Overwriting an existing file is not allowed', 'overwrite' );
159                                         break;
160                                 case UploadBase::VERIFICATION_ERROR:
161                                         $this->getResult()->setIndexedTagName( $verification['details'], 'detail' );
162                                         $this->dieUsage( 'This file did not pass file verification', 'verification-error',
163                                                         0, array( 'details' => $verification['details'] ) );
164                                         break;
165                                 case UploadBase::HOOK_ABORTED:
166                                         $this->dieUsage( "The modification you tried to make was aborted by an extension hook",
167                                                         'hookaborted', 0, array( 'error' => $verification['error'] ) );
168                                         break;
169                                 default:
170                                         $this->dieUsage( 'An unknown error occurred', 'unknown-error',
171                                                         0, array( 'code' =>  $verification['status'] ) );
172                                         break;
173                         }
174                         return $result;
175                 }
176                 if ( !$this->mParams['ignorewarnings'] ) {
177                         $warnings = $this->mUpload->checkWarnings();
178                         if ( $warnings ) {
179                                 // Add indices
180                                 $this->getResult()->setIndexedTagName( $warnings, 'warning' );
181
182                                 if ( isset( $warnings['duplicate'] ) ) {
183                                         $dupes = array();
184                                         foreach ( $warnings['duplicate'] as $key => $dupe )
185                                                 $dupes[] = $dupe->getName();
186                                         $this->getResult()->setIndexedTagName( $dupes, 'duplicate' );
187                                         $warnings['duplicate'] = $dupes;
188                                 }
189
190
191                                 if ( isset( $warnings['exists'] ) ) {
192                                         $warning = $warnings['exists'];
193                                         unset( $warnings['exists'] );
194                                         $warnings[$warning['warning']] = $warning['file']->getName();
195                                 }
196
197                                 $result['result'] = 'Warning';
198                                 $result['warnings'] = $warnings;
199
200                                 $sessionKey = $this->mUpload->stashSession();
201                                 if ( !$sessionKey )
202                                         $this->dieUsage( 'Stashing temporary file failed', 'stashfailed' );
203
204                                 $result['sessionkey'] = $sessionKey;
205
206                                 return $result;
207                         }
208                 }
209
210                 // Use comment as initial page text by default
211                 if ( is_null( $this->mParams['text'] ) )
212                         $this->mParams['text'] = $this->mParams['comment'];
213
214                 // No errors, no warnings: do the upload
215                 $status = $this->mUpload->performUpload( $this->mParams['comment'],
216                         $this->mParams['text'], $this->mParams['watch'], $wgUser );
217
218                 if ( !$status->isGood() ) {
219                         $error = $status->getErrorsArray();
220                         $this->getResult()->setIndexedTagName( $result['details'], 'error' );
221
222                         $this->dieUsage( 'An internal error occurred', 'internal-error', 0, $error );
223                 }
224
225                 $file = $this->mUpload->getLocalFile();
226                 $result['result'] = 'Success';
227                 $result['filename'] = $file->getName();
228                 $result['imageinfo'] = $this->mUpload->getImageInfo( $this->getResult() );
229
230                 return $result;
231         }
232
233         public function mustBePosted() {
234                 return true;
235         }
236
237         public function isWriteMode() {
238                 return true;
239         }
240
241         public function getAllowedParams() {
242                 $params = array(
243                         'filename' => null,
244                         'comment' => array(
245                                 ApiBase::PARAM_DFLT => ''
246                         ),
247                         'text' => null,
248                         'token' => null,
249                         'watch' => false,
250                         'ignorewarnings' => false,
251                         'file' => null,
252                         'url' => null,
253                         'sessionkey' => null,
254                 );
255                 return $params;
256
257         }
258
259         public function getParamDescription() {
260                 return array(
261                         'filename' => 'Target filename',
262                         'token' => 'Edit token. You can get one of these through prop=info',
263                         'comment' => 'Upload comment. Also used as the initial page text for new files if "text" is not specified',
264                         'text' => 'Initial page text for new files',
265                         'watch' => 'Watch the page',
266                         'ignorewarnings' => 'Ignore any warnings',
267                         'file' => 'File contents',
268                         'url' => 'Url to fetch the file from',
269                         'sessionkey' => array(
270                                 'Session key returned by a previous upload that failed due to warnings',
271                         ),
272                 );
273         }
274
275         public function getDescription() {
276                 return array(
277                         'Upload a file, or get the status of pending uploads. Several methods are available:',
278                         ' * Upload file contents directly, using the "file" parameter',
279                         ' * Have the MediaWiki server fetch a file from a URL, using the "url" parameter',
280                         ' * Complete an earlier upload that failed due to warnings, using the "sessionkey" parameter',
281                         'Note that the HTTP POST must be done as a file upload (i.e. using multipart/form-data) when',
282                         'sending the "file". Note also that queries using session keys must be',
283                         'done in the same login session as the query that originally returned the key (i.e. do not',
284                         'log out and then log back in). Also you must get and send an edit token before doing any upload stuff.'
285                 );
286         }
287         
288     public function getPossibleErrors() {
289                 return array_merge( parent::getPossibleErrors(), array(
290                         array( 'uploaddisabled' ),
291                         array( 'invalid-session-key' ),
292                         array( 'uploaddisabled' ),
293                         array( 'badaccess-groups' ),
294                         array( 'missingparam', 'filename' ),
295                         array( 'mustbeloggedin', 'upload' ),
296                         array( 'badaccess-groups' ),
297                         array( 'badaccess-groups' ),
298                         array( 'code' => 'fetchfileerror', 'info' => '' ),
299                         array( 'code' => 'nomodule', 'info' => 'No upload module set' ),
300                         array( 'code' => 'empty-file', 'info' => 'The file you submitted was empty' ),
301                         array( 'code' => 'filetype-missing', 'info' => 'The file is missing an extension' ),
302                         array( 'code' => 'filename-tooshort', 'info' => 'The filename is too short' ),
303                         array( 'code' => 'overwrite', 'info' => 'Overwriting an existing file is not allowed' ),
304                         array( 'code' => 'stashfailed', 'info' => 'Stashing temporary file failed' ),
305                         array( 'code' => 'internal-error', 'info' => 'An internal error occurred' ),
306         ) );
307         }
308         
309         public function getTokenSalt() {
310                 return '';
311         }
312
313         protected function getExamples() {
314                 return array(
315                         'Upload from a URL:',
316                         '    api.php?action=upload&filename=Wiki.png&url=http%3A//upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png',
317                         'Complete an upload that failed due to warnings:',
318                         '    api.php?action=upload&filename=Wiki.png&sessionkey=sessionkey&ignorewarnings=1',
319                 );
320         }
321
322         public function getVersion() {
323                 return __CLASS__ . ': $Id: ApiUpload.php 51812 2009-06-12 23:45:20Z dale $';
324         }
325 }