MediaWiki  master
SpecialUpload.php
Go to the documentation of this file.
1 <?php
28 
35 class SpecialUpload extends SpecialPage {
36 
38  private $localRepo;
39 
42 
45 
47  private $nsInfo;
48 
55  public function __construct(
56  RepoGroup $repoGroup = null,
59  NamespaceInfo $nsInfo = null
60  ) {
61  parent::__construct( 'Upload', 'upload' );
62  // This class is extended and therefor fallback to global state - T265300
63  $services = MediaWikiServices::getInstance();
64  $repoGroup = $repoGroup ?? $services->getRepoGroup();
65  $this->localRepo = $repoGroup->getLocalRepo();
66  $this->permissionManager = $permissionManager ?? $services->getPermissionManager();
67  $this->userOptionsLookup = $userOptionsLookup ?? $services->getUserOptionsLookup();
68  $this->nsInfo = $nsInfo ?? $services->getNamespaceInfo();
69  }
70 
71  public function doesWrites() {
72  return true;
73  }
74 
78  public $mRequest;
79  public $mSourceType;
80 
82  public $mUpload;
83 
85  public $mLocalFile;
87 
92  public $mComment;
93  public $mLicense;
94 
98  public $mWatchthis;
101 
105 
108 
111  public $mTokenOk;
112 
114  public $mUploadSuccessful = false;
115 
119 
123  protected function loadRequest() {
124  $this->mRequest = $request = $this->getRequest();
125  $this->mSourceType = $request->getVal( 'wpSourceType', 'file' );
126  $this->mUpload = UploadBase::createFromRequest( $request );
127  $this->mUploadClicked = $request->wasPosted()
128  && ( $request->getCheck( 'wpUpload' )
129  || $request->getCheck( 'wpUploadIgnoreWarning' ) );
130 
131  // Guess the desired name from the filename if not provided
132  $this->mDesiredDestName = $request->getText( 'wpDestFile' );
133  if ( !$this->mDesiredDestName && $request->getFileName( 'wpUploadFile' ) !== null ) {
134  $this->mDesiredDestName = $request->getFileName( 'wpUploadFile' );
135  }
136  $this->mLicense = $request->getText( 'wpLicense' );
137 
138  $this->mDestWarningAck = $request->getText( 'wpDestFileWarningAck' );
139  $this->mIgnoreWarning = $request->getCheck( 'wpIgnoreWarning' )
140  || $request->getCheck( 'wpUploadIgnoreWarning' );
141  $this->mWatchthis = $request->getBool( 'wpWatchthis' ) && $this->getUser()->isLoggedIn();
142  $this->mCopyrightStatus = $request->getText( 'wpUploadCopyStatus' );
143  $this->mCopyrightSource = $request->getText( 'wpUploadSource' );
144 
145  $this->mForReUpload = $request->getBool( 'wpForReUpload' ); // updating a file
146 
147  $commentDefault = '';
148  $commentMsg = $this->msg( 'upload-default-description' )->inContentLanguage();
149  if ( !$this->mForReUpload && !$commentMsg->isDisabled() ) {
150  $commentDefault = $commentMsg->plain();
151  }
152  $this->mComment = $request->getText( 'wpUploadDescription', $commentDefault );
153 
154  $this->mCancelUpload = $request->getCheck( 'wpCancelUpload' )
155  || $request->getCheck( 'wpReUpload' ); // b/w compat
156 
157  // If it was posted check for the token (no remote POST'ing with user credentials)
158  $token = $request->getVal( 'wpEditToken' );
159  $this->mTokenOk = $this->getUser()->matchEditToken( $token );
160 
161  $this->uploadFormTextTop = '';
162  $this->uploadFormTextAfterSummary = '';
163  }
164 
173  public function userCanExecute( User $user ) {
174  return UploadBase::isEnabled() && parent::userCanExecute( $user );
175  }
176 
187  public function execute( $par ) {
188  $this->useTransactionalTimeLimit();
189 
190  $this->setHeaders();
191  $this->outputHeader();
192 
193  # Check uploading enabled
194  if ( !UploadBase::isEnabled() ) {
195  throw new ErrorPageError( 'uploaddisabled', 'uploaddisabledtext' );
196  }
197 
198  $this->addHelpLink( 'Help:Managing files' );
199 
200  # Check permissions
201  $user = $this->getUser();
202  $permissionRequired = UploadBase::isAllowed( $user );
203  if ( $permissionRequired !== true ) {
204  throw new PermissionsError( $permissionRequired );
205  }
206 
207  # Check blocks
208  if ( $user->isBlockedFromUpload() ) {
209  throw new UserBlockedError(
210  $user->getBlock(),
211  $user,
212  $this->getLanguage(),
213  $this->getRequest()->getIP()
214  );
215  }
216 
217  // Global blocks
218  if ( $user->isBlockedGlobally() ) {
219  throw new UserBlockedError(
220  $user->getGlobalBlock(),
221  $user,
222  $this->getLanguage(),
223  $this->getRequest()->getIP()
224  );
225  }
226 
227  # Check whether we actually want to allow changing stuff
228  $this->checkReadOnly();
229 
230  $this->loadRequest();
231 
232  # Unsave the temporary file in case this was a cancelled upload
233  if ( $this->mCancelUpload && !$this->unsaveUploadedFile() ) {
234  # Something went wrong, so unsaveUploadedFile showed a warning
235  return;
236  }
237 
238  # Process upload or show a form
239  if (
240  $this->mTokenOk && !$this->mCancelUpload &&
241  ( $this->mUpload && $this->mUploadClicked )
242  ) {
243  $this->processUpload();
244  } else {
245  # Backwards compatibility hook
246  if ( !$this->getHookRunner()->onUploadForm_initial( $this ) ) {
247  wfDebug( "Hook 'UploadForm:initial' broke output of the upload form" );
248 
249  return;
250  }
251  $this->showUploadForm( $this->getUploadForm() );
252  }
253 
254  # Cleanup
255  if ( $this->mUpload ) {
256  $this->mUpload->cleanupTempFile();
257  }
258  }
259 
265  protected function showUploadForm( $form ) {
266  # Add links if file was previously deleted
267  if ( $this->mDesiredDestName ) {
268  $this->showViewDeletedLinks();
269  }
270 
271  if ( $form instanceof HTMLForm ) {
272  $form->show();
273  } else {
274  $this->getOutput()->addHTML( $form );
275  }
276  }
277 
286  protected function getUploadForm( $message = '', $sessionKey = '', $hideIgnoreWarning = false ) {
287  # Initialize form
288  $context = new DerivativeContext( $this->getContext() );
289  $context->setTitle( $this->getPageTitle() ); // Remove subpage
290  $form = new UploadForm(
291  [
292  'watch' => $this->getWatchCheck(),
293  'forreupload' => $this->mForReUpload,
294  'sessionkey' => $sessionKey,
295  'hideignorewarning' => $hideIgnoreWarning,
296  'destwarningack' => (bool)$this->mDestWarningAck,
297 
298  'description' => $this->mComment,
299  'texttop' => $this->uploadFormTextTop,
300  'textaftersummary' => $this->uploadFormTextAfterSummary,
301  'destfile' => $this->mDesiredDestName,
302  ],
303  $context,
304  $this->getLinkRenderer(),
305  $this->permissionManager,
306  $this->localRepo,
307  $this->getContentLanguage(),
308  $this->nsInfo
309  );
310 
311  # Check the token, but only if necessary
312  if (
313  !$this->mTokenOk && !$this->mCancelUpload &&
314  ( $this->mUpload && $this->mUploadClicked )
315  ) {
316  $form->addPreText( $this->msg( 'session_fail_preview' )->parse() );
317  }
318 
319  # Give a notice if the user is uploading a file that has been deleted or moved
320  # Note that this is independent from the message 'filewasdeleted'
321  $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
322  $delNotice = ''; // empty by default
323  if ( $desiredTitleObj instanceof Title && !$desiredTitleObj->exists() ) {
324  LogEventsList::showLogExtract( $delNotice, [ 'delete', 'move' ],
325  $desiredTitleObj,
326  '', [ 'lim' => 10,
327  'conds' => [ 'log_action != ' . $this->localRepo->getReplicaDB()->addQuotes( 'revision' ) ],
328  'showIfEmpty' => false,
329  'msgKey' => [ 'upload-recreate-warning' ] ]
330  );
331  }
332  $form->addPreText( $delNotice );
333 
334  # Add text to form
335  $form->addPreText( '<div id="uploadtext">' .
336  $this->msg( 'uploadtext', [ $this->mDesiredDestName ] )->parseAsBlock() .
337  '</div>' );
338  # Add upload error message
339  $form->addPreText( $message );
340 
341  # Add footer to form
342  $uploadFooter = $this->msg( 'uploadfooter' );
343  if ( !$uploadFooter->isDisabled() ) {
344  $form->addPostText( '<div id="mw-upload-footer-message">'
345  . $uploadFooter->parseAsBlock() . "</div>\n" );
346  }
347 
348  return $form;
349  }
350 
354  protected function showViewDeletedLinks() {
355  $title = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
356  $user = $this->getUser();
357  // Show a subtitle link to deleted revisions (to sysops et al only)
358  if ( $title instanceof Title ) {
359  $count = $title->getDeletedEditsCount();
360  if ( $count > 0 && $this->permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
361  $restorelink = $this->getLinkRenderer()->makeKnownLink(
362  SpecialPage::getTitleFor( 'Undelete', $title->getPrefixedText() ),
363  $this->msg( 'restorelink' )->numParams( $count )->text()
364  );
365  $link = $this->msg(
366  $this->permissionManager->userHasRight( $user, 'delete' ) ? 'thisisdeleted' : 'viewdeleted'
367  )->rawParams( $restorelink )->parseAsBlock();
368  $this->getOutput()->addHTML(
370  'div',
371  [ 'id' => 'contentSub2' ],
372  $link
373  )
374  );
375  }
376  }
377  }
378 
390  protected function showRecoverableUploadError( $message ) {
391  $stashStatus = $this->mUpload->tryStashFile( $this->getUser() );
392  if ( $stashStatus->isGood() ) {
393  $sessionKey = $stashStatus->getValue()->getFileKey();
394  $uploadWarning = 'upload-tryagain';
395  } else {
396  $sessionKey = null;
397  $uploadWarning = 'upload-tryagain-nostash';
398  }
399  $message = '<h2>' . $this->msg( 'uploaderror' )->escaped() . "</h2>\n" .
400  '<div class="error">' . $message . "</div>\n";
401 
402  $form = $this->getUploadForm( $message, $sessionKey );
403  $form->setSubmitText( $this->msg( $uploadWarning )->escaped() );
404  $this->showUploadForm( $form );
405  }
406 
415  protected function showUploadWarning( $warnings ) {
416  # If there are no warnings, or warnings we can ignore, return early.
417  # mDestWarningAck is set when some javascript has shown the warning
418  # to the user. mForReUpload is set when the user clicks the "upload a
419  # new version" link.
420  if ( !$warnings || ( count( $warnings ) == 1
421  && isset( $warnings['exists'] )
422  && ( $this->mDestWarningAck || $this->mForReUpload ) )
423  ) {
424  return false;
425  }
426 
427  $stashStatus = $this->mUpload->tryStashFile( $this->getUser() );
428  if ( $stashStatus->isGood() ) {
429  $sessionKey = $stashStatus->getValue()->getFileKey();
430  $uploadWarning = 'uploadwarning-text';
431  } else {
432  $sessionKey = null;
433  $uploadWarning = 'uploadwarning-text-nostash';
434  }
435 
436  // Add styles for the warning, reused from the live preview
437  $this->getOutput()->addModuleStyles( 'mediawiki.special' );
438 
439  $linkRenderer = $this->getLinkRenderer();
440  $warningHtml = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . "</h2>\n"
441  . '<div class="mw-destfile-warning"><ul>';
442  foreach ( $warnings as $warning => $args ) {
443  if ( $warning == 'badfilename' ) {
444  $this->mDesiredDestName = Title::makeTitle( NS_FILE, $args )->getText();
445  }
446  if ( $warning == 'exists' ) {
447  $msg = "\t<li>" . self::getExistsWarning( $args ) . "</li>\n";
448  } elseif ( $warning == 'no-change' ) {
449  $file = $args;
450  $filename = $file->getTitle()->getPrefixedText();
451  $msg = "\t<li>" . $this->msg( 'fileexists-no-change', $filename )->parse() . "</li>\n";
452  } elseif ( $warning == 'duplicate-version' ) {
453  $file = $args[0];
454  $count = count( $args );
455  $filename = $file->getTitle()->getPrefixedText();
456  $message = $this->msg( 'fileexists-duplicate-version' )
457  ->params( $filename )
458  ->numParams( $count );
459  $msg = "\t<li>" . $message->parse() . "</li>\n";
460  } elseif ( $warning == 'was-deleted' ) {
461  # If the file existed before and was deleted, warn the user of this
462  $ltitle = SpecialPage::getTitleFor( 'Log' );
463  $llink = $linkRenderer->makeKnownLink(
464  $ltitle,
465  $this->msg( 'deletionlog' )->text(),
466  [],
467  [
468  'type' => 'delete',
469  'page' => Title::makeTitle( NS_FILE, $args )->getPrefixedText(),
470  ]
471  );
472  $msg = "\t<li>" . $this->msg( 'filewasdeleted' )->rawParams( $llink )->parse() . "</li>\n";
473  } elseif ( $warning == 'duplicate' ) {
474  $msg = $this->getDupeWarning( $args );
475  } elseif ( $warning == 'duplicate-archive' ) {
476  if ( $args === '' ) {
477  $msg = "\t<li>" . $this->msg( 'file-deleted-duplicate-notitle' )->parse()
478  . "</li>\n";
479  } else {
480  $msg = "\t<li>" . $this->msg( 'file-deleted-duplicate',
481  Title::makeTitle( NS_FILE, $args )->getPrefixedText() )->parse()
482  . "</li>\n";
483  }
484  } else {
485  if ( $args === true ) {
486  $args = [];
487  } elseif ( !is_array( $args ) ) {
488  $args = [ $args ];
489  }
490  $msg = "\t<li>" . $this->msg( $warning, $args )->parse() . "</li>\n";
491  }
492  $warningHtml .= $msg;
493  }
494  $warningHtml .= "</ul></div>\n";
495  $warningHtml .= $this->msg( $uploadWarning )->parseAsBlock();
496 
497  $form = $this->getUploadForm( $warningHtml, $sessionKey, /* $hideIgnoreWarning */ true );
498  $form->setSubmitText( $this->msg( 'upload-tryagain' )->text() );
499  $form->addButton( [
500  'name' => 'wpUploadIgnoreWarning',
501  'value' => $this->msg( 'ignorewarning' )->text()
502  ] );
503  $form->addButton( [
504  'name' => 'wpCancelUpload',
505  'value' => $this->msg( 'reuploaddesc' )->text()
506  ] );
507 
508  $this->showUploadForm( $form );
509 
510  # Indicate that we showed a form
511  return true;
512  }
513 
519  protected function showUploadError( $message ) {
520  $message = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . "</h2>\n" .
521  '<div class="error">' . $message . "</div>\n";
522  $this->showUploadForm( $this->getUploadForm( $message ) );
523  }
524 
529  protected function processUpload() {
530  // Fetch the file if required
531  $status = $this->mUpload->fetchFile();
532  if ( !$status->isOK() ) {
533  $this->showUploadError( $this->getOutput()->parseAsInterface(
534  $status->getWikiText( false, false, $this->getLanguage() )
535  ) );
536 
537  return;
538  }
539  if ( !$this->getHookRunner()->onUploadForm_BeforeProcessing( $this ) ) {
540  wfDebug( "Hook 'UploadForm:BeforeProcessing' broke processing the file." );
541  // This code path is deprecated. If you want to break upload processing
542  // do so by hooking into the appropriate hooks in UploadBase::verifyUpload
543  // and UploadBase::verifyFile.
544  // If you use this hook to break uploading, the user will be returned
545  // an empty form with no error message whatsoever.
546  return;
547  }
548 
549  // Upload verification
550  $details = $this->mUpload->verifyUpload();
551  if ( $details['status'] != UploadBase::OK ) {
552  $this->processVerificationError( $details );
553 
554  return;
555  }
556 
557  // Verify permissions for this title
558  $user = $this->getUser();
559  $permErrors = $this->mUpload->verifyTitlePermissions( $user );
560  if ( $permErrors !== true ) {
561  $code = array_shift( $permErrors[0] );
562  $this->showRecoverableUploadError( $this->msg( $code, $permErrors[0] )->parse() );
563 
564  return;
565  }
566 
567  $this->mLocalFile = $this->mUpload->getLocalFile();
568 
569  // Check warnings if necessary
570  if ( !$this->mIgnoreWarning ) {
571  $warnings = $this->mUpload->checkWarnings( $user );
572  if ( $this->showUploadWarning( $warnings ) ) {
573  return;
574  }
575  }
576 
577  // This is as late as we can throttle, after expected issues have been handled
578  if ( UploadBase::isThrottled( $user ) ) {
580  $this->msg( 'actionthrottledtext' )->escaped()
581  );
582  return;
583  }
584 
585  // Get the page text if this is not a reupload
586  if ( !$this->mForReUpload ) {
587  $pageText = self::getInitialPageText( $this->mComment, $this->mLicense,
588  $this->mCopyrightStatus, $this->mCopyrightSource, $this->getConfig() );
589  } else {
590  $pageText = false;
591  }
592 
593  $changeTags = $this->getRequest()->getVal( 'wpChangeTags' );
594  if ( $changeTags === null || $changeTags === '' ) {
595  $changeTags = [];
596  } else {
597  $changeTags = array_filter( array_map( 'trim', explode( ',', $changeTags ) ) );
598  }
599 
600  if ( $changeTags ) {
601  $changeTagsStatus = ChangeTags::canAddTagsAccompanyingChange(
602  $changeTags, $user );
603  if ( !$changeTagsStatus->isOK() ) {
604  $this->showUploadError( $this->getOutput()->parseAsInterface(
605  $changeTagsStatus->getWikiText( false, false, $this->getLanguage() )
606  ) );
607 
608  return;
609  }
610  }
611 
612  $status = $this->mUpload->performUpload(
613  $this->mComment,
614  $pageText,
615  $this->mWatchthis,
616  $user,
617  $changeTags
618  );
619 
620  if ( !$status->isGood() ) {
622  $this->getOutput()->parseAsInterface(
623  $status->getWikiText( false, false, $this->getLanguage() )
624  )
625  );
626 
627  return;
628  }
629 
630  // Success, redirect to description page
631  $this->mUploadSuccessful = true;
632  $this->getHookRunner()->onSpecialUploadComplete( $this );
633  $this->getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
634  }
635 
645  public static function getInitialPageText( $comment = '', $license = '',
646  $copyStatus = '', $source = '', Config $config = null
647  ) {
648  if ( $config === null ) {
649  wfDebug( __METHOD__ . ' called without a Config instance passed to it' );
650  $config = MediaWikiServices::getInstance()->getMainConfig();
651  }
652 
653  $msg = [];
654  $forceUIMsgAsContentMsg = (array)$config->get( 'ForceUIMsgAsContentMsg' );
655  /* These messages are transcluded into the actual text of the description page.
656  * Thus, forcing them as content messages makes the upload to produce an int: template
657  * instead of hardcoding it there in the uploader language.
658  */
659  foreach ( [ 'license-header', 'filedesc', 'filestatus', 'filesource' ] as $msgName ) {
660  if ( in_array( $msgName, $forceUIMsgAsContentMsg ) ) {
661  $msg[$msgName] = "{{int:$msgName}}";
662  } else {
663  $msg[$msgName] = wfMessage( $msgName )->inContentLanguage()->text();
664  }
665  }
666 
667  $licenseText = '';
668  if ( $license !== '' ) {
669  $licenseText = '== ' . $msg['license-header'] . " ==\n{{" . $license . "}}\n";
670  }
671 
672  $pageText = $comment . "\n";
673  $headerText = '== ' . $msg['filedesc'] . ' ==';
674  if ( $comment !== '' && strpos( $comment, $headerText ) === false ) {
675  // prepend header to page text unless it's already there (or there is no content)
676  $pageText = $headerText . "\n" . $pageText;
677  }
678 
679  if ( $config->get( 'UseCopyrightUpload' ) ) {
680  $pageText .= '== ' . $msg['filestatus'] . " ==\n" . $copyStatus . "\n";
681  $pageText .= $licenseText;
682  $pageText .= '== ' . $msg['filesource'] . " ==\n" . $source;
683  } else {
684  $pageText .= $licenseText;
685  }
686 
687  // allow extensions to modify the content
688  Hooks::runner()->onUploadForm_getInitialPageText( $pageText, $msg, $config );
689 
690  return $pageText;
691  }
692 
705  protected function getWatchCheck() {
706  $user = $this->getUser();
707  if ( $this->userOptionsLookup->getBoolOption( $user, 'watchdefault' ) ) {
708  // Watch all edits!
709  return true;
710  }
711 
712  $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
713  if ( $desiredTitleObj instanceof Title && $user->isWatched( $desiredTitleObj ) ) {
714  // Already watched, don't change that
715  return true;
716  }
717 
718  $local = $this->localRepo->newFile( $this->mDesiredDestName );
719  if ( $local && $local->exists() ) {
720  // We're uploading a new version of an existing file.
721  // No creation, so don't watch it if we're not already.
722  return false;
723  } else {
724  // New page should get watched if that's our option.
725  return $this->userOptionsLookup->getBoolOption( $user, 'watchcreations' ) ||
726  $this->userOptionsLookup->getBoolOption( $user, 'watchuploads' );
727  }
728  }
729 
736  protected function processVerificationError( $details ) {
737  switch ( $details['status'] ) {
740  $this->showRecoverableUploadError( $this->msg( 'minlength1' )->escaped() );
741  break;
743  $this->showRecoverableUploadError( $this->msg( 'illegalfilename',
744  $details['filtered'] )->parse() );
745  break;
747  $this->showRecoverableUploadError( $this->msg( 'filename-toolong' )->escaped() );
748  break;
750  $this->showRecoverableUploadError( $this->msg( 'filetype-missing' )->parse() );
751  break;
753  $this->showRecoverableUploadError( $this->msg( 'windows-nonascii-filename' )->parse() );
754  break;
755 
758  $this->showUploadError( $this->msg( 'emptyfile' )->escaped() );
759  break;
761  $this->showUploadError( $this->msg( 'largefileserver' )->escaped() );
762  break;
764  $msg = $this->msg( 'filetype-banned-type' );
765  if ( isset( $details['blacklistedExt'] ) ) {
766  $msg->params( $this->getLanguage()->commaList( $details['blacklistedExt'] ) );
767  } else {
768  $msg->params( $details['finalExt'] );
769  }
770  $extensions = array_unique( $this->getConfig()->get( 'FileExtensions' ) );
771  $msg->params( $this->getLanguage()->commaList( $extensions ),
772  count( $extensions ) );
773 
774  // Add PLURAL support for the first parameter. This results
775  // in a bit unlogical parameter sequence, but does not break
776  // old translations
777  if ( isset( $details['blacklistedExt'] ) ) {
778  $msg->params( count( $details['blacklistedExt'] ) );
779  } else {
780  $msg->params( 1 );
781  }
782 
783  $this->showUploadError( $msg->parse() );
784  break;
786  unset( $details['status'] );
787  $code = array_shift( $details['details'] );
788  $this->showUploadError( $this->msg( $code, $details['details'] )->parse() );
789  break;
791  if ( is_array( $details['error'] ) ) { # allow hooks to return error details in an array
792  $args = $details['error'];
793  $error = array_shift( $args );
794  } else {
795  $error = $details['error'];
796  $args = null;
797  }
798 
799  $this->showUploadError( $this->msg( $error, $args )->parse() );
800  break;
801  default:
802  throw new MWException( __METHOD__ . ": Unknown value `{$details['status']}`" );
803  }
804  }
805 
811  protected function unsaveUploadedFile() {
812  if ( !( $this->mUpload instanceof UploadFromStash ) ) {
813  return true;
814  }
815  $success = $this->mUpload->unsaveUploadedFile();
816  if ( !$success ) {
817  $this->getOutput()->showFatalError(
818  $this->msg( 'filedeleteerror' )
819  ->params( $this->mUpload->getTempPath() )
820  ->escaped()
821  );
822 
823  return false;
824  } else {
825  return true;
826  }
827  }
828 
838  public static function getExistsWarning( $exists ) {
839  if ( !$exists ) {
840  return '';
841  }
842 
843  $file = $exists['file'];
844  $filename = $file->getTitle()->getPrefixedText();
845  $warnMsg = null;
846 
847  if ( $exists['warning'] == 'exists' ) {
848  // Exact match
849  $warnMsg = wfMessage( 'fileexists', $filename );
850  } elseif ( $exists['warning'] == 'page-exists' ) {
851  // Page exists but file does not
852  $warnMsg = wfMessage( 'filepageexists', $filename );
853  } elseif ( $exists['warning'] == 'exists-normalized' ) {
854  $warnMsg = wfMessage( 'fileexists-extension', $filename,
855  $exists['normalizedFile']->getTitle()->getPrefixedText() );
856  } elseif ( $exists['warning'] == 'thumb' ) {
857  // Swapped argument order compared with other messages for backwards compatibility
858  $warnMsg = wfMessage( 'fileexists-thumbnail-yes',
859  $exists['thumbFile']->getTitle()->getPrefixedText(), $filename );
860  } elseif ( $exists['warning'] == 'thumb-name' ) {
861  // Image w/o '180px-' does not exists, but we do not like these filenames
862  $name = $file->getName();
863  $badPart = substr( $name, 0, strpos( $name, '-' ) + 1 );
864  $warnMsg = wfMessage( 'file-thumbnail-no', $badPart );
865  } elseif ( $exists['warning'] == 'bad-prefix' ) {
866  $warnMsg = wfMessage( 'filename-bad-prefix', $exists['prefix'] );
867  }
868 
869  return $warnMsg ? $warnMsg->title( $file->getTitle() )->parse() : '';
870  }
871 
877  public function getDupeWarning( $dupes ) {
878  if ( !$dupes ) {
879  return '';
880  }
881 
882  $gallery = ImageGalleryBase::factory( false, $this->getContext() );
883  $gallery->setShowBytes( false );
884  $gallery->setShowDimensions( false );
885  foreach ( $dupes as $file ) {
886  $gallery->add( $file->getTitle() );
887  }
888 
889  return '<li>' .
890  $this->msg( 'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
891  $gallery->toHTML() . "</li>\n";
892  }
893 
894  protected function getGroupName() {
895  return 'media';
896  }
897 
906  public static function rotationEnabled() {
907  $bitmapHandler = new BitmapHandler();
908  return $bitmapHandler->autoRotateEnabled();
909  }
910 }
UploadBase
UploadBase and subclasses are the backend of MediaWiki's file uploads.
Definition: UploadBase.php:45
SpecialPage\$linkRenderer
LinkRenderer null $linkRenderer
Definition: SpecialPage.php:79
SpecialPage\getPageTitle
getPageTitle( $subpage=false)
Get a self-referential title object.
Definition: SpecialPage.php:742
SpecialUpload\getInitialPageText
static getInitialPageText( $comment='', $license='', $copyStatus='', $source='', Config $config=null)
Get the initial image page text based on a comment and optional file status information.
Definition: SpecialUpload.php:645
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:900
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: FauxRequest.php:35
UploadBase\VERIFICATION_ERROR
const VERIFICATION_ERROR
Definition: UploadBase.php:108
SpecialUpload\userCanExecute
userCanExecute(User $user)
This page can be shown if uploading is enabled.
Definition: SpecialUpload.php:173
UploadBase\isAllowed
static isAllowed(UserIdentity $user)
Returns true if the user can use this upload module or else a string identifying the missing permissi...
Definition: UploadBase.php:155
UserBlockedError
Show an error when the user tries to do something whilst blocked.
Definition: UserBlockedError.php:31
UploadBase\isThrottled
static isThrottled( $user)
Returns true if the user has surpassed the upload rate limit, false otherwise.
Definition: UploadBase.php:172
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:788
UploadBase\FILE_TOO_LARGE
const FILE_TOO_LARGE
Definition: UploadBase.php:110
UploadBase\MIN_LENGTH_PARTNAME
const MIN_LENGTH_PARTNAME
Definition: UploadBase.php:103
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:165
SpecialUpload\$mSourceType
$mSourceType
Definition: SpecialUpload.php:79
SpecialUpload\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: SpecialUpload.php:894
SpecialUpload\doesWrites
doesWrites()
Indicates whether this special page may perform database writes.
Definition: SpecialUpload.php:71
UploadBase\isEnabled
static isEnabled()
Returns true if uploads are enabled.
Definition: UploadBase.php:141
SpecialUpload\$mUploadClicked
$mUploadClicked
Definition: SpecialUpload.php:86
UploadForm
Sub class of HTMLForm that provides the form section of SpecialUpload.
Definition: UploadForm.php:28
NS_FILE
const NS_FILE
Definition: Defines.php:75
SpecialUpload\processUpload
processUpload()
Do the upload.
Definition: SpecialUpload.php:529
$file
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
SpecialUpload\$mCopyrightStatus
$mCopyrightStatus
Definition: SpecialUpload.php:99
SpecialUpload\unsaveUploadedFile
unsaveUploadedFile()
Remove a temporarily kept file stashed by saveTempUploadedFile().
Definition: SpecialUpload.php:811
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1220
SpecialPage\getTitleFor
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,...
Definition: SpecialPage.php:106
UploadFromStash
Implements uploading from previously stored file.
Definition: UploadFromStash.php:32
SpecialUpload\$mLocalFile
LocalFile $mLocalFile
Definition: SpecialUpload.php:85
UploadBase\HOOK_ABORTED
const HOOK_ABORTED
Definition: UploadBase.php:109
SpecialPage\useTransactionalTimeLimit
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
Definition: SpecialPage.php:1006
UploadBase\OK
const OK
Definition: UploadBase.php:101
PermissionsError
Show an error when a user tries to do something they do not have the necessary permissions for.
Definition: PermissionsError.php:31
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:818
$success
$success
Definition: NoLocalSettings.php:42
SpecialUpload\showViewDeletedLinks
showViewDeletedLinks()
Shows the "view X deleted revivions link"".
Definition: SpecialUpload.php:354
SpecialUpload\$permissionManager
PermissionManager $permissionManager
Definition: SpecialUpload.php:41
UploadBase\EMPTY_FILE
const EMPTY_FILE
Definition: UploadBase.php:102
SpecialUpload\$mDestWarningAck
$mDestWarningAck
Hidden variables.
Definition: SpecialUpload.php:104
SpecialUpload\getExistsWarning
static getExistsWarning( $exists)
Functions for formatting warnings.
Definition: SpecialUpload.php:838
SpecialUpload\$userOptionsLookup
UserOptionsLookup $userOptionsLookup
Definition: SpecialUpload.php:44
SpecialUpload\showUploadWarning
showUploadWarning( $warnings)
Stashes the upload, shows the main form, but adds a "continue anyway button".
Definition: SpecialUpload.php:415
SpecialUpload\getDupeWarning
getDupeWarning( $dupes)
Construct a warning and a gallery from an array of duplicate files.
Definition: SpecialUpload.php:877
SpecialUpload\showRecoverableUploadError
showRecoverableUploadError( $message)
Stashes the upload and shows the main upload form.
Definition: SpecialUpload.php:390
Config
Interface for configuration instances.
Definition: Config.php:30
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:31
SpecialPage\addHelpLink
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
Definition: SpecialPage.php:936
SpecialPage\getHookRunner
getHookRunner()
Definition: SpecialPage.php:1083
MWException
MediaWiki exception.
Definition: MWException.php:29
SpecialPage\getConfig
getConfig()
Shortcut to get main config object.
Definition: SpecialPage.php:866
SpecialUpload\$mRequest
WebRequest FauxRequest $mRequest
Misc variables.
Definition: SpecialUpload.php:78
BitmapHandler
Generic handler for bitmap images.
Definition: BitmapHandler.php:32
SpecialUpload\$mDesiredDestName
string $mDesiredDestName
User input variables from the "description" section.
Definition: SpecialUpload.php:91
SpecialUpload\$uploadFormTextAfterSummary
$uploadFormTextAfterSummary
Definition: SpecialUpload.php:118
UploadBase\WINDOWS_NONASCII_FILENAME
const WINDOWS_NONASCII_FILENAME
Definition: UploadBase.php:111
SpecialUpload\$mCancelUpload
bool $mCancelUpload
The user clicked "Cancel and return to upload form" button.
Definition: SpecialUpload.php:110
$args
if( $line===false) $args
Definition: mcc.php:124
SpecialUpload\$nsInfo
NamespaceInfo $nsInfo
Definition: SpecialUpload.php:47
SpecialUpload\execute
execute( $par)
Definition: SpecialUpload.php:187
SpecialUpload\$mCopyrightSource
$mCopyrightSource
Definition: SpecialUpload.php:100
$title
$title
Definition: testCompression.php:38
SpecialPage\setHeaders
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!...
Definition: SpecialPage.php:616
SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
Definition: SpecialPage.php:798
SpecialUpload\$mUpload
UploadBase $mUpload
Definition: SpecialUpload.php:82
Title\makeTitle
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:591
LogEventsList\showLogExtract
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
Definition: LogEventsList.php:618
SpecialUpload\$mComment
$mComment
Definition: SpecialUpload.php:92
SpecialUpload\loadRequest
loadRequest()
Initialize instance variables from request and create an Upload handler.
Definition: SpecialUpload.php:123
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:910
LocalFile
Class to represent a local file in the wiki's own database.
Definition: LocalFile.php:59
SpecialUpload
Form for handling uploads and special page.
Definition: SpecialUpload.php:35
SpecialPage\getContext
getContext()
Gets the context this SpecialPage is executed in.
Definition: SpecialPage.php:762
SpecialUpload\$mForReUpload
bool $mForReUpload
The user followed an "overwrite this file" link.
Definition: SpecialUpload.php:107
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:617
MediaWiki\Permissions\PermissionManager
A service class for checking permissions To obtain an instance, use MediaWikiServices::getInstance()-...
Definition: PermissionManager.php:50
SpecialUpload\$mLicense
$mLicense
Definition: SpecialUpload.php:93
SpecialUpload\__construct
__construct(RepoGroup $repoGroup=null, PermissionManager $permissionManager=null, UserOptionsLookup $userOptionsLookup=null, NamespaceInfo $nsInfo=null)
Definition: SpecialUpload.php:55
SpecialPage
Parent class for all special pages.
Definition: SpecialPage.php:42
SpecialUpload\getUploadForm
getUploadForm( $message='', $sessionKey='', $hideIgnoreWarning=false)
Get an UploadForm instance with title and text properly set.
Definition: SpecialUpload.php:286
SpecialUpload\rotationEnabled
static rotationEnabled()
Should we rotate images in the preview on Special:Upload.
Definition: SpecialUpload.php:906
SpecialUpload\showUploadError
showUploadError( $message)
Show the upload form with error message, but do not stash the file.
Definition: SpecialUpload.php:519
Hooks\runner
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
Definition: Hooks.php:172
SpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: SpecialPage.php:778
SpecialUpload\showUploadForm
showUploadForm( $form)
Show the main upload form.
Definition: SpecialUpload.php:265
UploadBase\FILENAME_TOO_LONG
const FILENAME_TOO_LONG
Definition: UploadBase.php:112
MediaWiki\User\UserOptionsLookup
Provides access to user options.
Definition: UserOptionsLookup.php:29
UploadBase\ILLEGAL_FILENAME
const ILLEGAL_FILENAME
Definition: UploadBase.php:104
WebRequest
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:42
UploadBase\createFromRequest
static createFromRequest(&$request, $type=null)
Create a form of UploadBase depending on wpSourceType and initializes it.
Definition: UploadBase.php:186
SpecialPage\getLinkRenderer
getLinkRenderer()
Definition: SpecialPage.php:1016
ChangeTags\canAddTagsAccompanyingChange
static canAddTagsAccompanyingChange(array $tags, User $user=null)
Is it OK to allow the user to apply all the specified tags at the same time as they edit/make the cha...
Definition: ChangeTags.php:598
Title
Represents a title within MediaWiki.
Definition: Title.php:41
SpecialUpload\$mWatchthis
$mWatchthis
Definition: SpecialUpload.php:98
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:212
getTitle
getTitle()
Definition: RevisionSearchResultTrait.php:81
RepoGroup
Prioritized list of file repositories.
Definition: RepoGroup.php:31
Title\exists
exists( $flags=0)
Check if page exists.
Definition: Title.php:3927
$source
$source
Definition: mwdoc-filter.php:34
ImageGalleryBase\factory
static factory( $mode=false, IContextSource $context=null)
Get a new image gallery.
Definition: ImageGalleryBase.php:116
NamespaceInfo
This is a utility class for dealing with namespaces that encodes all the "magic" behaviors of them ba...
Definition: NamespaceInfo.php:35
SpecialPage\getContentLanguage
getContentLanguage()
Shortcut to get content language.
Definition: SpecialPage.php:828
SpecialPage\checkReadOnly
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
Definition: SpecialPage.php:369
SpecialUpload\processVerificationError
processVerificationError( $details)
Provides output to the user for a result of UploadBase::verifyUpload.
Definition: SpecialUpload.php:736
ErrorPageError
An error page which can definitely be safely rendered using the OutputPage.
Definition: ErrorPageError.php:30
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:56
SpecialUpload\$uploadFormTextTop
$uploadFormTextTop
Text injection points for hooks not using HTMLForm.
Definition: SpecialUpload.php:117
SpecialUpload\$mUploadSuccessful
bool $mUploadSuccessful
Subclasses can use this to determine whether a file was uploaded.
Definition: SpecialUpload.php:114
SpecialPage\outputHeader
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
Definition: SpecialPage.php:707
SpecialUpload\$mTokenOk
$mTokenOk
Definition: SpecialUpload.php:111
SpecialUpload\$mIgnoreWarning
$mIgnoreWarning
User input variables from the root section.
Definition: SpecialUpload.php:97
LocalRepo
A repository that stores files in the local filesystem and registers them in the wiki's own database.
Definition: LocalRepo.php:37
SpecialUpload\getWatchCheck
getWatchCheck()
See if we should check the 'watch this page' checkbox on the form based on the user's preferences and...
Definition: SpecialUpload.php:705
SpecialUpload\$localRepo
LocalRepo $localRepo
Definition: SpecialUpload.php:38
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:135
UploadBase\FILETYPE_MISSING
const FILETYPE_MISSING
Definition: UploadBase.php:106
UploadBase\FILETYPE_BADTYPE
const FILETYPE_BADTYPE
Definition: UploadBase.php:107