38 parent::__construct(
'Upload',
'upload' );
90 $this->mRequest = $request = $this->
getRequest();
91 $this->mSourceType = $request->getVal(
'wpSourceType',
'file' );
92 $this->mUpload = UploadBase::createFromRequest( $request );
93 $this->mUploadClicked = $request->wasPosted()
94 && ( $request->getCheck(
'wpUpload' )
95 || $request->getCheck(
'wpUploadIgnoreWarning' ) );
98 $this->mDesiredDestName = $request->getText(
'wpDestFile' );
99 if ( !$this->mDesiredDestName && $request->getFileName(
'wpUploadFile' ) !== null ) {
100 $this->mDesiredDestName = $request->getFileName(
'wpUploadFile' );
102 $this->mLicense = $request->getText(
'wpLicense' );
104 $this->mDestWarningAck = $request->getText(
'wpDestFileWarningAck' );
105 $this->mIgnoreWarning = $request->getCheck(
'wpIgnoreWarning' )
106 || $request->getCheck(
'wpUploadIgnoreWarning' );
107 $this->mWatchthis = $request->getBool(
'wpWatchthis' ) && $this->
getUser()->isLoggedIn();
108 $this->mCopyrightStatus = $request->getText(
'wpUploadCopyStatus' );
109 $this->mCopyrightSource = $request->getText(
'wpUploadSource' );
111 $this->mForReUpload = $request->getBool(
'wpForReUpload' );
113 $commentDefault =
'';
114 $commentMsg =
wfMessage(
'upload-default-description' )->inContentLanguage();
115 if ( !$this->mForReUpload && !$commentMsg->isDisabled() ) {
116 $commentDefault = $commentMsg->plain();
118 $this->mComment = $request->getText(
'wpUploadDescription', $commentDefault );
120 $this->mCancelUpload = $request->getCheck(
'wpCancelUpload' )
121 || $request->getCheck(
'wpReUpload' );
124 $token = $request->getVal(
'wpEditToken' );
125 $this->mTokenOk = $this->
getUser()->matchEditToken( $token );
127 $this->uploadFormTextTop =
'';
128 $this->uploadFormTextAfterSummary =
'';
140 return UploadBase::isEnabled() && parent::userCanExecute(
$user );
146 public function execute( $par ) {
150 # Check uploading enabled
151 if ( !UploadBase::isEnabled() ) {
152 throw new ErrorPageError(
'uploaddisabled',
'uploaddisabledtext' );
157 $permissionRequired = UploadBase::isAllowed(
$user );
158 if ( $permissionRequired !==
true ) {
163 if (
$user->isBlocked() ) {
167 # Check whether we actually want to allow changing stuff
172 # Unsave the temporary file in case this was a cancelled upload
173 if ( $this->mCancelUpload ) {
175 # Something went wrong, so unsaveUploadedFile showed a warning
180 # Process upload or show a form
182 $this->mTokenOk && !$this->mCancelUpload &&
183 ( $this->mUpload && $this->mUploadClicked )
187 # Backwards compatibility hook
189 wfDebug(
"Hook 'UploadForm:initial' broke output of the upload form\n" );
197 if ( $this->mUpload ) {
198 $this->mUpload->cleanupTempFile();
208 # Add links if file was previously deleted
209 if ( $this->mDesiredDestName ) {
228 protected function getUploadForm( $message =
'', $sessionKey =
'', $hideIgnoreWarning =
false ) {
234 'forreupload' => $this->mForReUpload,
235 'sessionkey' => $sessionKey,
236 'hideignorewarning' => $hideIgnoreWarning,
237 'destwarningack' => (
bool)$this->mDestWarningAck,
239 'description' => $this->mComment,
240 'texttop' => $this->uploadFormTextTop,
241 'textaftersummary' => $this->uploadFormTextAfterSummary,
242 'destfile' => $this->mDesiredDestName,
245 # Check the token, but only if necessary
247 !$this->mTokenOk && !$this->mCancelUpload &&
248 ( $this->mUpload && $this->mUploadClicked )
250 $form->addPreText( $this->
msg(
'session_fail_preview' )->parse() );
253 # Give a notice if the user is uploading a file that has been deleted or moved
254 # Note that this is independent from the message 'filewasdeleted' that requires JS
257 if ( $desiredTitleObj instanceof
Title && !$desiredTitleObj->
exists() ) {
260 '',
array(
'lim' => 10,
261 'conds' =>
array(
"log_action != 'revision'" ),
262 'showIfEmpty' =>
false,
263 'msgKey' =>
array(
'upload-recreate-warning' ) )
266 $form->addPreText( $delNotice );
269 $form->addPreText(
'<div id="uploadtext">' .
270 $this->
msg(
'uploadtext',
array( $this->mDesiredDestName ) )->parseAsBlock() .
272 # Add upload error message
273 $form->addPreText( $message );
276 $uploadFooter = $this->
msg(
'uploadfooter' );
277 if ( !$uploadFooter->isDisabled() ) {
278 $form->addPostText(
'<div id="mw-upload-footer-message">'
279 . $uploadFooter->parseAsBlock() .
"</div>\n" );
294 if (
$count > 0 &&
$user->isAllowed(
'deletedhistory' ) ) {
297 $this->
msg(
'restorelink' )->numParams(
$count )->escaped()
299 $link = $this->
msg(
$user->isAllowed(
'delete' ) ?
'thisisdeleted' :
'viewdeleted' )
300 ->rawParams( $restorelink )->parseAsBlock();
301 $this->
getOutput()->addHTML(
"<div id=\"contentSub2\">{$link}</div>" );
318 $sessionKey = $this->mUpload->stashSession();
319 $message =
'<h2>' . $this->
msg(
'uploaderror' )->escaped() .
"</h2>\n" .
320 '<div class="error">' . $message .
"</div>\n";
323 $form->setSubmitText( $this->
msg(
'upload-tryagain' )->escaped() );
336 # If there are no warnings, or warnings we can ignore, return early.
337 # mDestWarningAck is set when some javascript has shown the warning
338 # to the user. mForReUpload is set when the user clicks the "upload a
340 if ( !$warnings || ( count( $warnings ) == 1
341 && isset( $warnings[
'exists'] )
342 && ( $this->mDestWarningAck || $this->mForReUpload ) )
347 $sessionKey = $this->mUpload->stashSession();
349 $warningHtml =
'<h2>' . $this->
msg(
'uploadwarning' )->escaped() .
"</h2>\n"
350 .
'<ul class="warning">';
351 foreach ( $warnings
as $warning =>
$args ) {
352 if ( $warning ==
'badfilename' ) {
355 if ( $warning ==
'exists' ) {
357 } elseif ( $warning ==
'duplicate' ) {
359 } elseif ( $warning ==
'duplicate-archive' ) {
360 if (
$args ===
'' ) {
361 $msg =
"\t<li>" . $this->
msg(
'file-deleted-duplicate-notitle' )->parse()
364 $msg =
"\t<li>" . $this->
msg(
'file-deleted-duplicate',
369 if (
$args ===
true ) {
371 } elseif ( !is_array(
$args ) ) {
374 $msg =
"\t<li>" . $this->
msg( $warning,
$args )->parse() .
"</li>\n";
376 $warningHtml .= $msg;
378 $warningHtml .=
"</ul>\n";
379 $warningHtml .= $this->
msg(
'uploadwarning-text' )->parseAsBlock();
382 $form->setSubmitText( $this->
msg(
'upload-tryagain' )->
text() );
383 $form->addButton(
'wpUploadIgnoreWarning', $this->
msg(
'ignorewarning' )->
text() );
384 $form->addButton(
'wpCancelUpload', $this->
msg(
'reuploaddesc' )->
text() );
388 # Indicate that we showed a form
398 $message =
'<h2>' . $this->
msg(
'uploadwarning' )->escaped() .
"</h2>\n" .
399 '<div class="error">' . $message .
"</div>\n";
409 $status = $this->mUpload->fetchFile();
410 if ( !$status->isOK() ) {
417 wfDebug(
"Hook 'UploadForm:BeforeProcessing' broke processing the file.\n" );
427 $details = $this->mUpload->verifyUpload();
428 if ( $details[
'status'] != UploadBase::OK ) {
435 $permErrors = $this->mUpload->verifyTitlePermissions( $this->
getUser() );
436 if ( $permErrors !==
true ) {
437 $code = array_shift( $permErrors[0] );
443 $this->mLocalFile = $this->mUpload->getLocalFile();
446 if ( !$this->mIgnoreWarning ) {
447 $warnings = $this->mUpload->checkWarnings();
454 if ( !$this->mForReUpload ) {
456 $this->mCopyrightStatus, $this->mCopyrightSource );
461 $status = $this->mUpload->performUpload(
468 if ( !$status->isGood() ) {
475 $this->mUploadSuccessful =
true;
477 $this->
getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
491 global $wgUseCopyrightUpload, $wgForceUIMsgAsContentMsg;
498 foreach (
array(
'license-header',
'filedesc',
'filestatus',
'filesource' )
as $msgName ) {
499 if ( in_array( $msgName, (
array)$wgForceUIMsgAsContentMsg ) ) {
500 $msg[$msgName] =
"{{int:$msgName}}";
502 $msg[$msgName] =
wfMessage( $msgName )->inContentLanguage()->text();
506 if ( $wgUseCopyrightUpload ) {
509 $licensetxt =
'== ' . $msg[
'license-header'] .
" ==\n" .
'{{' .
$license .
'}}' .
"\n";
511 $pageText =
'== ' . $msg[
'filedesc'] .
" ==\n" .
$comment .
"\n" .
512 '== ' . $msg[
'filestatus'] .
" ==\n" . $copyStatus .
"\n" .
514 '== ' . $msg[
'filesource'] .
" ==\n" .
$source;
517 $filedesc =
$comment ==
'' ?
'' :
'== ' . $msg[
'filedesc'] .
" ==\n" .
$comment .
"\n";
518 $pageText = $filedesc .
519 '== ' . $msg[
'license-header'] .
" ==\n" .
'{{' .
$license .
'}}' .
"\n";
541 if ( $this->
getUser()->getOption(
'watchdefault' ) ) {
547 if ( $desiredTitleObj instanceof
Title && $this->
getUser()->isWatched( $desiredTitleObj ) ) {
553 if ( $local && $local->exists() ) {
559 return $this->
getUser()->getOption(
'watchcreations' );
572 switch ( $details[
'status'] ) {
575 case UploadBase::MIN_LENGTH_PARTNAME:
578 case UploadBase::ILLEGAL_FILENAME:
580 $details[
'filtered'] )->parse() );
582 case UploadBase::FILENAME_TOO_LONG:
585 case UploadBase::FILETYPE_MISSING:
588 case UploadBase::WINDOWS_NONASCII_FILENAME:
593 case UploadBase::EMPTY_FILE:
596 case UploadBase::FILE_TOO_LARGE:
599 case UploadBase::FILETYPE_BADTYPE:
600 $msg = $this->
msg(
'filetype-banned-type' );
601 if ( isset( $details[
'blacklistedExt'] ) ) {
602 $msg->params( $this->
getLanguage()->commaList( $details[
'blacklistedExt'] ) );
604 $msg->params( $details[
'finalExt'] );
613 if ( isset( $details[
'blacklistedExt'] ) ) {
614 $msg->params( count( $details[
'blacklistedExt'] ) );
621 case UploadBase::VERIFICATION_ERROR:
622 unset( $details[
'status'] );
623 $code = array_shift( $details[
'details'] );
626 case UploadBase::HOOK_ABORTED:
627 if ( is_array( $details[
'error'] ) ) { # allow
hooks to
return error details
in an
array
628 $args = $details[
'error'];
631 $error = $details[
'error'];
638 throw new MWException( __METHOD__ .
": Unknown value `{$details['status']}`" );
651 $success = $this->mUpload->unsaveUploadedFile();
653 $this->
getOutput()->showFileDeleteError( $this->mUpload->getTempPath() );
675 $file = $exists[
'file'];
676 $filename =
$file->getTitle()->getPrefixedText();
679 if ( $exists[
'warning'] ==
'exists' ) {
681 $warning =
wfMessage(
'fileexists', $filename )->parse();
682 } elseif ( $exists[
'warning'] ==
'page-exists' ) {
684 $warning =
wfMessage(
'filepageexists', $filename )->parse();
685 } elseif ( $exists[
'warning'] ==
'exists-normalized' ) {
686 $warning =
wfMessage(
'fileexists-extension', $filename,
687 $exists[
'normalizedFile']->
getTitle()->getPrefixedText() )->parse();
688 } elseif ( $exists[
'warning'] ==
'thumb' ) {
690 $warning =
wfMessage(
'fileexists-thumbnail-yes',
691 $exists[
'thumbFile']->
getTitle()->getPrefixedText(), $filename )->parse();
692 } elseif ( $exists[
'warning'] ==
'thumb-name' ) {
695 $badPart = substr(
$name, 0, strpos(
$name,
'-' ) + 1 );
696 $warning =
wfMessage(
'file-thumbnail-no', $badPart )->parse();
697 } elseif ( $exists[
'warning'] ==
'bad-prefix' ) {
698 $warning =
wfMessage(
'filename-bad-prefix', $exists[
'prefix'] )->parse();
699 } elseif ( $exists[
'warning'] ==
'was-deleted' ) {
700 # If the file existed before and was deleted, warn the user of this
711 $warning =
wfMessage(
'filewasdeleted' )->rawParams( $llink )->parseAsBlock();
729 $gallery->setShowBytes(
false );
731 $gallery->add(
$file->getTitle() );
735 wfMessage(
'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
736 $gallery->toHtml() .
"</li>\n";
766 $this->mWatch = !empty(
$options[
'watch'] );
767 $this->mForReUpload = !empty(
$options[
'forreupload'] );
768 $this->mSessionKey = isset(
$options[
'sessionkey'] ) ?
$options[
'sessionkey'] :
'';
769 $this->mHideIgnoreWarning = !empty(
$options[
'hideignorewarning'] );
770 $this->mDestWarningAck = !empty(
$options[
'destwarningack'] );
771 $this->mDestFile = isset(
$options[
'destfile'] ) ?
$options[
'destfile'] :
'';
773 $this->mComment = isset(
$options[
'description'] ) ?
776 $this->mTextTop = isset(
$options[
'texttop'] )
779 $this->mTextAfterSummary = isset(
$options[
'textaftersummary'] )
780 ?
$options[
'textaftersummary'] :
'';
783 $descriptor = $sourceDescriptor
788 parent::__construct( $descriptor,
$context,
'upload' );
790 # Set some form properties
793 # Used message keys: 'accesskey-upload', 'tooltip-upload'
795 $this->
setId(
'mw-upload-form' );
797 # Build a list of IDs for javascript insertion
798 $this->mSourceIds =
array();
799 foreach ( $sourceDescriptor
as $field ) {
800 if ( !empty( $field[
'id'] ) ) {
801 $this->mSourceIds[] = $field[
'id'];
813 global $wgCopyUploadsFromSpecialUpload;
815 if ( $this->mSessionKey ) {
817 'SessionKey' =>
array(
819 'default' => $this->mSessionKey,
821 'SourceType' =>
array(
823 'default' =>
'Stash',
830 && $wgCopyUploadsFromSpecialUpload;
831 $radio = $canUploadByUrl;
832 $selectedSourceType = strtolower( $this->
getRequest()->getText(
'wpSourceType',
'File' ) );
834 $descriptor =
array();
835 if ( $this->mTextTop ) {
836 $descriptor[
'UploadFormTextTop'] =
array(
838 'section' =>
'source',
839 'default' => $this->mTextTop,
844 $this->mMaxUploadSize[
'file'] = UploadBase::getMaxUploadSize(
'file' );
845 # Limit to upload_max_filesize unless we are running under HipHop and
846 # that setting doesn't exist
848 $this->mMaxUploadSize[
'file'] = min( $this->mMaxUploadSize[
'file'],
854 $descriptor[
'UploadFile'] =
array(
855 'class' =>
'UploadSourceField',
856 'section' =>
'source',
858 'id' =>
'wpUploadFile',
859 'radio-id' =>
'wpSourceTypeFile',
860 'label-message' =>
'sourcefilename',
861 'upload-type' =>
'File',
863 'help' => $this->
msg(
'upload-maxfilesize',
866 $this->
msg(
'word-separator' )->escaped() .
867 $this->
msg(
'upload_source_file' )->escaped(),
868 'checked' => $selectedSourceType ==
'file',
871 if ( $canUploadByUrl ) {
872 $this->mMaxUploadSize[
'url'] = UploadBase::getMaxUploadSize(
'url' );
873 $descriptor[
'UploadFileURL'] =
array(
874 'class' =>
'UploadSourceField',
875 'section' =>
'source',
876 'id' =>
'wpUploadFileURL',
877 'radio-id' =>
'wpSourceTypeurl',
878 'label-message' =>
'sourceurl',
879 'upload-type' =>
'url',
881 'help' => $this->
msg(
'upload-maxfilesize',
884 $this->
msg(
'word-separator' )->escaped() .
885 $this->
msg(
'upload_source_url' )->escaped(),
886 'checked' => $selectedSourceType ==
'url',
889 wfRunHooks(
'UploadFormSourceDescriptors',
array( &$descriptor, &$radio, $selectedSourceType ) );
891 $descriptor[
'Extensions'] =
array(
893 'section' =>
'source',
907 # Print a list of allowed file extensions, if so configured. We ignore
908 # MIME type here, it's incomprehensible to most people and too long.
909 global $wgCheckFileExtensions, $wgStrictFileExtensions,
912 if ( $wgCheckFileExtensions ) {
913 if ( $wgStrictFileExtensions ) {
914 # Everything not permitted is banned
916 '<div id="mw-upload-permitted">' .
923 # We have to list both preferred and prohibited
925 '<div id="mw-upload-preferred">' .
931 '<div id="mw-upload-prohibited">' .
939 # Everything is permitted.
940 $extensionsList =
'';
943 return $extensionsList;
953 if ( $this->mSessionKey ) {
956 $file = $stash->getFile( $this->mSessionKey );
963 $mto =
$file->transform(
array(
'width' => 120 ) );
965 '<div class="thumb t' . $wgContLang->alignEnd() .
'">' .
967 'src' => $mto->getUrl(),
968 'class' =>
'thumbimage',
969 ) ) .
'</div>',
'description' );
976 'section' =>
'description',
977 'id' =>
'wpDestFile',
978 'label-message' =>
'destfilename',
980 'default' => $this->mDestFile,
981 # @todo FIXME: Hack to work around poor handling
of the
'default' option
in HTMLForm
982 'nodata' => strval( $this->mDestFile ) !==
'',
984 'UploadDescription' =>
array(
985 'type' =>
'textarea',
986 'section' =>
'description',
987 'id' =>
'wpUploadDescription',
988 'label-message' => $this->mForReUpload
989 ?
'filereuploadsummary'
990 :
'fileuploadsummary',
991 'default' => $this->mComment,
992 'cols' => $this->
getUser()->getIntOption(
'cols' ),
996 if ( $this->mTextAfterSummary ) {
997 $descriptor[
'UploadFormTextAfterSummary'] =
array(
999 'section' =>
'description',
1000 'default' => $this->mTextAfterSummary,
1005 $descriptor +=
array(
1006 'EditTools' =>
array(
1007 'type' =>
'edittools',
1008 'section' =>
'description',
1009 'message' =>
'edittools-upload',
1013 if ( $this->mForReUpload ) {
1014 $descriptor[
'DestFile'][
'readonly'] =
true;
1016 $descriptor[
'License'] =
array(
1018 'class' =>
'Licenses',
1019 'section' =>
'description',
1020 'id' =>
'wpLicense',
1021 'label-message' =>
'license',
1025 global $wgUseCopyrightUpload;
1026 if ( $wgUseCopyrightUpload ) {
1027 $descriptor[
'UploadCopyStatus'] =
array(
1029 'section' =>
'description',
1030 'id' =>
'wpUploadCopyStatus',
1031 'label-message' =>
'filestatus',
1033 $descriptor[
'UploadSource'] =
array(
1035 'section' =>
'description',
1036 'id' =>
'wpUploadSource',
1037 'label-message' =>
'filesource',
1052 if (
$user->isLoggedIn() ) {
1053 $descriptor =
array(
1054 'Watchthis' =>
array(
1056 'id' =>
'wpWatchthis',
1057 'label-message' =>
'watchthisupload',
1058 'section' =>
'options',
1059 'default' => $this->mWatch,
1063 if ( !$this->mHideIgnoreWarning ) {
1064 $descriptor[
'IgnoreWarning'] =
array(
1066 'id' =>
'wpIgnoreWarning',
1067 'label-message' =>
'ignorewarnings',
1068 'section' =>
'options',
1072 $descriptor[
'DestFileWarningAck'] =
array(
1074 'id' =>
'wpDestFileWarningAck',
1075 'default' => $this->mDestWarningAck ?
'1' :
'',
1078 if ( $this->mForReUpload ) {
1079 $descriptor[
'ForReUpload'] =
array(
1081 'id' =>
'wpForReUpload',
1092 public function show() {
1101 global $wgUseAjax, $wgAjaxUploadDestCheck, $wgAjaxLicensePreview,
1102 $wgEnableAPI, $wgStrictFileExtensions;
1104 $useAjaxDestCheck = $wgUseAjax && $wgAjaxUploadDestCheck;
1105 $useAjaxLicensePreview = $wgUseAjax && $wgAjaxLicensePreview && $wgEnableAPI;
1106 $this->mMaxUploadSize[
'*'] = UploadBase::getMaxUploadSize();
1108 $scriptVars =
array(
1109 'wgAjaxUploadDestCheck' => $useAjaxDestCheck,
1110 'wgAjaxLicensePreview' => $useAjaxLicensePreview,
1111 'wgUploadAutoFill' => !$this->mForReUpload &&
1114 $this->mDestFile ===
'',
1115 'wgUploadSourceIds' => $this->mSourceIds,
1116 'wgStrictFileExtensions' => $wgStrictFileExtensions,
1118 'wgMaxUploadSize' => $this->mMaxUploadSize,
1122 $out->addJsConfigVars( $scriptVars );
1125 'mediawiki.action.edit',
1126 'mediawiki.legacy.upload',
1127 'mediawiki.special.upload',
1151 $id = $this->mParams[
'id'];
1154 if ( !empty( $this->mParams[
'radio'] ) ) {
1155 if ( isset( $this->mParams[
'radio-id'] ) ) {
1156 $radioId = $this->mParams[
'radio-id'];
1160 $radioId =
'wpSourceType' . $this->mParams[
'upload-type'];
1164 'name' =>
'wpSourceType',
1167 'value' => $this->mParams[
'upload-type'],
1170 if ( !empty( $this->mParams[
'checked'] ) ) {
1184 return isset( $this->mParams[
'size'] )
1185 ? $this->mParams[
'size']