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 ( UploadBase::isThrottled( $this->
getUser() ) ) {
456 $this->
msg(
'actionthrottledtext' )->escaped()
462 if ( !$this->mForReUpload ) {
464 $this->mCopyrightStatus, $this->mCopyrightSource );
469 $status = $this->mUpload->performUpload(
476 if ( !$status->isGood() ) {
483 $this->mUploadSuccessful =
true;
485 $this->
getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
499 global $wgUseCopyrightUpload, $wgForceUIMsgAsContentMsg;
506 foreach (
array(
'license-header',
'filedesc',
'filestatus',
'filesource' )
as $msgName ) {
507 if ( in_array( $msgName, (
array)$wgForceUIMsgAsContentMsg ) ) {
508 $msg[$msgName] =
"{{int:$msgName}}";
510 $msg[$msgName] =
wfMessage( $msgName )->inContentLanguage()->text();
514 if ( $wgUseCopyrightUpload ) {
517 $licensetxt =
'== ' . $msg[
'license-header'] .
" ==\n" .
'{{' .
$license .
'}}' .
"\n";
519 $pageText =
'== ' . $msg[
'filedesc'] .
" ==\n" .
$comment .
"\n" .
520 '== ' . $msg[
'filestatus'] .
" ==\n" . $copyStatus .
"\n" .
522 '== ' . $msg[
'filesource'] .
" ==\n" .
$source;
525 $filedesc =
$comment ==
'' ?
'' :
'== ' . $msg[
'filedesc'] .
" ==\n" .
$comment .
"\n";
526 $pageText = $filedesc .
527 '== ' . $msg[
'license-header'] .
" ==\n" .
'{{' .
$license .
'}}' .
"\n";
549 if ( $this->
getUser()->getOption(
'watchdefault' ) ) {
555 if ( $desiredTitleObj instanceof
Title && $this->
getUser()->isWatched( $desiredTitleObj ) ) {
561 if ( $local && $local->exists() ) {
567 return $this->
getUser()->getOption(
'watchcreations' );
580 switch ( $details[
'status'] ) {
583 case UploadBase::MIN_LENGTH_PARTNAME:
586 case UploadBase::ILLEGAL_FILENAME:
588 $details[
'filtered'] )->parse() );
590 case UploadBase::FILENAME_TOO_LONG:
593 case UploadBase::FILETYPE_MISSING:
596 case UploadBase::WINDOWS_NONASCII_FILENAME:
601 case UploadBase::EMPTY_FILE:
604 case UploadBase::FILE_TOO_LARGE:
607 case UploadBase::FILETYPE_BADTYPE:
608 $msg = $this->
msg(
'filetype-banned-type' );
609 if ( isset( $details[
'blacklistedExt'] ) ) {
610 $msg->params( $this->
getLanguage()->commaList( $details[
'blacklistedExt'] ) );
612 $msg->params( $details[
'finalExt'] );
621 if ( isset( $details[
'blacklistedExt'] ) ) {
622 $msg->params( count( $details[
'blacklistedExt'] ) );
629 case UploadBase::VERIFICATION_ERROR:
630 unset( $details[
'status'] );
631 $code = array_shift( $details[
'details'] );
634 case UploadBase::HOOK_ABORTED:
635 if ( is_array( $details[
'error'] ) ) { # allow
hooks to
return error details
in an
array
636 $args = $details[
'error'];
639 $error = $details[
'error'];
646 throw new MWException( __METHOD__ .
": Unknown value `{$details['status']}`" );
659 $success = $this->mUpload->unsaveUploadedFile();
661 $this->
getOutput()->showFileDeleteError( $this->mUpload->getTempPath() );
683 $file = $exists[
'file'];
684 $filename =
$file->getTitle()->getPrefixedText();
687 if ( $exists[
'warning'] ==
'exists' ) {
689 $warning =
wfMessage(
'fileexists', $filename )->parse();
690 } elseif ( $exists[
'warning'] ==
'page-exists' ) {
692 $warning =
wfMessage(
'filepageexists', $filename )->parse();
693 } elseif ( $exists[
'warning'] ==
'exists-normalized' ) {
694 $warning =
wfMessage(
'fileexists-extension', $filename,
695 $exists[
'normalizedFile']->
getTitle()->getPrefixedText() )->parse();
696 } elseif ( $exists[
'warning'] ==
'thumb' ) {
698 $warning =
wfMessage(
'fileexists-thumbnail-yes',
699 $exists[
'thumbFile']->
getTitle()->getPrefixedText(), $filename )->parse();
700 } elseif ( $exists[
'warning'] ==
'thumb-name' ) {
703 $badPart = substr(
$name, 0, strpos(
$name,
'-' ) + 1 );
704 $warning =
wfMessage(
'file-thumbnail-no', $badPart )->parse();
705 } elseif ( $exists[
'warning'] ==
'bad-prefix' ) {
706 $warning =
wfMessage(
'filename-bad-prefix', $exists[
'prefix'] )->parse();
707 } elseif ( $exists[
'warning'] ==
'was-deleted' ) {
708 # If the file existed before and was deleted, warn the user of this
719 $warning =
wfMessage(
'filewasdeleted' )->rawParams( $llink )->parseAsBlock();
737 $gallery->setShowBytes(
false );
739 $gallery->add(
$file->getTitle() );
743 wfMessage(
'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
744 $gallery->toHtml() .
"</li>\n";
774 $this->mWatch = !empty(
$options[
'watch'] );
775 $this->mForReUpload = !empty(
$options[
'forreupload'] );
776 $this->mSessionKey = isset(
$options[
'sessionkey'] ) ?
$options[
'sessionkey'] :
'';
777 $this->mHideIgnoreWarning = !empty(
$options[
'hideignorewarning'] );
778 $this->mDestWarningAck = !empty(
$options[
'destwarningack'] );
779 $this->mDestFile = isset(
$options[
'destfile'] ) ?
$options[
'destfile'] :
'';
781 $this->mComment = isset(
$options[
'description'] ) ?
784 $this->mTextTop = isset(
$options[
'texttop'] )
787 $this->mTextAfterSummary = isset(
$options[
'textaftersummary'] )
788 ?
$options[
'textaftersummary'] :
'';
791 $descriptor = $sourceDescriptor
796 parent::__construct( $descriptor,
$context,
'upload' );
798 # Set some form properties
801 # Used message keys: 'accesskey-upload', 'tooltip-upload'
803 $this->
setId(
'mw-upload-form' );
805 # Build a list of IDs for javascript insertion
806 $this->mSourceIds =
array();
807 foreach ( $sourceDescriptor
as $field ) {
808 if ( !empty( $field[
'id'] ) ) {
809 $this->mSourceIds[] = $field[
'id'];
821 global $wgCopyUploadsFromSpecialUpload;
823 if ( $this->mSessionKey ) {
825 'SessionKey' =>
array(
827 'default' => $this->mSessionKey,
829 'SourceType' =>
array(
831 'default' =>
'Stash',
838 && $wgCopyUploadsFromSpecialUpload;
839 $radio = $canUploadByUrl;
840 $selectedSourceType = strtolower( $this->
getRequest()->getText(
'wpSourceType',
'File' ) );
842 $descriptor =
array();
843 if ( $this->mTextTop ) {
844 $descriptor[
'UploadFormTextTop'] =
array(
846 'section' =>
'source',
847 'default' => $this->mTextTop,
852 $this->mMaxUploadSize[
'file'] = UploadBase::getMaxUploadSize(
'file' );
853 # Limit to upload_max_filesize unless we are running under HipHop and
854 # that setting doesn't exist
856 $this->mMaxUploadSize[
'file'] = min( $this->mMaxUploadSize[
'file'],
862 $descriptor[
'UploadFile'] =
array(
863 'class' =>
'UploadSourceField',
864 'section' =>
'source',
866 'id' =>
'wpUploadFile',
867 'radio-id' =>
'wpSourceTypeFile',
868 'label-message' =>
'sourcefilename',
869 'upload-type' =>
'File',
871 'help' => $this->
msg(
'upload-maxfilesize',
874 $this->
msg(
'word-separator' )->escaped() .
875 $this->
msg(
'upload_source_file' )->escaped(),
876 'checked' => $selectedSourceType ==
'file',
879 if ( $canUploadByUrl ) {
880 $this->mMaxUploadSize[
'url'] = UploadBase::getMaxUploadSize(
'url' );
881 $descriptor[
'UploadFileURL'] =
array(
882 'class' =>
'UploadSourceField',
883 'section' =>
'source',
884 'id' =>
'wpUploadFileURL',
885 'radio-id' =>
'wpSourceTypeurl',
886 'label-message' =>
'sourceurl',
887 'upload-type' =>
'url',
889 'help' => $this->
msg(
'upload-maxfilesize',
892 $this->
msg(
'word-separator' )->escaped() .
893 $this->
msg(
'upload_source_url' )->escaped(),
894 'checked' => $selectedSourceType ==
'url',
897 wfRunHooks(
'UploadFormSourceDescriptors',
array( &$descriptor, &$radio, $selectedSourceType ) );
899 $descriptor[
'Extensions'] =
array(
901 'section' =>
'source',
915 # Print a list of allowed file extensions, if so configured. We ignore
916 # MIME type here, it's incomprehensible to most people and too long.
917 global $wgCheckFileExtensions, $wgStrictFileExtensions,
920 if ( $wgCheckFileExtensions ) {
921 if ( $wgStrictFileExtensions ) {
922 # Everything not permitted is banned
924 '<div id="mw-upload-permitted">' .
931 # We have to list both preferred and prohibited
933 '<div id="mw-upload-preferred">' .
939 '<div id="mw-upload-prohibited">' .
947 # Everything is permitted.
948 $extensionsList =
'';
951 return $extensionsList;
961 if ( $this->mSessionKey ) {
964 $file = $stash->getFile( $this->mSessionKey );
971 $mto =
$file->transform(
array(
'width' => 120 ) );
973 '<div class="thumb t' . $wgContLang->alignEnd() .
'">' .
975 'src' => $mto->getUrl(),
976 'class' =>
'thumbimage',
977 ) ) .
'</div>',
'description' );
984 'section' =>
'description',
985 'id' =>
'wpDestFile',
986 'label-message' =>
'destfilename',
988 'default' => $this->mDestFile,
989 # @todo FIXME: Hack to work around poor handling
of the
'default' option
in HTMLForm
990 'nodata' => strval( $this->mDestFile ) !==
'',
992 'UploadDescription' =>
array(
993 'type' =>
'textarea',
994 'section' =>
'description',
995 'id' =>
'wpUploadDescription',
996 'label-message' => $this->mForReUpload
997 ?
'filereuploadsummary'
998 :
'fileuploadsummary',
999 'default' => $this->mComment,
1000 'cols' => $this->
getUser()->getIntOption(
'cols' ),
1004 if ( $this->mTextAfterSummary ) {
1005 $descriptor[
'UploadFormTextAfterSummary'] =
array(
1007 'section' =>
'description',
1008 'default' => $this->mTextAfterSummary,
1013 $descriptor +=
array(
1014 'EditTools' =>
array(
1015 'type' =>
'edittools',
1016 'section' =>
'description',
1017 'message' =>
'edittools-upload',
1021 if ( $this->mForReUpload ) {
1022 $descriptor[
'DestFile'][
'readonly'] =
true;
1024 $descriptor[
'License'] =
array(
1026 'class' =>
'Licenses',
1027 'section' =>
'description',
1028 'id' =>
'wpLicense',
1029 'label-message' =>
'license',
1033 global $wgUseCopyrightUpload;
1034 if ( $wgUseCopyrightUpload ) {
1035 $descriptor[
'UploadCopyStatus'] =
array(
1037 'section' =>
'description',
1038 'id' =>
'wpUploadCopyStatus',
1039 'label-message' =>
'filestatus',
1041 $descriptor[
'UploadSource'] =
array(
1043 'section' =>
'description',
1044 'id' =>
'wpUploadSource',
1045 'label-message' =>
'filesource',
1060 if (
$user->isLoggedIn() ) {
1061 $descriptor =
array(
1062 'Watchthis' =>
array(
1064 'id' =>
'wpWatchthis',
1065 'label-message' =>
'watchthisupload',
1066 'section' =>
'options',
1067 'default' => $this->mWatch,
1071 if ( !$this->mHideIgnoreWarning ) {
1072 $descriptor[
'IgnoreWarning'] =
array(
1074 'id' =>
'wpIgnoreWarning',
1075 'label-message' =>
'ignorewarnings',
1076 'section' =>
'options',
1080 $descriptor[
'DestFileWarningAck'] =
array(
1082 'id' =>
'wpDestFileWarningAck',
1083 'default' => $this->mDestWarningAck ?
'1' :
'',
1086 if ( $this->mForReUpload ) {
1087 $descriptor[
'ForReUpload'] =
array(
1089 'id' =>
'wpForReUpload',
1100 public function show() {
1109 global $wgUseAjax, $wgAjaxUploadDestCheck, $wgAjaxLicensePreview,
1110 $wgEnableAPI, $wgStrictFileExtensions;
1112 $useAjaxDestCheck = $wgUseAjax && $wgAjaxUploadDestCheck;
1113 $useAjaxLicensePreview = $wgUseAjax && $wgAjaxLicensePreview && $wgEnableAPI;
1114 $this->mMaxUploadSize[
'*'] = UploadBase::getMaxUploadSize();
1116 $scriptVars =
array(
1117 'wgAjaxUploadDestCheck' => $useAjaxDestCheck,
1118 'wgAjaxLicensePreview' => $useAjaxLicensePreview,
1119 'wgUploadAutoFill' => !$this->mForReUpload &&
1122 $this->mDestFile ===
'',
1123 'wgUploadSourceIds' => $this->mSourceIds,
1124 'wgStrictFileExtensions' => $wgStrictFileExtensions,
1126 'wgMaxUploadSize' => $this->mMaxUploadSize,
1130 $out->addJsConfigVars( $scriptVars );
1133 'mediawiki.action.edit',
1134 'mediawiki.legacy.upload',
1135 'mediawiki.special.upload',
1159 $id = $this->mParams[
'id'];
1162 if ( !empty( $this->mParams[
'radio'] ) ) {
1163 if ( isset( $this->mParams[
'radio-id'] ) ) {
1164 $radioId = $this->mParams[
'radio-id'];
1168 $radioId =
'wpSourceType' . $this->mParams[
'upload-type'];
1172 'name' =>
'wpSourceType',
1175 'value' => $this->mParams[
'upload-type'],
1178 if ( !empty( $this->mParams[
'checked'] ) ) {
1192 return isset( $this->mParams[
'size'] )
1193 ? $this->mParams[
'size']