MediaWiki  master
SpecialUpload.php
Go to the documentation of this file.
1 <?php
26 
33 class SpecialUpload extends SpecialPage {
38  public function __construct( $request = null ) {
39  parent::__construct( 'Upload', 'upload' );
40  }
41 
42  public function doesWrites() {
43  return true;
44  }
45 
49  public $mRequest;
50  public $mSourceType;
51 
53  public $mUpload;
54 
56  public $mLocalFile;
58 
63  public $mComment;
64  public $mLicense;
65 
69  public $mWatchthis;
72 
76 
78  public $mForReUpload;
79 
82  public $mTokenOk;
83 
85  public $mUploadSuccessful = false;
86 
90 
94  protected function loadRequest() {
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' ) );
101 
102  // Guess the desired name from the filename if not provided
103  $this->mDesiredDestName = $request->getText( 'wpDestFile' );
104  if ( !$this->mDesiredDestName && $request->getFileName( 'wpUploadFile' ) !== null ) {
105  $this->mDesiredDestName = $request->getFileName( 'wpUploadFile' );
106  }
107  $this->mLicense = $request->getText( 'wpLicense' );
108 
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' );
115 
116  $this->mForReUpload = $request->getBool( 'wpForReUpload' ); // updating a file
117 
118  $commentDefault = '';
119  $commentMsg = $this->msg( 'upload-default-description' )->inContentLanguage();
120  if ( !$this->mForReUpload && !$commentMsg->isDisabled() ) {
121  $commentDefault = $commentMsg->plain();
122  }
123  $this->mComment = $request->getText( 'wpUploadDescription', $commentDefault );
124 
125  $this->mCancelUpload = $request->getCheck( 'wpCancelUpload' )
126  || $request->getCheck( 'wpReUpload' ); // b/w compat
127 
128  // If it was posted check for the token (no remote POST'ing with user credentials)
129  $token = $request->getVal( 'wpEditToken' );
130  $this->mTokenOk = $this->getUser()->matchEditToken( $token );
131 
132  $this->uploadFormTextTop = '';
133  $this->uploadFormTextAfterSummary = '';
134  }
135 
144  public function userCanExecute( User $user ) {
145  return UploadBase::isEnabled() && parent::userCanExecute( $user );
146  }
147 
158  public function execute( $par ) {
159  $this->useTransactionalTimeLimit();
160 
161  $this->setHeaders();
162  $this->outputHeader();
163 
164  # Check uploading enabled
165  if ( !UploadBase::isEnabled() ) {
166  throw new ErrorPageError( 'uploaddisabled', 'uploaddisabledtext' );
167  }
168 
169  $this->addHelpLink( 'Help:Managing files' );
170 
171  # Check permissions
172  $user = $this->getUser();
173  $permissionRequired = UploadBase::isAllowed( $user );
174  if ( $permissionRequired !== true ) {
175  throw new PermissionsError( $permissionRequired );
176  }
177 
178  # Check blocks
179  if ( $user->isBlockedFromUpload() ) {
180  throw new UserBlockedError(
181  $user->getBlock(),
182  $user,
183  $this->getLanguage(),
184  $this->getRequest()->getIP()
185  );
186  }
187 
188  // Global blocks
189  if ( $user->isBlockedGlobally() ) {
190  throw new UserBlockedError(
191  $user->getGlobalBlock(),
192  $user,
193  $this->getLanguage(),
194  $this->getRequest()->getIP()
195  );
196  }
197 
198  # Check whether we actually want to allow changing stuff
199  $this->checkReadOnly();
200 
201  $this->loadRequest();
202 
203  # Unsave the temporary file in case this was a cancelled upload
204  if ( $this->mCancelUpload && !$this->unsaveUploadedFile() ) {
205  # Something went wrong, so unsaveUploadedFile showed a warning
206  return;
207  }
208 
209  # Process upload or show a form
210  if (
211  $this->mTokenOk && !$this->mCancelUpload &&
212  ( $this->mUpload && $this->mUploadClicked )
213  ) {
214  $this->processUpload();
215  } else {
216  # Backwards compatibility hook
217  // Avoid PHP 7.1 warning of passing $this by reference
218  $upload = $this;
219  if ( !Hooks::run( 'UploadForm:initial', [ &$upload ] ) ) {
220  wfDebug( "Hook 'UploadForm:initial' broke output of the upload form\n" );
221 
222  return;
223  }
224  $this->showUploadForm( $this->getUploadForm() );
225  }
226 
227  # Cleanup
228  if ( $this->mUpload ) {
229  $this->mUpload->cleanupTempFile();
230  }
231  }
232 
238  protected function showUploadForm( $form ) {
239  # Add links if file was previously deleted
240  if ( $this->mDesiredDestName ) {
241  $this->showViewDeletedLinks();
242  }
243 
244  if ( $form instanceof HTMLForm ) {
245  $form->show();
246  } else {
247  $this->getOutput()->addHTML( $form );
248  }
249  }
250 
259  protected function getUploadForm( $message = '', $sessionKey = '', $hideIgnoreWarning = false ) {
260  # Initialize form
261  $context = new DerivativeContext( $this->getContext() );
262  $context->setTitle( $this->getPageTitle() ); // Remove subpage
263  $form = new UploadForm( [
264  'watch' => $this->getWatchCheck(),
265  'forreupload' => $this->mForReUpload,
266  'sessionkey' => $sessionKey,
267  'hideignorewarning' => $hideIgnoreWarning,
268  'destwarningack' => (bool)$this->mDestWarningAck,
269 
270  'description' => $this->mComment,
271  'texttop' => $this->uploadFormTextTop,
272  'textaftersummary' => $this->uploadFormTextAfterSummary,
273  'destfile' => $this->mDesiredDestName,
274  ], $context, $this->getLinkRenderer() );
275 
276  # Check the token, but only if necessary
277  if (
278  !$this->mTokenOk && !$this->mCancelUpload &&
279  ( $this->mUpload && $this->mUploadClicked )
280  ) {
281  $form->addPreText( $this->msg( 'session_fail_preview' )->parse() );
282  }
283 
284  # Give a notice if the user is uploading a file that has been deleted or moved
285  # Note that this is independent from the message 'filewasdeleted'
286  $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
287  $delNotice = ''; // empty by default
288  if ( $desiredTitleObj instanceof Title && !$desiredTitleObj->exists() ) {
289  $dbr = wfGetDB( DB_REPLICA );
290 
291  LogEventsList::showLogExtract( $delNotice, [ 'delete', 'move' ],
292  $desiredTitleObj,
293  '', [ 'lim' => 10,
294  'conds' => [ 'log_action != ' . $dbr->addQuotes( 'revision' ) ],
295  'showIfEmpty' => false,
296  'msgKey' => [ 'upload-recreate-warning' ] ]
297  );
298  }
299  $form->addPreText( $delNotice );
300 
301  # Add text to form
302  $form->addPreText( '<div id="uploadtext">' .
303  $this->msg( 'uploadtext', [ $this->mDesiredDestName ] )->parseAsBlock() .
304  '</div>' );
305  # Add upload error message
306  $form->addPreText( $message );
307 
308  # Add footer to form
309  $uploadFooter = $this->msg( 'uploadfooter' );
310  if ( !$uploadFooter->isDisabled() ) {
311  $form->addPostText( '<div id="mw-upload-footer-message">'
312  . $uploadFooter->parseAsBlock() . "</div>\n" );
313  }
314 
315  return $form;
316  }
317 
321  protected function showViewDeletedLinks() {
322  $title = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
323  $user = $this->getUser();
324  $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
325  // Show a subtitle link to deleted revisions (to sysops et al only)
326  if ( $title instanceof Title ) {
327  $count = $title->isDeleted();
328  if ( $count > 0 && $permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
329  $restorelink = $this->getLinkRenderer()->makeKnownLink(
330  SpecialPage::getTitleFor( 'Undelete', $title->getPrefixedText() ),
331  $this->msg( 'restorelink' )->numParams( $count )->text()
332  );
333  $link = $this->msg(
334  $permissionManager->userHasRight( $user, 'delete' ) ? 'thisisdeleted' : 'viewdeleted'
335  )->rawParams( $restorelink )->parseAsBlock();
336  $this->getOutput()->addHTML(
338  'div',
339  [ 'id' => 'contentSub2' ],
340  $link
341  )
342  );
343  }
344  }
345  }
346 
358  protected function showRecoverableUploadError( $message ) {
359  $stashStatus = $this->mUpload->tryStashFile( $this->getUser() );
360  if ( $stashStatus->isGood() ) {
361  $sessionKey = $stashStatus->getValue()->getFileKey();
362  $uploadWarning = 'upload-tryagain';
363  } else {
364  $sessionKey = null;
365  $uploadWarning = 'upload-tryagain-nostash';
366  }
367  $message = '<h2>' . $this->msg( 'uploaderror' )->escaped() . "</h2>\n" .
368  '<div class="error">' . $message . "</div>\n";
369 
370  $form = $this->getUploadForm( $message, $sessionKey );
371  $form->setSubmitText( $this->msg( $uploadWarning )->escaped() );
372  $this->showUploadForm( $form );
373  }
374 
383  protected function showUploadWarning( $warnings ) {
384  # If there are no warnings, or warnings we can ignore, return early.
385  # mDestWarningAck is set when some javascript has shown the warning
386  # to the user. mForReUpload is set when the user clicks the "upload a
387  # new version" link.
388  if ( !$warnings || ( count( $warnings ) == 1
389  && isset( $warnings['exists'] )
390  && ( $this->mDestWarningAck || $this->mForReUpload ) )
391  ) {
392  return false;
393  }
394 
395  $stashStatus = $this->mUpload->tryStashFile( $this->getUser() );
396  if ( $stashStatus->isGood() ) {
397  $sessionKey = $stashStatus->getValue()->getFileKey();
398  $uploadWarning = 'uploadwarning-text';
399  } else {
400  $sessionKey = null;
401  $uploadWarning = 'uploadwarning-text-nostash';
402  }
403 
404  // Add styles for the warning, reused from the live preview
405  $this->getOutput()->addModuleStyles( 'mediawiki.special' );
406 
407  $linkRenderer = $this->getLinkRenderer();
408  $warningHtml = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . "</h2>\n"
409  . '<div class="mw-destfile-warning"><ul>';
410  foreach ( $warnings as $warning => $args ) {
411  if ( $warning == 'badfilename' ) {
412  $this->mDesiredDestName = Title::makeTitle( NS_FILE, $args )->getText();
413  }
414  if ( $warning == 'exists' ) {
415  $msg = "\t<li>" . self::getExistsWarning( $args ) . "</li>\n";
416  } elseif ( $warning == 'no-change' ) {
417  $file = $args;
418  $filename = $file->getTitle()->getPrefixedText();
419  $msg = "\t<li>" . $this->msg( 'fileexists-no-change', $filename )->parse() . "</li>\n";
420  } elseif ( $warning == 'duplicate-version' ) {
421  $file = $args[0];
422  $count = count( $args );
423  $filename = $file->getTitle()->getPrefixedText();
424  $message = $this->msg( 'fileexists-duplicate-version' )
425  ->params( $filename )
426  ->numParams( $count );
427  $msg = "\t<li>" . $message->parse() . "</li>\n";
428  } elseif ( $warning == 'was-deleted' ) {
429  # If the file existed before and was deleted, warn the user of this
430  $ltitle = SpecialPage::getTitleFor( 'Log' );
431  $llink = $linkRenderer->makeKnownLink(
432  $ltitle,
433  $this->msg( 'deletionlog' )->text(),
434  [],
435  [
436  'type' => 'delete',
437  'page' => Title::makeTitle( NS_FILE, $args )->getPrefixedText(),
438  ]
439  );
440  $msg = "\t<li>" . $this->msg( 'filewasdeleted' )->rawParams( $llink )->parse() . "</li>\n";
441  } elseif ( $warning == 'duplicate' ) {
442  $msg = $this->getDupeWarning( $args );
443  } elseif ( $warning == 'duplicate-archive' ) {
444  if ( $args === '' ) {
445  $msg = "\t<li>" . $this->msg( 'file-deleted-duplicate-notitle' )->parse()
446  . "</li>\n";
447  } else {
448  $msg = "\t<li>" . $this->msg( 'file-deleted-duplicate',
449  Title::makeTitle( NS_FILE, $args )->getPrefixedText() )->parse()
450  . "</li>\n";
451  }
452  } else {
453  if ( $args === true ) {
454  $args = [];
455  } elseif ( !is_array( $args ) ) {
456  $args = [ $args ];
457  }
458  $msg = "\t<li>" . $this->msg( $warning, $args )->parse() . "</li>\n";
459  }
460  $warningHtml .= $msg;
461  }
462  $warningHtml .= "</ul></div>\n";
463  $warningHtml .= $this->msg( $uploadWarning )->parseAsBlock();
464 
465  $form = $this->getUploadForm( $warningHtml, $sessionKey, /* $hideIgnoreWarning */ true );
466  $form->setSubmitText( $this->msg( 'upload-tryagain' )->text() );
467  $form->addButton( [
468  'name' => 'wpUploadIgnoreWarning',
469  'value' => $this->msg( 'ignorewarning' )->text()
470  ] );
471  $form->addButton( [
472  'name' => 'wpCancelUpload',
473  'value' => $this->msg( 'reuploaddesc' )->text()
474  ] );
475 
476  $this->showUploadForm( $form );
477 
478  # Indicate that we showed a form
479  return true;
480  }
481 
487  protected function showUploadError( $message ) {
488  $message = '<h2>' . $this->msg( 'uploadwarning' )->escaped() . "</h2>\n" .
489  '<div class="error">' . $message . "</div>\n";
490  $this->showUploadForm( $this->getUploadForm( $message ) );
491  }
492 
497  protected function processUpload() {
498  // Fetch the file if required
499  $status = $this->mUpload->fetchFile();
500  if ( !$status->isOK() ) {
501  $this->showUploadError( $this->getOutput()->parseAsInterface(
502  $status->getWikiText( false, false, $this->getLanguage() )
503  ) );
504 
505  return;
506  }
507  // Avoid PHP 7.1 warning of passing $this by reference
508  $upload = $this;
509  if ( !Hooks::run( 'UploadForm:BeforeProcessing', [ &$upload ] ) ) {
510  wfDebug( "Hook 'UploadForm:BeforeProcessing' broke processing the file.\n" );
511  // This code path is deprecated. If you want to break upload processing
512  // do so by hooking into the appropriate hooks in UploadBase::verifyUpload
513  // and UploadBase::verifyFile.
514  // If you use this hook to break uploading, the user will be returned
515  // an empty form with no error message whatsoever.
516  return;
517  }
518 
519  // Upload verification
520  $details = $this->mUpload->verifyUpload();
521  if ( $details['status'] != UploadBase::OK ) {
522  $this->processVerificationError( $details );
523 
524  return;
525  }
526 
527  // Verify permissions for this title
528  $permErrors = $this->mUpload->verifyTitlePermissions( $this->getUser() );
529  if ( $permErrors !== true ) {
530  $code = array_shift( $permErrors[0] );
531  $this->showRecoverableUploadError( $this->msg( $code, $permErrors[0] )->parse() );
532 
533  return;
534  }
535 
536  $this->mLocalFile = $this->mUpload->getLocalFile();
537 
538  // Check warnings if necessary
539  if ( !$this->mIgnoreWarning ) {
540  $warnings = $this->mUpload->checkWarnings();
541  if ( $this->showUploadWarning( $warnings ) ) {
542  return;
543  }
544  }
545 
546  // This is as late as we can throttle, after expected issues have been handled
547  if ( UploadBase::isThrottled( $this->getUser() ) ) {
549  $this->msg( 'actionthrottledtext' )->escaped()
550  );
551  return;
552  }
553 
554  // Get the page text if this is not a reupload
555  if ( !$this->mForReUpload ) {
556  $pageText = self::getInitialPageText( $this->mComment, $this->mLicense,
557  $this->mCopyrightStatus, $this->mCopyrightSource, $this->getConfig() );
558  } else {
559  $pageText = false;
560  }
561 
562  $changeTags = $this->getRequest()->getVal( 'wpChangeTags' );
563  if ( is_null( $changeTags ) || $changeTags === '' ) {
564  $changeTags = [];
565  } else {
566  $changeTags = array_filter( array_map( 'trim', explode( ',', $changeTags ) ) );
567  }
568 
569  if ( $changeTags ) {
570  $changeTagsStatus = ChangeTags::canAddTagsAccompanyingChange(
571  $changeTags, $this->getUser() );
572  if ( !$changeTagsStatus->isOK() ) {
573  $this->showUploadError( $this->getOutput()->parseAsInterface(
574  $changeTagsStatus->getWikiText( false, false, $this->getLanguage() )
575  ) );
576 
577  return;
578  }
579  }
580 
581  $status = $this->mUpload->performUpload(
582  $this->mComment,
583  $pageText,
584  $this->mWatchthis,
585  $this->getUser(),
586  $changeTags
587  );
588 
589  if ( !$status->isGood() ) {
591  $this->getOutput()->parseAsInterface(
592  $status->getWikiText( false, false, $this->getLanguage() )
593  )
594  );
595 
596  return;
597  }
598 
599  // Success, redirect to description page
600  $this->mUploadSuccessful = true;
601  // Avoid PHP 7.1 warning of passing $this by reference
602  $upload = $this;
603  Hooks::run( 'SpecialUploadComplete', [ &$upload ] );
604  $this->getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
605  }
606 
616  public static function getInitialPageText( $comment = '', $license = '',
617  $copyStatus = '', $source = '', Config $config = null
618  ) {
619  if ( $config === null ) {
620  wfDebug( __METHOD__ . ' called without a Config instance passed to it' );
621  $config = MediaWikiServices::getInstance()->getMainConfig();
622  }
623 
624  $msg = [];
625  $forceUIMsgAsContentMsg = (array)$config->get( 'ForceUIMsgAsContentMsg' );
626  /* These messages are transcluded into the actual text of the description page.
627  * Thus, forcing them as content messages makes the upload to produce an int: template
628  * instead of hardcoding it there in the uploader language.
629  */
630  foreach ( [ 'license-header', 'filedesc', 'filestatus', 'filesource' ] as $msgName ) {
631  if ( in_array( $msgName, $forceUIMsgAsContentMsg ) ) {
632  $msg[$msgName] = "{{int:$msgName}}";
633  } else {
634  $msg[$msgName] = wfMessage( $msgName )->inContentLanguage()->text();
635  }
636  }
637 
638  $licenseText = '';
639  if ( $license !== '' ) {
640  $licenseText = '== ' . $msg['license-header'] . " ==\n{{" . $license . "}}\n";
641  }
642 
643  $pageText = $comment . "\n";
644  $headerText = '== ' . $msg['filedesc'] . ' ==';
645  if ( $comment !== '' && strpos( $comment, $headerText ) === false ) {
646  // prepend header to page text unless it's already there (or there is no content)
647  $pageText = $headerText . "\n" . $pageText;
648  }
649 
650  if ( $config->get( 'UseCopyrightUpload' ) ) {
651  $pageText .= '== ' . $msg['filestatus'] . " ==\n" . $copyStatus . "\n";
652  $pageText .= $licenseText;
653  $pageText .= '== ' . $msg['filesource'] . " ==\n" . $source;
654  } else {
655  $pageText .= $licenseText;
656  }
657 
658  // allow extensions to modify the content
659  Hooks::run( 'UploadForm:getInitialPageText', [ &$pageText, $msg, $config ] );
660 
661  return $pageText;
662  }
663 
676  protected function getWatchCheck() {
677  if ( $this->getUser()->getOption( 'watchdefault' ) ) {
678  // Watch all edits!
679  return true;
680  }
681 
682  $desiredTitleObj = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
683  if ( $desiredTitleObj instanceof Title && $this->getUser()->isWatched( $desiredTitleObj ) ) {
684  // Already watched, don't change that
685  return true;
686  }
687 
688  $local = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo()
689  ->newFile( $this->mDesiredDestName );
690  if ( $local && $local->exists() ) {
691  // We're uploading a new version of an existing file.
692  // No creation, so don't watch it if we're not already.
693  return false;
694  } else {
695  // New page should get watched if that's our option.
696  return $this->getUser()->getOption( 'watchcreations' ) ||
697  $this->getUser()->getOption( 'watchuploads' );
698  }
699  }
700 
707  protected function processVerificationError( $details ) {
708  switch ( $details['status'] ) {
711  $this->showRecoverableUploadError( $this->msg( 'minlength1' )->escaped() );
712  break;
714  $this->showRecoverableUploadError( $this->msg( 'illegalfilename',
715  $details['filtered'] )->parse() );
716  break;
718  $this->showRecoverableUploadError( $this->msg( 'filename-toolong' )->escaped() );
719  break;
721  $this->showRecoverableUploadError( $this->msg( 'filetype-missing' )->parse() );
722  break;
724  $this->showRecoverableUploadError( $this->msg( 'windows-nonascii-filename' )->parse() );
725  break;
726 
729  $this->showUploadError( $this->msg( 'emptyfile' )->escaped() );
730  break;
732  $this->showUploadError( $this->msg( 'largefileserver' )->escaped() );
733  break;
735  $msg = $this->msg( 'filetype-banned-type' );
736  if ( isset( $details['blacklistedExt'] ) ) {
737  $msg->params( $this->getLanguage()->commaList( $details['blacklistedExt'] ) );
738  } else {
739  $msg->params( $details['finalExt'] );
740  }
741  $extensions = array_unique( $this->getConfig()->get( 'FileExtensions' ) );
742  $msg->params( $this->getLanguage()->commaList( $extensions ),
743  count( $extensions ) );
744 
745  // Add PLURAL support for the first parameter. This results
746  // in a bit unlogical parameter sequence, but does not break
747  // old translations
748  if ( isset( $details['blacklistedExt'] ) ) {
749  $msg->params( count( $details['blacklistedExt'] ) );
750  } else {
751  $msg->params( 1 );
752  }
753 
754  $this->showUploadError( $msg->parse() );
755  break;
757  unset( $details['status'] );
758  $code = array_shift( $details['details'] );
759  $this->showUploadError( $this->msg( $code, $details['details'] )->parse() );
760  break;
762  if ( is_array( $details['error'] ) ) { # allow hooks to return error details in an array
763  $args = $details['error'];
764  $error = array_shift( $args );
765  } else {
766  $error = $details['error'];
767  $args = null;
768  }
769 
770  $this->showUploadError( $this->msg( $error, $args )->parse() );
771  break;
772  default:
773  throw new MWException( __METHOD__ . ": Unknown value `{$details['status']}`" );
774  }
775  }
776 
782  protected function unsaveUploadedFile() {
783  if ( !( $this->mUpload instanceof UploadFromStash ) ) {
784  return true;
785  }
786  $success = $this->mUpload->unsaveUploadedFile();
787  if ( !$success ) {
788  $this->getOutput()->showFatalError(
789  $this->msg( 'filedeleteerror' )
790  ->params( $this->mUpload->getTempPath() )
791  ->escaped()
792  );
793 
794  return false;
795  } else {
796  return true;
797  }
798  }
799 
809  public static function getExistsWarning( $exists ) {
810  if ( !$exists ) {
811  return '';
812  }
813 
814  $file = $exists['file'];
815  $filename = $file->getTitle()->getPrefixedText();
816  $warnMsg = null;
817 
818  if ( $exists['warning'] == 'exists' ) {
819  // Exact match
820  $warnMsg = wfMessage( 'fileexists', $filename );
821  } elseif ( $exists['warning'] == 'page-exists' ) {
822  // Page exists but file does not
823  $warnMsg = wfMessage( 'filepageexists', $filename );
824  } elseif ( $exists['warning'] == 'exists-normalized' ) {
825  $warnMsg = wfMessage( 'fileexists-extension', $filename,
826  $exists['normalizedFile']->getTitle()->getPrefixedText() );
827  } elseif ( $exists['warning'] == 'thumb' ) {
828  // Swapped argument order compared with other messages for backwards compatibility
829  $warnMsg = wfMessage( 'fileexists-thumbnail-yes',
830  $exists['thumbFile']->getTitle()->getPrefixedText(), $filename );
831  } elseif ( $exists['warning'] == 'thumb-name' ) {
832  // Image w/o '180px-' does not exists, but we do not like these filenames
833  $name = $file->getName();
834  $badPart = substr( $name, 0, strpos( $name, '-' ) + 1 );
835  $warnMsg = wfMessage( 'file-thumbnail-no', $badPart );
836  } elseif ( $exists['warning'] == 'bad-prefix' ) {
837  $warnMsg = wfMessage( 'filename-bad-prefix', $exists['prefix'] );
838  }
839 
840  return $warnMsg ? $warnMsg->title( $file->getTitle() )->parse() : '';
841  }
842 
848  public function getDupeWarning( $dupes ) {
849  if ( !$dupes ) {
850  return '';
851  }
852 
853  $gallery = ImageGalleryBase::factory( false, $this->getContext() );
854  $gallery->setShowBytes( false );
855  $gallery->setShowDimensions( false );
856  foreach ( $dupes as $file ) {
857  $gallery->add( $file->getTitle() );
858  }
859 
860  return '<li>' .
861  $this->msg( 'file-exists-duplicate' )->numParams( count( $dupes ) )->parse() .
862  $gallery->toHTML() . "</li>\n";
863  }
864 
865  protected function getGroupName() {
866  return 'media';
867  }
868 
877  public static function rotationEnabled() {
878  $bitmapHandler = new BitmapHandler();
879  return $bitmapHandler->autoRotateEnabled();
880  }
881 }
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42
static rotationEnabled()
Should we rotate images in the preview on Special:Upload.
__construct( $request=null)
Get data POSTed through the form and assign them to the object.
const FILENAME_TOO_LONG
Definition: UploadBase.php:107
getUploadForm( $message='', $sessionKey='', $hideIgnoreWarning=false)
Get an UploadForm instance with title and text properly set.
$context
Definition: load.php:45
getContext()
Gets the context this SpecialPage is executed in.
static getInitialPageText( $comment='', $license='', $copyStatus='', $source='', Config $config=null)
Get the initial image page text based on a comment and optional file status information.
Implements uploading from previously stored file.
getWatchCheck()
See if we should check the &#39;watch this page&#39; checkbox on the form based on the user&#39;s preferences and...
$success
static createFromRequest(&$request, $type=null)
Create a form of UploadBase depending on wpSourceType and initializes it.
Definition: UploadBase.php:180
showUploadError( $message)
Show the upload form with error message, but do not stash the file.
UploadBase $mUpload
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:209
An IContextSource implementation which will inherit context from another source but allow individual ...
LocalFile $mLocalFile
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
$source
addHelpLink( $to, $overrideBaseUrl=false)
Adds help link with an icon via page indicators.
bool $mForReUpload
The user followed an "overwrite this file" link.
static factory( $mode=false, IContextSource $context=null)
Get a new image gallery.
showViewDeletedLinks()
Shows the "view X deleted revivions link"".
unsaveUploadedFile()
Remove a temporarily kept file stashed by saveTempUploadedFile().
getOutput()
Get the OutputPage being used for this instance.
const ILLEGAL_FILENAME
Definition: UploadBase.php:99
showUploadWarning( $warnings)
Stashes the upload, shows the main form, but adds a "continue anyway button".
bool $mUploadSuccessful
Subclasses can use this to determine whether a file was uploaded.
if( $line===false) $args
Definition: cdb.php:64
userCanExecute(User $user)
This page can be shown if uploading is enabled.
The User object encapsulates all of the user-specific settings (user_id, name, rights, email address, options, last login time).
Definition: User.php:51
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
string $mDesiredDestName
User input variables from the "description" section.
Interface for configuration instances.
Definition: Config.php:28
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:149
An error page which can definitely be safely rendered using the OutputPage.
processVerificationError( $details)
Provides output to the user for a result of UploadBase::verifyUpload.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Form for handling uploads and special page.
$uploadFormTextTop
Text injection points for hooks not using HTMLForm.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes! ...
WebRequest FauxRequest $mRequest
Misc variables.
const FILE_TOO_LARGE
Definition: UploadBase.php:105
const MIN_LENGTH_PARTNAME
Definition: UploadBase.php:98
const NS_FILE
Definition: Defines.php:66
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don&#39;t need a full Title object...
Definition: SpecialPage.php:83
Show an error when the user tries to do something whilst blocked.
const VERIFICATION_ERROR
Definition: UploadBase.php:103
showRecoverableUploadError( $message)
Stashes the upload and shows the main upload form.
static isEnabled()
Returns true if uploads are enabled.
Definition: UploadBase.php:135
static isThrottled( $user)
Returns true if the user has surpassed the upload rate limit, false otherwise.
Definition: UploadBase.php:166
const FILETYPE_BADTYPE
Definition: UploadBase.php:102
const FILETYPE_MISSING
Definition: UploadBase.php:101
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:612
static makeTitle( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:586
static getExistsWarning( $exists)
Functions for formatting warnings.
showUploadForm( $form)
Show the main upload form.
$mIgnoreWarning
User input variables from the root section.
loadRequest()
Initialize instance variables from request and create an Upload handler.
const HOOK_ABORTED
Definition: UploadBase.php:104
useTransactionalTimeLimit()
Call wfTransactionalTimeLimit() if this request was POSTed.
getUser()
Shortcut to get the User executing this instance.
getConfig()
Shortcut to get main config object.
Show an error when a user tries to do something they do not have the necessary permissions for...
const WINDOWS_NONASCII_FILENAME
Definition: UploadBase.php:106
getLanguage()
Shortcut to get user&#39;s language.
Generic handler for bitmap images.
bool $mCancelUpload
The user clicked "Cancel and return to upload form" button.
const DB_REPLICA
Definition: defines.php:25
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:521
processUpload()
Do the upload.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
getRequest()
Get the WebRequest being used for this instance.
const OK
Definition: UploadBase.php:96
$mDestWarningAck
Hidden variables.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
getDupeWarning( $dupes)
Construct a warning and a gallery from an array of duplicate files.
Sub class of HTMLForm that provides the form section of SpecialUpload.
Definition: UploadForm.php:27
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
getPageTitle( $subpage=false)
Get a self-referential title object.
const EMPTY_FILE
Definition: UploadBase.php:97
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
static showLogExtract(&$out, $types=[], $page='', $user='', $param=[])
Show log extract.
MediaWiki Linker LinkRenderer null $linkRenderer
Definition: SpecialPage.php:67