Go to the documentation of this file.
42 $request = $this->
getMain()->getRequest();
44 $this->mParams[
'async'] = ( $this->mParams[
'async'] &&
45 $this->
getConfig()->get(
'EnableAsyncUploads' ) );
47 $this->mParams[
'file'] = $request->getFileName(
'file' );
48 $this->mParams[
'chunk'] = $request->getFileName(
'chunk' );
51 if ( !$this->mParams[
'filekey'] && $this->mParams[
'sessionkey'] ) {
52 $this->mParams[
'filekey'] = $this->mParams[
'sessionkey'];
59 } elseif ( !isset( $this->mUpload ) ) {
60 $this->
dieDebug( __METHOD__,
'No upload module set' );
71 $status = $this->mUpload->fetchFile();
72 if ( !$status->isGood() ) {
77 if ( $this->mParams[
'chunk'] ) {
79 if ( $this->mParams[
'filesize'] > $maxSize ) {
82 if ( !$this->mUpload->getTitle() ) {
85 } elseif ( $this->mParams[
'async'] && $this->mParams[
'filekey'] ) {
88 wfDebug( __METHOD__ .
" about to verify\n" );
95 if ( !$this->mParams[
'stash'] ) {
96 $permErrors = $this->mUpload->verifyTitlePermissions( $user );
97 if ( $permErrors !==
true ) {
112 if ( $result[
'result'] ===
'Success' ) {
113 $imageinfo = $this->mUpload->getImageInfo( $this->
getResult() );
118 $this->mUpload->cleanupTempFile();
127 if ( $warnings && !$this->mParams[
'ignorewarnings'] ) {
130 } elseif ( $this->mParams[
'chunk'] ) {
133 } elseif ( $this->mParams[
'stash'] ) {
156 $result[
'result'] =
'Success';
157 if ( $warnings && count( $warnings ) > 0 ) {
158 $result[
'warnings'] = $warnings;
174 $result[
'result'] =
'Warning';
175 $result[
'warnings'] = $warnings;
191 if ( $warnings && count( $warnings ) > 0 ) {
192 $result[
'warnings'] = $warnings;
195 $request = $this->
getMain()->getRequest();
196 $chunkPath = $request->getFileTempname(
'chunk' );
197 $chunkSize = $request->getUpload(
'chunk' )->getSize();
198 $totalSoFar = $this->mParams[
'offset'] + $chunkSize;
199 $minChunkSize = $this->
getConfig()->get(
'MinUploadChunkSize' );
202 if ( $totalSoFar > $this->mParams[
'filesize'] ) {
207 if ( $totalSoFar != $this->mParams[
'filesize'] && $chunkSize < $minChunkSize ) {
211 if ( $this->mParams[
'offset'] == 0 ) {
214 $filekey = $this->mParams[
'filekey'];
220 $this->
dieWithError(
'apierror-stashfailed-nosession',
'stashfailed' );
221 } elseif ( $progress[
'result'] !==
'Continue' || $progress[
'stage'] !==
'uploading' ) {
222 $this->
dieWithError(
'apierror-stashfailed-complete',
'stashfailed' );
225 $status = $this->mUpload->addChunk(
226 $chunkPath, $chunkSize, $this->mParams[
'offset'] );
227 if ( !$status->isGood() ) {
229 'offset' => $this->mUpload->getOffset(),
237 if ( $totalSoFar == $this->mParams[
'filesize'] ) {
238 if ( $this->mParams[
'async'] ) {
242 [
'result' =>
'Poll',
248 'filename' => $this->mParams[
'filename'],
249 'filekey' => $filekey,
253 $result[
'result'] =
'Poll';
254 $result[
'stage'] =
'queued';
256 $status = $this->mUpload->concatenateChunks();
257 if ( !$status->isGood() ) {
261 [
'result' =>
'Failure',
'stage' =>
'assembling',
'status' => $status ]
269 $result[
'warnings'] = $warnings;
275 $this->mUpload->stash->removeFile( $filekey );
276 $filekey = $this->mUpload->getStashFile()->getFileKey();
278 $result[
'result'] =
'Success';
285 'result' =>
'Continue',
286 'stage' =>
'uploading',
287 'offset' => $totalSoFar,
291 $result[
'result'] =
'Continue';
292 $result[
'offset'] = $totalSoFar;
295 $result[
'filekey'] = $filekey;
313 $isPartial = (bool)$this->mParams[
'chunk'];
315 $status = $this->mUpload->tryStashFile( $this->
getUser(), $isPartial );
317 if ( $status->isGood() && !$status->getValue() ) {
319 $status->fatal(
new ApiMessage(
'apierror-stashinvalidfile',
'stashfailed' ) );
321 }
catch ( Exception $e ) {
322 $debugMessage =
'Stashing temporary file failed: ' . get_class( $e ) .
' ' . $e->getMessage();
323 wfDebug( __METHOD__ .
' ' . $debugMessage .
"\n" );
325 $e, [
'wrap' =>
new ApiMessage(
'apierror-stashexception',
'stashfailed' ) ]
329 if ( $status->isGood() ) {
330 $stashFile = $status->getValue();
331 $data[
'filekey'] = $stashFile->getFileKey();
333 $data[
'sessionkey'] = $data[
'filekey'];
334 return $data[
'filekey'];
337 if ( $status->getMessage()->getKey() ===
'uploadstash-exception' ) {
340 list( $exceptionType, $message ) = $status->getMessage()->getParams();
341 $debugMessage =
'Stashing temporary file failed: ' . $exceptionType .
' ' . $message;
342 wfDebug( __METHOD__ .
' ' . $debugMessage .
"\n" );
346 if ( $failureMode !==
'optional' ) {
367 $data[
'invalidparameter'] = $parameter;
371 foreach ( $errors as $error ) {
373 $msg->setApiData( $msg->getApiData() + $data );
390 foreach ( $status->getErrors() as $error ) {
392 if ( $moreExtraData ) {
393 $msg->setApiData( $msg->getApiData() + $moreExtraData );
408 $request = $this->
getMain()->getRequest();
411 if ( !$this->mParams[
'chunk'] ) {
413 'filekey',
'file',
'url' );
417 if ( $this->mParams[
'filekey'] && $this->mParams[
'checkstatus'] ) {
420 $this->
dieWithError(
'apierror-upload-missingresult',
'missingresult' );
421 } elseif ( !$progress[
'status']->isGood() ) {
424 if ( isset( $progress[
'status']->value[
'verification'] ) ) {
427 if ( isset( $progress[
'status']->value[
'warnings'] ) ) {
430 $progress[
'warnings'] = $warnings;
433 unset( $progress[
'status'] );
435 if ( isset( $progress[
'imageinfo'] ) ) {
436 $imageinfo = $progress[
'imageinfo'];
437 unset( $progress[
'imageinfo'] );
451 if ( is_null( $this->mParams[
'filename'] ) ) {
452 $this->
dieWithError( [
'apierror-missingparam',
'filename' ] );
455 if ( $this->mParams[
'chunk'] ) {
458 if ( isset( $this->mParams[
'filekey'] ) ) {
459 if ( $this->mParams[
'offset'] === 0 ) {
460 $this->
dieWithError(
'apierror-upload-filekeynotallowed',
'filekeynotallowed' );
464 $this->mUpload->continueChunks(
465 $this->mParams[
'filename'],
466 $this->mParams[
'filekey'],
467 $request->getUpload(
'chunk' )
470 if ( $this->mParams[
'offset'] !== 0 ) {
471 $this->
dieWithError(
'apierror-upload-filekeyneeded',
'filekeyneeded' );
475 $this->mUpload->initialize(
476 $this->mParams[
'filename'],
477 $request->getUpload(
'chunk' )
480 } elseif ( isset( $this->mParams[
'filekey'] ) ) {
489 $this->mUpload->initialize(
490 $this->mParams[
'filekey'], $this->mParams[
'filename'], !$this->mParams[
'async']
492 } elseif ( isset( $this->mParams[
'file'] ) ) {
496 if ( $this->mParams[
'async'] ) {
497 $this->
dieWithError(
'apierror-cannot-async-upload-file' );
501 $this->mUpload->initialize(
502 $this->mParams[
'filename'],
503 $request->getUpload(
'file' )
505 } elseif ( isset( $this->mParams[
'url'] ) ) {
520 $this->mUpload->
initialize( $this->mParams[
'filename'],
521 $this->mParams[
'url'] );
534 $permission = $this->mUpload->isAllowed( $user );
536 if ( $permission !==
true ) {
537 if ( !$user->isLoggedIn() ) {
538 $this->
dieWithError( [
'apierror-mustbeloggedin', $this->
msg(
'action-upload' ) ] );
545 if ( $user->isBlockedFromUpload() ) {
550 if ( $user->isBlockedGlobally() ) {
559 $verification = $this->mUpload->verifyUpload();
572 switch ( $verification[
'status'] ) {
580 'illegal-filename',
null, [
'filename' => $verification[
'filtered'] ]
604 'filetype' => $verification[
'finalExt'],
605 'allowed' => array_values( array_unique( $this->
getConfig()->
get(
'FileExtensions' ) ) )
607 $extensions = array_unique( $this->
getConfig()->
get(
'FileExtensions' ) );
609 'filetype-banned-type',
612 count( $extensions ),
617 if ( isset( $verification[
'blacklistedExt'] ) ) {
619 $msg[4] = count( $verification[
'blacklistedExt'] );
620 $extradata[
'blacklisted'] = array_values( $verification[
'blacklistedExt'] );
623 $msg[1] = $verification[
'finalExt'];
627 $this->
dieWithError( $msg,
'filetype-banned', $extradata );
633 $details = array_merge( [ $msg->getKey() ], $msg->getParams() );
635 $details = $verification[
'details'];
638 $msg->setApiData( $msg->getApiData() + [
'details' => $details ] );
644 $msg = $verification[
'error'] ===
'' ?
'hookaborted' : $verification[
'error'];
645 $this->
dieWithError( $msg,
'hookaborted', [
'details' => $verification[
'error'] ] );
648 $this->
dieWithError(
'apierror-unknownerror-nocode',
'unknown-error',
649 [
'details' => [
'code' => $verification[
'status'] ] ] );
672 if ( isset( $warnings[
'duplicate'] ) ) {
674 foreach ( $warnings[
'duplicate'] as $dupe ) {
675 $dupes[] = $dupe[
'fileName'];
678 $warnings[
'duplicate'] = $dupes;
681 if ( isset( $warnings[
'exists'] ) ) {
682 $warning = $warnings[
'exists'];
683 unset( $warnings[
'exists'] );
684 $localFile = $warning[
'normalizedFile'] ?? $warning[
'file'];
685 $warnings[$warning[
'warning']] = $localFile[
'fileName'];
688 if ( isset( $warnings[
'no-change'] ) ) {
689 $file = $warnings[
'no-change'];
690 unset( $warnings[
'no-change'] );
692 $warnings[
'nochange'] = [
697 if ( isset( $warnings[
'duplicate-version'] ) ) {
699 foreach ( $warnings[
'duplicate-version'] as $dupe ) {
701 'timestamp' =>
wfTimestamp( TS_ISO_8601, $dupe[
'timestamp'] )
704 unset( $warnings[
'duplicate-version'] );
707 $warnings[
'duplicateversions'] = $dupes;
721 switch ( get_class( $e ) ) {
722 case UploadStashFileNotFoundException::class:
723 $wrap =
'apierror-stashedfilenotfound';
725 case UploadStashBadPathException::class:
726 $wrap =
'apierror-stashpathinvalid';
728 case UploadStashFileException::class:
729 $wrap =
'apierror-stashfilestorage';
731 case UploadStashZeroLengthFileException::class:
732 $wrap =
'apierror-stashzerolength';
734 case UploadStashNotLoggedInException::class:
736 [
'apierror-mustbeloggedin', $this->
msg(
'action-upload' ) ],
'stashnotloggedin'
738 case UploadStashWrongOwnerException::class:
739 $wrap =
'apierror-stashwrongowner';
741 case UploadStashNoSuchKeyException::class:
742 $wrap =
'apierror-stashnosuchfilekey';
745 $wrap = [
'uploadstash-exception', get_class( $e ) ];
762 if ( is_null( $this->mParams[
'text'] ) ) {
763 $this->mParams[
'text'] = $this->mParams[
'comment'];
767 $file = $this->mUpload->getLocalFile();
775 $this->mParams[
'watchlist'],
$file->getTitle(),
'watchdefault'
778 if ( !$watch && $this->mParams[
'watchlist'] ==
'preferences' && !
$file->exists() ) {
786 if ( $this->mParams[
'watch'] ) {
790 if ( $this->mParams[
'tags'] ) {
792 if ( !$status->isOK() ) {
799 if ( $this->mParams[
'async'] ) {
801 if ( $progress && $progress[
'result'] ===
'Poll' ) {
802 $this->
dieWithError(
'apierror-upload-inprogress',
'publishfailed' );
806 $this->mParams[
'filekey'],
807 [
'result' =>
'Poll',
'stage' =>
'queued',
'status' =>
Status::newGood() ]
812 'filename' => $this->mParams[
'filename'],
813 'filekey' => $this->mParams[
'filekey'],
814 'comment' => $this->mParams[
'comment'],
815 'tags' => $this->mParams[
'tags'],
816 'text' => $this->mParams[
'text'],
821 $result[
'result'] =
'Poll';
822 $result[
'stage'] =
'queued';
825 $status = $this->mUpload->performUpload( $this->mParams[
'comment'],
826 $this->mParams[
'text'], $watch, $this->
getUser(), $this->mParams[
'tags'] );
828 if ( !$status->isGood() ) {
831 $result[
'result'] =
'Success';
834 $result[
'filename'] =
$file->getName();
835 if ( $warnings && count( $warnings ) > 0 ) {
836 $result[
'warnings'] = $warnings;
877 'ignorewarnings' =>
false,
902 'checkstatus' =>
false,
914 'action=upload&filename=Wiki.png' .
915 '&url=http%3A//upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png&token=123ABC'
916 =>
'apihelp-upload-example-url',
917 'action=upload&filename=Wiki.png&filekey=filekey&ignorewarnings=1&token=123ABC'
918 =>
'apihelp-upload-example-filekey',
923 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Upload';
getChunkResult( $warnings)
Get the result of a chunk upload.
selectUploadModule()
Select an upload module and set it to mUpload.
getContext()
Get the base IContextSource object.
isWriteMode()
Indicates whether this module requires write mode.
static newFatal( $message,... $parameters)
Factory function for fatal errors.
static isThrottled( $user)
Returns true if the user has surpassed the upload rate limit, false otherwise.
getStashResult( $warnings)
Get Stash Result, throws an exception if the file could not be stashed.
static makeWarningsSerializable( $warnings)
Convert the warnings array returned by checkWarnings() to something that can be serialized.
const MIN_LENGTH_PARTNAME
static newFatalPermissionDeniedStatus( $permission)
Factory function for fatal permission-denied errors.
verifyUpload()
Performs file verification, dies on error.
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
static isEnabled()
Returns true if uploads are enabled.
const PARAM_TYPE
(string|string[]) Either an array of allowed value strings, or a string type as described below.
getResult()
Get the result object.
getWarningsResult( $warnings)
Get Warnings Result.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
static setSessionStatus(User $user, $statusKey, $value)
Set the current status of a chunked upload (used for polling)
UploadBase UploadFromChunks $mUpload
getApiWarnings()
Check warnings.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
dieBlocked(AbstractBlock $block)
Throw an ApiUsageException, which will (if uncaught) call the main module's error handler and die wit...
Implements uploading from previously stored file.
getExamplesMessages()
Returns usage examples for this module.
static listParam(array $list, $type='text')
This abstract class implements many basic API functions, and is the base of all API classes.
Extension of Message implementing IApiMessage.
initialize( $name, $url)
Entry point for API upload.
Upload a file from the upload stash into the local file repo.
const PARAM_DEPRECATED
(boolean) Is the parameter deprecated (will show a warning)?
const PARAM_MIN
(integer) Lowest value allowed for the parameter, for PARAM_TYPE 'integer' and 'limit'.
dieStatusWithCode( $status, $overrideCode, $moreExtraData=null)
Like dieStatus(), but always uses $overrideCode for the error code, unless the code comes from IApiMe...
Implements uploading from a HTTP resource.
performStash( $failureMode, &$data=null)
Stash the file and add the file key, or error information if it fails, to the data.
static isEnabled()
Checks if the upload from URL feature is enabled.
const WINDOWS_NONASCII_FILENAME
dieRecoverableError( $errors, $parameter=null)
Throw an error that the user can recover from by providing a better value for $parameter.
const PARAM_MAX
(integer) Max value allowed for the parameter, for PARAM_TYPE 'integer' and 'limit'.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
getContextResult()
Get an upload result based on upload context.
handleStashException( $e)
Handles a stash exception, giving a useful error to the user.
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
static create( $msg, $code=null, array $data=null)
Create an IApiMessage for the message.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
getWatchlistValue( $watchlist, $titleObj, $userOption=null)
Return true if we're to watch the page, false if not, null if no change.
needsToken()
Returns the token type this module requires in order to execute.
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
static setIndexedTagName(array &$arr, $tag)
Set the tag name for numeric-keyed values in XML format.
static isAllowedUrl( $url)
Checks whether the URL is not allowed.
static newGood( $value=null)
Factory function for good results.
Assemble the segments of a chunked upload.
getHelpUrls()
Return links to more detailed help pages about the module.
mustBePosted()
Indicates whether this module must be called with a POST request.
performUpload( $warnings)
Perform the actual upload.
requireOnlyOneParameter( $params, $required)
Die if none or more than one of a certain set of parameters is set and not false.
static isAllowedHost( $url)
Checks whether the URL is for an allowed host The domains in the whitelist can include wildcard chara...
static getSessionStatus(User $user, $statusKey)
Get the current status of a chunked upload (used for polling)
static getMaxUploadSize( $forType=null)
Get the MediaWiki maximum uploaded file size for given type of upload, based on $wgMaxUploadSize.
static singleton( $domain=false)
exportSession()
Export the resolved user IP, HTTP headers, user ID, and session ID.
const PARAM_DFLT
(null|boolean|integer|string) Default value of the parameter.
checkPermissions( $user)
Checks that the user has permissions to perform this upload.
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
getModuleName()
Get the name of the module being executed by this instance.
const PARAM_ISMULTI
(boolean) Accept multiple pipe-separated values for this parameter (e.g.
getMain()
Get the main module.
Implements uploading from chunks.
transformWarnings( $warnings)
static dieDebug( $method, $message)
Internal code errors should be reported with this method.
Implements regular file uploads.
getErrorFormatter()
Get the error formatter.
checkVerification(array $verification)
Performs file verification, dies on error.