39 parent::__construct(
'Upload',
'upload' );
95 $this->mRequest = $request = $this->
getRequest();
96 $this->mSourceType = $request->getVal(
'wpSourceType',
'file' );
97 $this->mUpload = UploadBase::createFromRequest( $request );
98 $this->mUploadClicked = $request->wasPosted()
99 && ( $request->getCheck(
'wpUpload' )
100 || $request->getCheck(
'wpUploadIgnoreWarning' ) );
103 $this->mDesiredDestName = $request->getText(
'wpDestFile' );
104 if ( !$this->mDesiredDestName && $request->getFileName(
'wpUploadFile' ) !== null ) {
105 $this->mDesiredDestName = $request->getFileName(
'wpUploadFile' );
107 $this->mLicense = $request->getText(
'wpLicense' );
109 $this->mDestWarningAck = $request->getText(
'wpDestFileWarningAck' );
110 $this->mIgnoreWarning = $request->getCheck(
'wpIgnoreWarning' )
111 || $request->getCheck(
'wpUploadIgnoreWarning' );
112 $this->mWatchthis = $request->getBool(
'wpWatchthis' ) && $this->
getUser()->isLoggedIn();
113 $this->mCopyrightStatus = $request->getText(
'wpUploadCopyStatus' );
114 $this->mCopyrightSource = $request->getText(
'wpUploadSource' );
116 $this->mForReUpload = $request->getBool(
'wpForReUpload' );
118 $commentDefault =
'';
119 $commentMsg = $this->
msg(
'upload-default-description' )->inContentLanguage();
120 if ( !$this->mForReUpload && !$commentMsg->isDisabled() ) {
121 $commentDefault = $commentMsg->plain();
123 $this->mComment = $request->getText(
'wpUploadDescription', $commentDefault );
125 $this->mCancelUpload = $request->getCheck(
'wpCancelUpload' )
126 || $request->getCheck(
'wpReUpload' );
129 $token = $request->getVal(
'wpEditToken' );
130 $this->mTokenOk = $this->
getUser()->matchEditToken( $token );
132 $this->uploadFormTextTop =
'';
133 $this->uploadFormTextAfterSummary =
'';
145 return UploadBase::isEnabled() && parent::userCanExecute( $user );
164 # Check uploading enabled
165 if ( !UploadBase::isEnabled() ) {
166 throw new ErrorPageError(
'uploaddisabled',
'uploaddisabledtext' );
173 $permissionRequired = UploadBase::isAllowed( $user );
174 if ( $permissionRequired !==
true ) {
179 if ( $user->isBlockedFromUpload() ) {
183 $this->getLanguage(),
184 $this->getRequest()->getIP()
189 if ( $user->isBlockedGlobally() ) {
191 $user->getGlobalBlock(),
193 $this->getLanguage(),
194 $this->getRequest()->getIP()
198 # Check whether we actually want to allow changing stuff
203 # Unsave the temporary file in case this was a cancelled upload
205 # Something went wrong, so unsaveUploadedFile showed a warning
209 # Process upload or show a form
211 $this->mTokenOk && !$this->mCancelUpload &&
212 ( $this->mUpload && $this->mUploadClicked )
216 # Backwards compatibility hook
217 if ( !$this->
getHookRunner()->onUploadForm_initial( $this ) ) {
218 wfDebug(
"Hook 'UploadForm:initial' broke output of the upload form" );
226 if ( $this->mUpload ) {
227 $this->mUpload->cleanupTempFile();
237 # Add links if file was previously deleted
238 if ( $this->mDesiredDestName ) {
257 protected function getUploadForm( $message =
'', $sessionKey =
'', $hideIgnoreWarning =
false ) {
263 'forreupload' => $this->mForReUpload,
264 'sessionkey' => $sessionKey,
265 'hideignorewarning' => $hideIgnoreWarning,
266 'destwarningack' => (
bool)$this->mDestWarningAck,
268 'description' => $this->mComment,
269 'texttop' => $this->uploadFormTextTop,
270 'textaftersummary' => $this->uploadFormTextAfterSummary,
271 'destfile' => $this->mDesiredDestName,
274 # Check the token, but only if necessary
276 !$this->mTokenOk && !$this->mCancelUpload &&
277 ( $this->mUpload && $this->mUploadClicked )
279 $form->addPreText( $this->
msg(
'session_fail_preview' )->parse() );
282 # Give a notice if the user is uploading a file that has been deleted or moved
283 # Note that this is independent from the message 'filewasdeleted'
284 $desiredTitleObj = Title::makeTitleSafe(
NS_FILE, $this->mDesiredDestName );
286 if ( $desiredTitleObj instanceof
Title && !$desiredTitleObj->
exists() ) {
289 LogEventsList::showLogExtract( $delNotice, [
'delete',
'move' ],
292 'conds' => [
'log_action != ' .
$dbr->addQuotes(
'revision' ) ],
293 'showIfEmpty' =>
false,
294 'msgKey' => [
'upload-recreate-warning' ] ]
297 $form->addPreText( $delNotice );
300 $form->addPreText(
'<div id="uploadtext">' .
301 $this->
msg(
'uploadtext', [ $this->mDesiredDestName ] )->parseAsBlock() .
303 # Add upload error message
304 $form->addPreText( $message );
307 $uploadFooter = $this->
msg(
'uploadfooter' );
308 if ( !$uploadFooter->isDisabled() ) {
309 $form->addPostText(
'<div id="mw-upload-footer-message">'
310 . $uploadFooter->parseAsBlock() .
"</div>\n" );
320 $title = Title::makeTitleSafe(
NS_FILE, $this->mDesiredDestName );
322 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
325 $count =
$title->isDeleted();
326 if ( $count > 0 && $permissionManager->userHasRight( $user,
'deletedhistory' ) ) {
329 $this->msg(
'restorelink' )->numParams( $count )->text()
332 $permissionManager->userHasRight( $user,
'delete' ) ?
'thisisdeleted' :
'viewdeleted'
333 )->rawParams( $restorelink )->parseAsBlock();
337 [
'id' =>
'contentSub2' ],
357 $stashStatus = $this->mUpload->tryStashFile( $this->
getUser() );
358 if ( $stashStatus->isGood() ) {
359 $sessionKey = $stashStatus->getValue()->getFileKey();
360 $uploadWarning =
'upload-tryagain';
363 $uploadWarning =
'upload-tryagain-nostash';
365 $message =
'<h2>' . $this->
msg(
'uploaderror' )->escaped() .
"</h2>\n" .
366 '<div class="error">' . $message .
"</div>\n";
369 $form->setSubmitText( $this->
msg( $uploadWarning )->escaped() );
382 # If there are no warnings, or warnings we can ignore, return early.
383 # mDestWarningAck is set when some javascript has shown the warning
384 # to the user. mForReUpload is set when the user clicks the "upload a
386 if ( !$warnings || ( count( $warnings ) == 1
387 && isset( $warnings[
'exists'] )
388 && ( $this->mDestWarningAck || $this->mForReUpload ) )
393 $stashStatus = $this->mUpload->tryStashFile( $this->
getUser() );
394 if ( $stashStatus->isGood() ) {
395 $sessionKey = $stashStatus->getValue()->getFileKey();
396 $uploadWarning =
'uploadwarning-text';
399 $uploadWarning =
'uploadwarning-text-nostash';
403 $this->
getOutput()->addModuleStyles(
'mediawiki.special' );
406 $warningHtml =
'<h2>' . $this->
msg(
'uploadwarning' )->escaped() .
"</h2>\n"
407 .
'<div class="mw-destfile-warning"><ul>';
408 foreach ( $warnings as $warning =>
$args ) {
409 if ( $warning ==
'badfilename' ) {
410 $this->mDesiredDestName = Title::makeTitle(
NS_FILE,
$args )->getText();
412 if ( $warning ==
'exists' ) {
413 $msg =
"\t<li>" . self::getExistsWarning(
$args ) .
"</li>\n";
414 } elseif ( $warning ==
'no-change' ) {
416 $filename =
$file->getTitle()->getPrefixedText();
417 $msg =
"\t<li>" . $this->
msg(
'fileexists-no-change', $filename )->parse() .
"</li>\n";
418 } elseif ( $warning ==
'duplicate-version' ) {
420 $count = count(
$args );
421 $filename =
$file->getTitle()->getPrefixedText();
422 $message = $this->
msg(
'fileexists-duplicate-version' )
423 ->params( $filename )
424 ->numParams( $count );
425 $msg =
"\t<li>" . $message->parse() .
"</li>\n";
426 } elseif ( $warning ==
'was-deleted' ) {
427 # If the file existed before and was deleted, warn the user of this
431 $this->
msg(
'deletionlog' )->text(),
435 'page' => Title::makeTitle(
NS_FILE,
$args )->getPrefixedText(),
438 $msg =
"\t<li>" . $this->
msg(
'filewasdeleted' )->rawParams( $llink )->parse() .
"</li>\n";
439 } elseif ( $warning ==
'duplicate' ) {
441 } elseif ( $warning ==
'duplicate-archive' ) {
442 if (
$args ===
'' ) {
443 $msg =
"\t<li>" . $this->
msg(
'file-deleted-duplicate-notitle' )->parse()
446 $msg =
"\t<li>" . $this->
msg(
'file-deleted-duplicate',
447 Title::makeTitle(
NS_FILE,
$args )->getPrefixedText() )->parse()
451 if (
$args ===
true ) {
453 } elseif ( !is_array(
$args ) ) {
456 $msg =
"\t<li>" . $this->
msg( $warning,
$args )->parse() .
"</li>\n";
458 $warningHtml .= $msg;
460 $warningHtml .=
"</ul></div>\n";
461 $warningHtml .= $this->
msg( $uploadWarning )->parseAsBlock();
463 $form = $this->
getUploadForm( $warningHtml, $sessionKey,
true );
464 $form->setSubmitText( $this->
msg(
'upload-tryagain' )->text() );
466 'name' =>
'wpUploadIgnoreWarning',
467 'value' => $this->
msg(
'ignorewarning' )->text()
470 'name' =>
'wpCancelUpload',
471 'value' => $this->
msg(
'reuploaddesc' )->text()
476 # Indicate that we showed a form
486 $message =
'<h2>' . $this->
msg(
'uploadwarning' )->escaped() .
"</h2>\n" .
487 '<div class="error">' . $message .
"</div>\n";
497 $status = $this->mUpload->fetchFile();
498 if ( !$status->isOK() ) {
500 $status->getWikiText(
false,
false, $this->getLanguage() )
505 if ( !$this->
getHookRunner()->onUploadForm_BeforeProcessing( $this ) ) {
506 wfDebug(
"Hook 'UploadForm:BeforeProcessing' broke processing the file." );
516 $details = $this->mUpload->verifyUpload();
517 if ( $details[
'status'] != UploadBase::OK ) {
525 $permErrors = $this->mUpload->verifyTitlePermissions( $user );
526 if ( $permErrors !==
true ) {
527 $code = array_shift( $permErrors[0] );
533 $this->mLocalFile = $this->mUpload->getLocalFile();
536 if ( !$this->mIgnoreWarning ) {
537 $warnings = $this->mUpload->checkWarnings( $user );
544 if ( UploadBase::isThrottled( $user ) ) {
546 $this->
msg(
'actionthrottledtext' )->escaped()
552 if ( !$this->mForReUpload ) {
553 $pageText = self::getInitialPageText( $this->mComment, $this->mLicense,
554 $this->mCopyrightStatus, $this->mCopyrightSource, $this->
getConfig() );
559 $changeTags = $this->
getRequest()->getVal(
'wpChangeTags' );
560 if ( $changeTags ===
null || $changeTags ===
'' ) {
563 $changeTags = array_filter( array_map(
'trim', explode(
',', $changeTags ) ) );
568 $changeTags, $user );
569 if ( !$changeTagsStatus->isOK() ) {
571 $changeTagsStatus->getWikiText(
false,
false, $this->getLanguage() )
578 $status = $this->mUpload->performUpload(
586 if ( !$status->isGood() ) {
589 $status->getWikiText(
false,
false, $this->getLanguage() )
597 $this->mUploadSuccessful =
true;
599 $this->
getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
614 if ( $config ===
null ) {
615 wfDebug( __METHOD__ .
' called without a Config instance passed to it' );
616 $config = MediaWikiServices::getInstance()->getMainConfig();
620 $forceUIMsgAsContentMsg = (array)$config->get(
'ForceUIMsgAsContentMsg' );
625 foreach ( [
'license-header',
'filedesc',
'filestatus',
'filesource' ] as $msgName ) {
626 if ( in_array( $msgName, $forceUIMsgAsContentMsg ) ) {
627 $msg[$msgName] =
"{{int:$msgName}}";
629 $msg[$msgName] =
wfMessage( $msgName )->inContentLanguage()->text();
634 if ( $license !==
'' ) {
635 $licenseText =
'== ' . $msg[
'license-header'] .
" ==\n{{" . $license .
"}}\n";
638 $pageText = $comment .
"\n";
639 $headerText =
'== ' . $msg[
'filedesc'] .
' ==';
640 if ( $comment !==
'' && strpos( $comment, $headerText ) ===
false ) {
642 $pageText = $headerText .
"\n" . $pageText;
645 if ( $config->get(
'UseCopyrightUpload' ) ) {
646 $pageText .=
'== ' . $msg[
'filestatus'] .
" ==\n" . $copyStatus .
"\n";
647 $pageText .= $licenseText;
648 $pageText .=
'== ' . $msg[
'filesource'] .
" ==\n" .
$source;
650 $pageText .= $licenseText;
654 Hooks::runner()->onUploadForm_getInitialPageText( $pageText, $msg, $config );
672 if ( $this->
getUser()->getOption(
'watchdefault' ) ) {
677 $desiredTitleObj = Title::makeTitleSafe(
NS_FILE, $this->mDesiredDestName );
678 if ( $desiredTitleObj instanceof
Title && $this->
getUser()->isWatched( $desiredTitleObj ) ) {
683 $local = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo()
684 ->newFile( $this->mDesiredDestName );
685 if ( $local && $local->exists() ) {
691 return $this->
getUser()->getOption(
'watchcreations' ) ||
692 $this->
getUser()->getOption(
'watchuploads' );
703 switch ( $details[
'status'] ) {
705 case UploadBase::MIN_LENGTH_PARTNAME:
708 case UploadBase::ILLEGAL_FILENAME:
710 $details[
'filtered'] )->parse() );
712 case UploadBase::FILENAME_TOO_LONG:
715 case UploadBase::FILETYPE_MISSING:
718 case UploadBase::WINDOWS_NONASCII_FILENAME:
723 case UploadBase::EMPTY_FILE:
726 case UploadBase::FILE_TOO_LARGE:
729 case UploadBase::FILETYPE_BADTYPE:
730 $msg = $this->
msg(
'filetype-banned-type' );
731 if ( isset( $details[
'blacklistedExt'] ) ) {
732 $msg->params( $this->
getLanguage()->commaList( $details[
'blacklistedExt'] ) );
734 $msg->params( $details[
'finalExt'] );
736 $extensions = array_unique( $this->
getConfig()->
get(
'FileExtensions' ) );
737 $msg->params( $this->
getLanguage()->commaList( $extensions ),
738 count( $extensions ) );
743 if ( isset( $details[
'blacklistedExt'] ) ) {
744 $msg->params( count( $details[
'blacklistedExt'] ) );
751 case UploadBase::VERIFICATION_ERROR:
752 unset( $details[
'status'] );
753 $code = array_shift( $details[
'details'] );
756 case UploadBase::HOOK_ABORTED:
757 if ( is_array( $details[
'error'] ) ) { # allow hooks to
return error details in an array
758 $args = $details[
'error'];
759 $error = array_shift(
$args );
761 $error = $details[
'error'];
768 throw new MWException( __METHOD__ .
": Unknown value `{$details['status']}`" );
781 $success = $this->mUpload->unsaveUploadedFile();
784 $this->
msg(
'filedeleteerror' )
785 ->params( $this->mUpload->getTempPath() )
809 $file = $exists[
'file'];
810 $filename =
$file->getTitle()->getPrefixedText();
813 if ( $exists[
'warning'] ==
'exists' ) {
815 $warnMsg =
wfMessage(
'fileexists', $filename );
816 } elseif ( $exists[
'warning'] ==
'page-exists' ) {
818 $warnMsg =
wfMessage(
'filepageexists', $filename );
819 } elseif ( $exists[
'warning'] ==
'exists-normalized' ) {
820 $warnMsg =
wfMessage(
'fileexists-extension', $filename,
821 $exists[
'normalizedFile']->
getTitle()->getPrefixedText() );
822 } elseif ( $exists[
'warning'] ==
'thumb' ) {
824 $warnMsg =
wfMessage(
'fileexists-thumbnail-yes',
825 $exists[
'thumbFile']->
getTitle()->getPrefixedText(), $filename );
826 } elseif ( $exists[
'warning'] ==
'thumb-name' ) {
828 $name =
$file->getName();
829 $badPart = substr( $name, 0, strpos( $name,
'-' ) + 1 );
830 $warnMsg =
wfMessage(
'file-thumbnail-no', $badPart );
831 } elseif ( $exists[
'warning'] ==
'bad-prefix' ) {
832 $warnMsg =
wfMessage(
'filename-bad-prefix', $exists[
'prefix'] );
835 return $warnMsg ? $warnMsg->title(
$file->getTitle() )->parse() :
'';
848 $gallery = ImageGalleryBase::factory(
false, $this->
getContext() );
849 $gallery->setShowBytes(
false );
850 $gallery->setShowDimensions(
false );
851 foreach ( $dupes as
$file ) {
852 $gallery->add(
$file->getTitle() );
856 $this->
msg(
'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
857 $gallery->toHTML() .
"</li>\n";
874 return $bitmapHandler->autoRotateEnabled();
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Generic handler for bitmap images.
An IContextSource implementation which will inherit context from another source but allow individual ...
An error page which can definitely be safely rendered using the OutputPage.
WebRequest clone which takes values from a provided array.
Class to represent a local file in the wiki's own database.
Show an error when a user tries to do something they do not have the necessary permissions for.
Parent class for all special pages.
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!...
getOutput()
Get the OutputPage being used for this instance.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
getPageTitle( $subpage=false)
Get a self-referential title object.
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
getLanguage()
Shortcut to get user's language.
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
MediaWiki Linker LinkRenderer null $linkRenderer
Form for handling uploads and special page.
processVerificationError( $details)
Provides output to the user for a result of UploadBase::verifyUpload.
showViewDeletedLinks()
Shows the "view X deleted revivions link"".
getWatchCheck()
See if we should check the 'watch this page' checkbox on the form based on the user's preferences and...
loadRequest()
Initialize instance variables from request and create an Upload handler.
static getInitialPageText( $comment='', $license='', $copyStatus='', $source='', Config $config=null)
Get the initial image page text based on a comment and optional file status information.
showUploadWarning( $warnings)
Stashes the upload, shows the main form, but adds a "continue anyway button".
$uploadFormTextTop
Text injection points for hooks not using HTMLForm.
bool $mCancelUpload
The user clicked "Cancel and return to upload form" button.
unsaveUploadedFile()
Remove a temporarily kept file stashed by saveTempUploadedFile().
userCanExecute(User $user)
This page can be shown if uploading is enabled.
static getExistsWarning( $exists)
Functions for formatting warnings.
string $mDesiredDestName
User input variables from the "description" section.
showRecoverableUploadError( $message)
Stashes the upload and shows the main upload form.
$mDestWarningAck
Hidden variables.
getDupeWarning( $dupes)
Construct a warning and a gallery from an array of duplicate files.
showUploadForm( $form)
Show the main upload form.
__construct( $request=null)
Get data POSTed through the form and assign them to the object.
WebRequest FauxRequest $mRequest
Misc variables.
processUpload()
Do the upload.
bool $mUploadSuccessful
Subclasses can use this to determine whether a file was uploaded.
$uploadFormTextAfterSummary
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
getUploadForm( $message='', $sessionKey='', $hideIgnoreWarning=false)
Get an UploadForm instance with title and text properly set.
doesWrites()
Indicates whether this special page may perform database writes.
bool $mForReUpload
The user followed an "overwrite this file" link.
$mIgnoreWarning
User input variables from the root section.
showUploadError( $message)
Show the upload form with error message, but do not stash the file.
static rotationEnabled()
Should we rotate images in the preview on Special:Upload.
Represents a title within MediaWiki.
exists( $flags=0)
Check if page exists.
UploadBase and subclasses are the backend of MediaWiki's file uploads.
Implements uploading from previously stored file.
Show an error when the user tries to do something whilst blocked.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Interface for configuration instances.
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.