mRequest = $request; } protected function initForm() { global $wgRequest, $wgUser; if ( is_null( $this->mRequest ) ) { $request = $wgRequest; } else { $request = $this->mRequest; } // Guess the desired name from the filename if not provided $this->mDesiredDestName = $request->getText( 'wpDestFile' ); if( !$this->mDesiredDestName ) $this->mDesiredDestName = $request->getText( 'wpUploadFile' ); $this->mForReUpload = $request->getBool( 'wpForReUpload' ); // updating a file $this->mIgnoreWarning = $request->getCheck( 'wpIgnoreWarning' ); $this->mComment = $request->getText( 'wpUploadDescription' ); if( !$request->wasPosted() ) { # GET requests just give the main form; no data except destination # filename and description return; } //if it was posted check for the token (no remote POST'ing with user credentials) $token = $request->getVal( 'wpEditToken' ); $this->mTokenOk = $wgUser->matchEditToken( $token ); # Placeholders for text injection by hooks (empty per default) $this->uploadFormTextTop = ""; $this->uploadFormTextAfterSummary = ""; $this->mUploadClicked = $request->getCheck( 'wpUpload' ); $this->mLicense = $request->getText( 'wpLicense' ); $this->mCopyrightStatus = $request->getText( 'wpUploadCopyStatus' ); $this->mCopyrightSource = $request->getText( 'wpUploadSource' ); $this->mWatchthis = $request->getBool( 'wpWatchthis' ); $this->mSourceType = $request->getText( 'wpSourceType' ); $this->mDestWarningAck = $request->getText( 'wpDestFileWarningAck' ); $this->mReUpload = $request->getCheck( 'wpReUpload' ); // retrying upload $this->mAction = $request->getVal( 'action' ); $this->mUpload = UploadBase::createFromRequest( $request ); } public function userCanExecute( $user ) { return UploadBase::isEnabled() && parent::userCanExecute( $user ); } /** * Start doing stuff * @access public */ function execute( $par ) { global $wgUser, $wgOut, $wgRequest; $this->setHeaders(); $this->outputHeader(); $this->initForm(); # Check uploading enabled if( !UploadBase::isEnabled() ) { $wgOut->showErrorPage( 'uploaddisabled', 'uploaddisabledtext' ); return; } # Check permissions global $wgGroupPermissions; if( !$wgUser->isAllowed( 'upload' ) ) { if( !$wgUser->isLoggedIn() && ( $wgGroupPermissions['user']['upload'] || $wgGroupPermissions['autoconfirmed']['upload'] ) ) { // Custom message if logged-in users without any special rights can upload $wgOut->showErrorPage( 'uploadnologin', 'uploadnologintext' ); } else { $wgOut->permissionRequired( 'upload' ); } return; } # Check blocks if( $wgUser->isBlocked() ) { $wgOut->blockedPage(); return; } if( wfReadOnly() ) { $wgOut->readOnlyPage(); return; } //check token if uploading or reUploading if( !$this->mTokenOk && !$this->mReUpload && ($this->mUpload && ( 'submit' == $this->mAction || $this->mUploadClicked ) ) ) { $this->mainUploadForm ( wfMsg( 'session_fail_preview', 'parseinline' ) ); return ; } if( $this->mReUpload && $this->mUpload) { // User choose to cancel upload if( !$this->mUpload->unsaveUploadedFile() ) { return; } # Because it is probably checked and shouldn't be $this->mIgnoreWarning = false; $this->mainUploadForm(); } elseif( $this->mUpload && ( 'submit' == $this->mAction || $this->mUploadClicked ) ) { $this->processUpload(); } else { $this->mainUploadForm(); } if( $this->mUpload ) $this->mUpload->cleanupTempFile(); } /** * Do the upload * Checks are made in SpecialUpload::execute() * * FIXME this should really use the standard Status class (instead of associative array) * FIXME would be nice if we refactored this into the upload api. * (the special upload page is not the only response point that needs clean localized error msgs) * * @access private */ function processUpload() { global $wgOut, $wgFileExtensions, $wgLang; $details = $this->internalProcessUpload(); switch( $details['status'] ) { case UploadBase::SUCCESS: $wgOut->redirect( $this->mLocalFile->getTitle()->getFullURL() ); break; case UploadBase::BEFORE_PROCESSING: $this->uploadError( $details['error'] ); break; case UploadBase::LARGE_FILE_SERVER: $this->mainUploadForm( wfMsgHtml( 'largefileserver' ) ); break; case UploadBase::EMPTY_FILE: $this->mainUploadForm( wfMsgHtml( 'emptyfile' ) ); break; case UploadBase::MIN_LENGTH_PARTNAME: $this->mainUploadForm( wfMsgHtml( 'minlength1' ) ); break; case UploadBase::ILLEGAL_FILENAME: $this->uploadError( wfMsgExt( 'illegalfilename', 'parseinline', $details['filtered'] ) ); break; case UploadBase::PROTECTED_PAGE: $wgOut->showPermissionsErrorPage( $details['permissionserrors'] ); break; case UploadBase::OVERWRITE_EXISTING_FILE: $this->uploadError( wfMsgExt( $details['overwrite'], 'parseinline' ) ); break; case UploadBase::FILETYPE_MISSING: $this->uploadError( wfMsgExt( 'filetype-missing', array ( 'parseinline' ) ) ); break; case UploadBase::FILETYPE_BADTYPE: $finalExt = $details['finalExt']; $this->uploadError( wfMsgExt( 'filetype-banned-type', array( 'parseinline' ), htmlspecialchars( $finalExt ), implode( wfMsgExt( 'comma-separator', array( 'escapenoentities' ) ), $wgFileExtensions ), $wgLang->formatNum( count( $wgFileExtensions ) ) ) ); break; case UploadBase::VERIFICATION_ERROR: unset( $details['status'] ); $code = array_shift( $details['details'] ); $this->uploadError( wfMsgExt( $code, 'parseinline', $details['details'] ) ); break; case UploadBase::UPLOAD_VERIFICATION_ERROR: $error = $details['error']; $this->uploadError( wfMsgExt( $error, 'parseinline' ) ); break; case UploadBase::UPLOAD_WARNING: unset( $details['status'] ); $this->uploadWarning( $details ); break; case UploadBase::INTERNAL_ERROR: $status = $details['internal']; $this->showError( $wgOut->parse( $status->getWikiText() ) ); break; default: throw new MWException( __METHOD__ . ": Unknown value `{$details['status']}`" ); } } /** * Really do the upload * Checks are made in SpecialUpload::execute() * * @param array $resultDetails contains result-specific dict of additional values * * @access private */ function internalProcessUpload() { global $wgUser; if( !wfRunHooks( 'UploadForm:BeforeProcessing', array( &$this ) ) ) { wfDebug( "Hook 'UploadForm:BeforeProcessing' broke processing the file.\n" ); return array( 'status' => UploadBase::BEFORE_PROCESSING ); } /** * If the image is protected, non-sysop users won't be able * to modify it by uploading a new revision. */ $permErrors = $this->mUpload->verifyPermissions( $wgUser ); if( $permErrors !== true ) { return array( 'status' => UploadBase::PROTECTED_PAGE, 'permissionserrors' => $permErrors ); } // Fetch the file if required $status = $this->mUpload->fetchFile(); if( !$status->isOK() ) { return array( 'status' => UploadBase::BEFORE_PROCESSING, 'error'=> $status->getWikiText() ); } // Check whether this is a sane upload $result = $this->mUpload->verifyUpload(); if( $result['status'] != UploadBase::OK ) return $result; $this->mLocalFile = $this->mUpload->getLocalFile(); if( !$this->mIgnoreWarning ) { $warnings = $this->mUpload->checkWarnings(); if( count( $warnings ) ) { $warnings['status'] = UploadBase::UPLOAD_WARNING; return $warnings; } } /** * Try actually saving the thing... * It will show an error form on failure. No it will not. */ if( !$this->mForReUpload ) { $pageText = self::getInitialPageText( $this->mComment, $this->mLicense, $this->mCopyrightStatus, $this->mCopyrightSource ); } else { $pageText = false; } $status = $this->mUpload->performUpload( $this->mComment, $pageText, $this->mWatchthis, $wgUser ); if ( !$status->isGood() ) { return array( 'status' => UploadBase::INTERNAL_ERROR, 'internal' => $status ); } else { // Success, redirect to description page wfRunHooks( 'SpecialUploadComplete', array( &$this ) ); return UploadBase::SUCCESS; } } /** * Formats a result of UploadBase::getExistsWarning as HTML * This check is static and can be done pre-upload via AJAX * * @param array $exists The result of UploadBase::getExistsWarning * @return string Empty string if there is no warning or an HTML fragment * consisting of one or more
  • elements if there is a warning. */ public static function getExistsWarning( $exists ) { global $wgUser, $wgContLang; if ( !$exists ) return ''; $file = $exists['file']; $filename = $file->getTitle()->getPrefixedText(); $warning = array(); $sk = $wgUser->getSkin(); if( $exists['warning'] == 'exists' ) { // Exact match $warning[] = '
  • ' . wfMsgExt( 'fileexists', 'parseinline', $filename ) . '
  • '; } elseif( $exists['warning'] == 'page-exists' ) { // Page exists but file does not $warning[] = '
  • ' . wfMsgExt( 'filepageexists', 'parseinline', $filename ) . '
  • '; } elseif ( $exists['warning'] == 'exists-normalized' ) { $warning[] = '
  • ' . wfMsgExt( 'fileexists-extension', 'parseinline', $filename, $exists['normalizedFile']->getTitle()->getPrefixedText() ) . '
  • '; } elseif ( $exists['warning'] == 'thumb' ) { // Swapped argument order compared with other messages for backwards compatibility $warning[] = '
  • ' . wfMsgExt( 'fileexists-thumbnail-yes', 'parseinline', $exists['thumbFile']->getTitle()->getPrefixedText(), $filename ) . '
  • '; } elseif ( $exists['warning'] == 'thumb-name' ) { # Image w/o '180px-' does not exists, but we do not like these filenames $name = $file->getName(); $badPart = substr( $name, 0, strpos( $name, '-' ) + 1 ); $warning[] = '
  • ' . wfMsgExt( 'file-thumbnail-no', 'parseinline', $badPart ) . '
  • '; } elseif ( $exists['warning'] == 'bad-prefix' ) { $warning[] = '
  • ' . wfMsgExt( 'filename-bad-prefix', 'parseinline', $exists['prefix'] ) . '
  • '; } elseif ( $exists['warning'] == 'was-deleted' ) { # If the file existed before and was deleted, warn the user of this $ltitle = SpecialPage::getTitleFor( 'Log' ); $llink = $sk->linkKnown( $ltitle, wfMsgHtml( 'deletionlog' ), array(), array( 'type' => 'delete', 'page' => $filename ) ); $warning[] = '
  • ' . wfMsgWikiHtml( 'filewasdeleted', $llink ) . '
  • '; } return implode( "\n", $warning ); } /** * Get a list of warnings * * @param string local filename, e.g. 'file exists', 'non-descriptive filename' * @return array list of warning messages */ static function ajaxGetExistsWarning( $filename ) { $file = wfFindFile( $filename ); if( !$file ) { // Force local file so we have an object to do further checks against // if there isn't an exact match... $file = wfLocalFile( $filename ); } $s = ' '; if ( $file ) { $exists = UploadBase::getExistsWarning( $file ); $warning = self::getExistsWarning( $exists ); // FIXME: We probably also want the prefix blacklist and the wasdeleted check here if ( $warning !== '' ) { $s = ""; } } return $s; } /** * Render a preview of a given license for the AJAX preview on upload * * @param string $license * @return string */ public static function ajaxGetLicensePreview( $license ) { global $wgParser, $wgUser; $text = '{{' . $license . '}}'; $title = Title::makeTitle( NS_FILE, 'Sample.jpg' ); $options = ParserOptions::newFromUser( $wgUser ); // Expand subst: first, then live templates... $text = $wgParser->preSaveTransform( $text, $title, $wgUser, $options ); $output = $wgParser->parse( $text, $title, $options ); return $output->getText(); } /** * Construct the human readable warning message from an array of duplicate files */ public static function getDupeWarning( $dupes ) { if( $dupes ) { global $wgOut; $msg = ""; foreach( $dupes as $file ) { $title = $file->getTitle(); $msg .= $title->getPrefixedText() . "|" . $title->getText() . "\n"; } $msg .= ""; return "
  • " . wfMsgExt( "file-exists-duplicate", array( "parse" ), count( $dupes ) ) . $wgOut->parse( $msg ) . "
  • \n"; } else { return ''; } } /** * Remove a temporarily kept file stashed by saveTempUploadedFile(). * @access private * @return success */ function unsaveUploadedFile() { global $wgOut; $success = $this->mUpload->unsaveUploadedFile(); if ( ! $success ) { $wgOut->showFileDeleteError( $this->mUpload->getTempPath() ); return false; } else { return true; } } /* Interface code starts below this line * * -------------------------------------------------------------- */ /** * @param string $error as HTML * @access private */ function uploadError( $error ) { global $wgOut; $wgOut->addHTML( '

    ' . wfMsgHtml( 'uploadwarning' ) . "

    \n" ); $wgOut->addHTML( '' . $error . '' ); } /** * There's something wrong with this file, not enough to reject it * totally but we require manual intervention to save it for real. * Stash it away, then present a form asking to confirm or cancel. * * @param string $warning as HTML * @access private */ function uploadWarning( $warnings ) { global $wgOut, $wgUser; global $wgUseCopyrightUpload; $this->mSessionKey = $this->mUpload->stashSession(); if( $this->mSessionKey === false ) { # Couldn't save file; an error has been displayed so let's go. return; } $sk = $wgUser->getSkin(); $wgOut->addHTML( '

    ' . wfMsgHtml( 'uploadwarning' ) . "

    \n" ); $wgOut->addHTML( '