X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FSpecialUpload.php;h=2ebd3fa7ad3a941cbe280c28f27374966b1b3ef2;hb=078a5ad8957be65d74fa8f6ae436a6d0e744b3c6;hp=fd8e31e3ebf13bea2af32d3adf0904a0fe89130d;hpb=a7d7323b063a4ab4e17cecbc594f2df05dbd24d7;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/SpecialUpload.php b/includes/SpecialUpload.php index fd8e31e3eb..2ebd3fa7ad 100644 --- a/includes/SpecialUpload.php +++ b/includes/SpecialUpload.php @@ -1,16 +1,10 @@ mDestFile = $request->getText( 'wpDestFile' ); if( !$request->wasPosted() ) { @@ -48,7 +50,11 @@ class UploadForm { return; } - $this->mIgnoreWarning = $request->getCheck( 'wpIgnoreWarning'); + # Placeholders for text injection by hooks (empty per default) + $this->uploadFormTextTop = ""; + $this->uploadFormTextAfterSummary = ""; + + $this->mIgnoreWarning = $request->getCheck( 'wpIgnoreWarning' ); $this->mReUpload = $request->getCheck( 'wpReUpload' ); $this->mUpload = $request->getCheck( 'wpUpload' ); @@ -57,6 +63,7 @@ class UploadForm { $this->mUploadCopyStatus = $request->getText( 'wpUploadCopyStatus' ); $this->mUploadSource = $request->getText( 'wpUploadSource' ); $this->mWatchthis = $request->getBool( 'wpWatchthis' ); + $this->mSourceType = $request->getText( 'wpSourceType' ); wfDebug( "UploadForm: watchthis is: '$this->mWatchthis'\n" ); $this->mAction = $request->getVal( 'action' ); @@ -81,14 +88,116 @@ class UploadForm { /** *Check for a newly uploaded file. */ - $this->mUploadTempName = $request->getFileTempName( 'wpUploadFile' ); - $this->mUploadSize = $request->getFileSize( 'wpUploadFile' ); - $this->mOname = $request->getFileName( 'wpUploadFile' ); - $this->mUploadError = $request->getUploadError( 'wpUploadFile' ); - $this->mSessionKey = false; - $this->mStashed = false; - $this->mRemoveTempFile = false; // PHP will handle this + if( $wgAllowCopyUploads && $this->mSourceType == 'web' ) { + $this->initializeFromUrl( $request ); + } else { + $this->initializeFromUpload( $request ); + } + } + } + + /** + * Initialize the uploaded file from PHP data + * @access private + */ + function initializeFromUpload( $request ) { + $this->mUploadTempName = $request->getFileTempName( 'wpUploadFile' ); + $this->mUploadSize = $request->getFileSize( 'wpUploadFile' ); + $this->mOname = $request->getFileName( 'wpUploadFile' ); + $this->mUploadError = $request->getUploadError( 'wpUploadFile' ); + $this->mSessionKey = false; + $this->mStashed = false; + $this->mRemoveTempFile = false; // PHP will handle this + } + + /** + * Copy a web file to a temporary file + * @access private + */ + function initializeFromUrl( $request ) { + global $wgTmpDirectory; + $url = $request->getText( 'wpUploadFileURL' ); + $local_file = tempnam( $wgTmpDirectory, 'WEBUPLOAD' ); + + $this->mUploadTempName = $local_file; + $this->mUploadError = $this->curlCopy( $url, $local_file ); + $this->mUploadSize = $this->mUploadTempFileSize; + $this->mOname = array_pop( explode( '/', $url ) ); + $this->mSessionKey = false; + $this->mStashed = false; + + // PHP won't auto-cleanup the file + $this->mRemoveTempFile = file_exists( $local_file ); + } + + /** + * Safe copy from URL + * Returns true if there was an error, false otherwise + */ + private function curlCopy( $url, $dest ) { + global $wgUser, $wgOut; + + if( !$wgUser->isAllowed( 'upload_by_url' ) ) { + $wgOut->permissionRequired( 'upload_by_url' ); + return true; + } + + # Maybe remove some pasting blanks :-) + $url = trim( $url ); + if( stripos($url, 'http://') !== 0 && stripos($url, 'ftp://') !== 0 ) { + # Only HTTP or FTP URLs + $wgOut->errorPage( 'upload-proto-error', 'upload-proto-error-text' ); + return true; + } + + # Open temporary file + $this->mUploadTempFile = @fopen( $this->mUploadTempName, "wb" ); + if( $this->mUploadTempFile === false ) { + # Could not open temporary file to write in + $wgOut->errorPage( 'upload-file-error', 'upload-file-error-text'); + return true; + } + + $ch = curl_init(); + curl_setopt( $ch, CURLOPT_HTTP_VERSION, 1.0); # Probably not needed, but apparently can work around some bug + curl_setopt( $ch, CURLOPT_TIMEOUT, 10); # 10 seconds timeout + curl_setopt( $ch, CURLOPT_LOW_SPEED_LIMIT, 512); # 0.5KB per second minimum transfer speed + curl_setopt( $ch, CURLOPT_URL, $url); + curl_setopt( $ch, CURLOPT_WRITEFUNCTION, array( $this, 'uploadCurlCallback' ) ); + curl_exec( $ch ); + $error = curl_errno( $ch ) ? true : false; + $errornum = curl_errno( $ch ); + // if ( $error ) print curl_error ( $ch ) ; # Debugging output + curl_close( $ch ); + + fclose( $this->mUploadTempFile ); + unset( $this->mUploadTempFile ); + if( $error ) { + unlink( $dest ); + if( wfEmptyMsg( "upload-curl-error$errornum", wfMsg("upload-curl-error$errornum") ) ) + $wgOut->errorPage( 'upload-misc-error', 'upload-misc-error-text' ); + else + $wgOut->errorPage( "upload-curl-error$errornum", "upload-curl-error$errornum-text" ); + } + + return $error; + } + + /** + * Callback function for CURL-based web transfer + * Write data to file unless we've passed the length limit; + * if so, abort immediately. + * @access private + */ + function uploadCurlCallback( $ch, $data ) { + global $wgMaxUploadSize; + $length = strlen( $data ); + $this->mUploadTempFileSize += $length; + if( $this->mUploadTempFileSize > $wgMaxUploadSize ) { + return 0; } + fwrite( $this->mUploadTempFile, $data ); + return $length; } /** @@ -99,32 +208,45 @@ class UploadForm { global $wgUser, $wgOut; global $wgEnableUploads, $wgUploadDirectory; - /** Show an error message if file upload is disabled */ - if( ! $wgEnableUploads ) { - $wgOut->addWikiText( wfMsg( 'uploaddisabled' ) ); + # Check uploading enabled + if( !$wgEnableUploads ) { + $wgOut->showErrorPage( 'uploaddisabled', 'uploaddisabledtext', array( $this->mDestFile ) ); + return; + } + + # Check permissions + if( !$wgUser->isAllowed( 'upload' ) ) { + if( !$wgUser->isLoggedIn() ) { + $wgOut->showErrorPage( 'uploadnologin', 'uploadnologintext' ); + } else { + $wgOut->permissionRequired( 'upload' ); + } return; } - /** Various rights checks */ - if( !$wgUser->isAllowed( 'upload' ) || $wgUser->isBlocked() ) { - $wgOut->errorpage( 'uploadnologin', 'uploadnologintext' ); + # Check blocks + if( $wgUser->isBlocked() ) { + $wgOut->blockedPage(); return; } + if( wfReadOnly() ) { $wgOut->readOnlyPage(); return; } /** Check if the image directory is writeable, this is a common mistake */ - if ( !is_writeable( $wgUploadDirectory ) ) { + if( !is_writeable( $wgUploadDirectory ) ) { $wgOut->addWikiText( wfMsg( 'upload_directory_read_only', $wgUploadDirectory ) ); return; } if( $this->mReUpload ) { - $this->unsaveUploadedFile(); + if( !$this->unsaveUploadedFile() ) { + return; + } $this->mainUploadForm(); - } else if ( 'submit' == $this->mAction || $this->mUpload ) { + } else if( 'submit' == $this->mAction || $this->mUpload ) { $this->processUpload(); } else { $this->mainUploadForm(); @@ -141,12 +263,16 @@ class UploadForm { * @access private */ function processUpload() { - global $wgUser, $wgOut, $wgLang, $wgContLang; - global $wgUploadDirectory; - global $wgUseCopyrightUpload, $wgCheckCopyrightUpload; + global $wgUser, $wgOut; + + if( !wfRunHooks( 'UploadForm:BeforeProcessing', array( &$this ) ) ) + { + wfDebug( "Hook 'UploadForm:BeforeProcessing' broke processing the file." ); + return false; + } /* Check for PHP error if any, requires php 4.2 or newer */ - if ( $this->mUploadError == 1/*UPLOAD_ERR_INI_SIZE*/ ) { + if( $this->mUploadError == 1/*UPLOAD_ERR_INI_SIZE*/ ) { $this->mainUploadForm( wfMsgHtml( 'largefileserver' ) ); return; } @@ -160,10 +286,10 @@ class UploadForm { } # Chop off any directories in the given filename - if ( $this->mDestFile ) { - $basename = basename( $this->mDestFile ); + if( $this->mDestFile ) { + $basename = wfBaseName( $this->mDestFile ); } else { - $basename = basename( $this->mOname ); + $basename = wfBaseName( $this->mOname ); } /** @@ -171,14 +297,21 @@ class UploadForm { * only the final one for the whitelist. */ list( $partname, $ext ) = $this->splitExtensions( $basename ); + if( count( $ext ) ) { $finalExt = $ext[count( $ext ) - 1]; } else { $finalExt = ''; } - $fullExt = implode( '.', $ext ); - if ( strlen( $partname ) < 3 ) { + # If there was more than one "extension", reassemble the base + # filename to prevent bogus complaints about length + if( count( $ext ) > 1 ) { + for( $i = 0; $i < count( $ext ) - 1; $i++ ) + $partname .= '.' . $ext[$i]; + } + + if( strlen( $partname ) < 3 ) { $this->mainUploadForm( wfMsgHtml( 'minlength' ) ); return; } @@ -200,10 +333,10 @@ class UploadForm { * If the image is protected, non-sysop users won't be able * to modify it by uploading a new revision. */ - if( !$nt->userCanEdit() ) { + if( !$nt->userCan( 'edit' ) ) { return $this->uploadError( wfMsgWikiHtml( 'protectedpage' ) ); } - + /** * In some cases we may forbid overwriting of existing files. */ @@ -215,10 +348,12 @@ class UploadForm { /* Don't allow users to override the blacklist (check file extension) */ global $wgStrictFileExtensions; global $wgFileExtensions, $wgFileBlacklist; - if( $this->checkFileExtensionList( $ext, $wgFileBlacklist ) || - ($wgStrictFileExtensions && - !$this->checkFileExtension( $finalExt, $wgFileExtensions ) ) ) { - return $this->uploadError( wfMsgHtml( 'badfiletype', htmlspecialchars( $fullExt ) ) ); + if ($finalExt == '') { + return $this->uploadError( wfMsgExt( 'filetype-missing', array ( 'parseinline' ) ) ); + } elseif ( $this->checkFileExtensionList( $ext, $wgFileBlacklist ) || + ($wgStrictFileExtensions && + !$this->checkFileExtension( $finalExt, $wgFileExtensions ) ) ) { + return $this->uploadError( wfMsgExt( 'filetype-badtype', array ( 'parseinline' ), htmlspecialchars( $finalExt ), implode ( ', ', $wgFileExtensions ) ) ); } /** @@ -233,23 +368,24 @@ class UploadForm { if( $veri !== true ) { //it's a wiki error... return $this->uploadError( $veri->toString() ); } + + /** + * Provide an opportunity for extensions to add futher checks + */ + $error = ''; + if( !wfRunHooks( 'UploadVerification', + array( $this->mUploadSaveName, $this->mUploadTempName, &$error ) ) ) { + return $this->uploadError( $error ); + } } - - /** - * Provide an opportunity for extensions to add futher checks - */ - $error = ''; - if( !wfRunHooks( 'UploadVerification', - array( $this->mUploadSaveName, $this->mUploadTempName, &$error ) ) ) { - return $this->uploadError( $error ); - } + /** * Check for non-fatal conditions */ if ( ! $this->mIgnoreWarning ) { $warning = ''; - + global $wgCapitalLinks; if( $wgCapitalLinks ) { $filtered = ucfirst( $filtered ); @@ -261,25 +397,88 @@ class UploadForm { global $wgCheckFileExtensions; if ( $wgCheckFileExtensions ) { if ( ! $this->checkFileExtension( $finalExt, $wgFileExtensions ) ) { - $warning .= '
  • '.wfMsgHtml( 'badfiletype', htmlspecialchars( $fullExt ) ).'
  • '; + $warning .= '
  • '.wfMsgExt( 'filetype-badtype', array ( 'parseinline' ), htmlspecialchars( $finalExt ), implode ( ', ', $wgFileExtensions ) ).'
  • '; } } global $wgUploadSizeWarning; if ( $wgUploadSizeWarning && ( $this->mUploadSize > $wgUploadSizeWarning ) ) { - # TODO: Format $wgUploadSizeWarning to something that looks better than the raw byte - # value, perhaps add GB,MB and KB suffixes? - $warning .= '
  • '.wfMsgHtml( 'largefile', $wgUploadSizeWarning, $this->mUploadSize ).'
  • '; + $skin = $wgUser->getSkin(); + $wsize = $skin->formatSize( $wgUploadSizeWarning ); + $asize = $skin->formatSize( $this->mUploadSize ); + $warning .= '
  • ' . wfMsgHtml( 'large-file', $wsize, $asize ) . '
  • '; } if ( $this->mUploadSize == 0 ) { $warning .= '
  • '.wfMsgHtml( 'emptyfile' ).'
  • '; } - if( $nt->getArticleID() ) { - global $wgUser; - $sk = $wgUser->getSkin(); + global $wgUser; + $sk = $wgUser->getSkin(); + $image = wfLocalFile( $nt ); + + // Check for uppercase extension. We allow these filenames but check if an image + // with lowercase extension exists already + if ( $finalExt != strtolower( $finalExt ) ) { + $nt_lc = Title::newFromText( $partname . '.' . strtolower( $finalExt ) ); + $image_lc = wfLocalFile( $nt_lc ); + } + + if( $image->exists() ) { $dlink = $sk->makeKnownLinkObj( $nt ); - $warning .= '
  • '.wfMsgHtml( 'fileexists', $dlink ).'
  • '; + if ( $image->allowInlineDisplay() ) { + $dlink2 = $sk->makeImageLinkObj( $nt, wfMsgExt( 'fileexists-thumb', 'parseinline', $dlink ), $nt->getText(), 'right', array(), false, true ); + } elseif ( !$image->allowInlineDisplay() && $image->isSafeFile() ) { + $icon = $image->iconThumb(); + $dlink2 = '
    ' . $icon->toHtml() . '
    ' . $dlink . '
    '; + } else { + $dlink2 = ''; + } + + $warning .= '
  • ' . wfMsgExt( 'fileexists', 'parseline', $dlink ) . '
  • ' . $dlink2; + + } elseif ( isset( $image_lc) && $image_lc->exists() ) { + # Check if image with lowercase extension exists. + # It's not forbidden but in 99% it makes no sense to upload the same filename with uppercase extension + $dlink = $sk->makeKnownLinkObj( $nt_lc ); + if ( $image_lc->allowInlineDisplay() ) { + $dlink2 = $sk->makeImageLinkObj( $nt_lc, wfMsgExt( 'fileexists-thumb', 'parseinline', $dlink ), $nt_lc->getText(), 'right', array(), false, true ); + } elseif ( !$image_lc->allowInlineDisplay() && $image_lc->isSafeFile() ) { + $icon = $image_lc->iconThumb(); + $dlink2 = '
    ' . $icon->toHtml() . '
    ' . $dlink . '
    '; + } else { + $dlink2 = ''; + } + + $warning .= '
  • ' . wfMsgExt( 'fileexists-extension', 'parsemag' , $partname . '.' . $finalExt , $dlink ) . '
  • ' . $dlink2; + + } elseif ( ( substr( $partname , 3, 3 ) == 'px-' || substr( $partname , 2, 3 ) == 'px-' ) && ereg( "[0-9]{2}" , substr( $partname , 0, 2) ) ) { + # Check for filenames like 50px- or 180px-, these are mostly thumbnails + $nt_thb = Title::newFromText( substr( $partname , strpos( $partname , '-' ) +1 ) . '.' . $finalExt ); + $image_thb = wfLocalFile( $nt_thb ); + if ($image_thb->exists() ) { + # Check if an image without leading '180px-' (or similiar) exists + $dlink = $sk->makeKnownLinkObj( $nt_thb); + if ( $image_thb->allowInlineDisplay() ) { + $dlink2 = $sk->makeImageLinkObj( $nt_thb, wfMsgExt( 'fileexists-thumb', 'parseinline', $dlink ), $nt_thb->getText(), 'right', array(), false, true ); + } elseif ( !$image_thb->allowInlineDisplay() && $image_thb->isSafeFile() ) { + $icon = $image_thb->iconThumb(); + $dlink2 = '
    ' . $icon->toHtml() . '
    ' . $dlink . '
    '; + } else { + $dlink2 = ''; + } + + $warning .= '
  • ' . wfMsgExt( 'fileexists-thumbnail-yes', 'parsemag', $dlink ) . '
  • ' . $dlink2; + } else { + # Image w/o '180px-' does not exists, but we do not like these filenames + $warning .= '
  • ' . wfMsgExt( 'file-thumbnail-no', 'parseinline' , substr( $partname , 0, strpos( $partname , '-' ) +1 ) ) . '
  • '; + } + } + if ( $image->wasDeleted() ) { + # If the file existed before and was deleted, warn the user of this + # Don't bother doing so if the image exists now, however + $ltitle = SpecialPage::getTitleFor( 'Log' ); + $llink = $sk->makeKnownLinkObj( $ltitle, wfMsgHtml( 'deletionlog' ), 'type=delete&page=' . $nt->getPrefixedUrl() ); + $warning .= wfOpenElement( 'li' ) . wfMsgWikiHtml( 'filewasdeleted', $llink ) . wfCloseElement( 'li' ); } if( $warning != '' ) { @@ -303,8 +502,8 @@ class UploadForm { * Update the upload log and create the description page * if it's a new file. */ - $img = Image::newFromName( $this->mUploadSaveName ); - $success = $img->recordUpload( $this->mUploadOldVersion, + $this->mImage = wfLocalFile( $this->mUploadSaveName ); + $success = $this->mImage->recordUpload( $this->mUploadOldVersion, $this->mUploadDescription, $this->mLicense, $this->mUploadCopyStatus, @@ -313,10 +512,11 @@ class UploadForm { if ( $success ) { $this->showSuccess(); + wfRunHooks( 'UploadComplete', array( &$img ) ); } else { - // Image::recordUpload() fails if the image went missing, which is + // File::recordUpload() fails if the image went missing, which is // unlikely, hence the lack of a specialised message - $wgOut->fileNotFoundError( $this->mUploadSaveName ); + $wgOut->showFileNotFoundError( $this->mUploadSaveName ); } } } @@ -334,45 +534,15 @@ class UploadForm { * is a PHP-managed upload temporary */ function saveUploadedFile( $saveName, $tempName, $useRename = false ) { - global $wgUploadDirectory, $wgOut; - - $fname= "SpecialUpload::saveUploadedFile"; - - $dest = wfImageDir( $saveName ); - $archive = wfImageArchiveDir( $saveName ); - $this->mSavedFile = "{$dest}/{$saveName}"; - - if( is_file( $this->mSavedFile ) ) { - $this->mUploadOldVersion = gmdate( 'YmdHis' ) . "!{$saveName}"; - wfSuppressWarnings(); - $success = rename( $this->mSavedFile, "${archive}/{$this->mUploadOldVersion}" ); - wfRestoreWarnings(); - - if( ! $success ) { - $wgOut->fileRenameError( $this->mSavedFile, - "${archive}/{$this->mUploadOldVersion}" ); - return false; - } - else wfDebug("$fname: moved file ".$this->mSavedFile." to ${archive}/{$this->mUploadOldVersion}\n"); - } - else { - $this->mUploadOldVersion = ''; - } - - wfSuppressWarnings(); - $success = $useRename - ? rename( $tempName, $this->mSavedFile ) - : move_uploaded_file( $tempName, $this->mSavedFile ); - wfRestoreWarnings(); + global $wgOut, $wgAllowCopyUploads; - if( ! $success ) { - $wgOut->fileCopyError( $tempName, $this->mSavedFile ); + $image = wfLocalFile( $saveName ); + $archiveName = $image->publish( $tempName, File::DELETE_SOURCE ); + if ( WikiError::isError( $archiveName ) ) { + $this->showError( $archiveName ); return false; - } else { - wfDebug("$fname: wrote tempfile $tempName to ".$this->mSavedFile."\n"); } - - chmod( $this->mSavedFile, 0644 ); + $this->mUploadOldVersion = $archiveName; return true; } @@ -390,18 +560,14 @@ class UploadForm { */ function saveTempUploadedFile( $saveName, $tempName ) { global $wgOut; - $archive = wfImageArchiveDir( $saveName, 'temp' ); - $stash = $archive . '/' . gmdate( "YmdHis" ) . '!' . $saveName; - - $success = $this->mRemoveTempFile - ? rename( $tempName, $stash ) - : move_uploaded_file( $tempName, $stash ); - if ( !$success ) { - $wgOut->fileCopyError( $tempName, $stash ); + $repo = RepoGroup::singleton()->getLocalRepo(); + $result = $repo->storeTemp( $saveName, $tempName ); + if ( WikiError::isError( $result ) ) { + $this->showError( $result ); return false; + } else { + return $result; } - - return $stash; } /** @@ -433,14 +599,17 @@ class UploadForm { /** * Remove a temporarily kept file stashed by saveTempUploadedFile(). * @access private + * @return success */ function unsaveUploadedFile() { global $wgOut; - wfSuppressWarnings(); - $success = unlink( $this->mUploadTempName ); - wfRestoreWarnings(); + $repo = RepoGroup::singleton()->getLocalRepo(); + $success = $repo->freeTemp( $this->mUploadTempName ); if ( ! $success ) { - $wgOut->fileDeleteError( $this->mUploadTempName ); + $wgOut->showFileDeleteError( $this->mUploadTempName ); + return false; + } else { + return true; } } @@ -454,7 +623,7 @@ class UploadForm { global $wgUser, $wgOut, $wgContLang; $sk = $wgUser->getSkin(); - $ilink = $sk->makeMediaLink( $this->mUploadSaveName, Image::imageUrl( $this->mUploadSaveName ) ); + $ilink = $sk->makeMediaLinkObj( $this->mImage->getTitle() ); $dname = $wgContLang->getNsText( NS_IMAGE ) . ':'.$this->mUploadSaveName; $dlink = $sk->makeKnownLink( $dname, $dname ); @@ -483,7 +652,7 @@ class UploadForm { * @access private */ function uploadWarning( $warning ) { - global $wgOut, $wgUser, $wgLang, $wgUploadDirectory, $wgRequest; + global $wgOut; global $wgUseCopyrightUpload; $this->mSessionKey = $this->stashSession(); @@ -499,7 +668,7 @@ class UploadForm { $reupload = wfMsgHtml( 'reupload' ); $iw = wfMsgWikiHtml( 'ignorewarning' ); $reup = wfMsgWikiHtml( 'reuploaddesc' ); - $titleObj = Title::makeTitle( NS_SPECIAL, 'Upload' ); + $titleObj = SpecialPage::getTitleFor( 'Upload' ); $action = $titleObj->escapeLocalURL( 'action=submit' ); if ( $wgUseCopyrightUpload ) @@ -525,13 +694,13 @@ class UploadForm { - + $iw - + $reup @@ -547,8 +716,15 @@ class UploadForm { * @access private */ function mainUploadForm( $msg='' ) { - global $wgOut, $wgUser, $wgLang, $wgUploadDirectory, $wgRequest; + global $wgOut, $wgUser; global $wgUseCopyrightUpload; + global $wgRequest, $wgAllowCopyUploads; + + if( !wfRunHooks( 'UploadForm:initial', array( &$this ) ) ) + { + wfDebug( "Hook 'UploadForm:initial' broke output of the upload form" ); + return false; + } $cols = intval($wgUser->getOption( 'cols' )); $ew = $wgUser->getOption( 'editwidth' ); @@ -561,10 +737,8 @@ class UploadForm { "{$msg}\n" ); } $wgOut->addHTML( '
    ' ); - $wgOut->addWikiText( wfMsg( 'uploadtext' ) ); + $wgOut->addWikiText( wfMsgNoTrans( 'uploadtext', $this->mDestFile ) ); $wgOut->addHTML( '
    ' ); - $sk = $wgUser->getSkin(); - $sourcefilename = wfMsgHtml( 'sourcefilename' ); $destfilename = wfMsgHtml( 'destfilename' ); @@ -574,26 +748,48 @@ class UploadForm { $license = wfMsgHtml( 'license' ); $nolicense = wfMsgHtml( 'nolicense' ); $licenseshtml = $licenses->getHtml(); - + $ulb = wfMsgHtml( 'uploadbtn' ); - $titleObj = Title::makeTitle( NS_SPECIAL, 'Upload' ); + $titleObj = SpecialPage::getTitleFor( 'Upload' ); $action = $titleObj->escapeLocalURL(); $encDestFile = htmlspecialchars( $this->mDestFile ); - $watchChecked = $wgUser->getOption( 'watchdefault' ) + $watchChecked = + ( $wgUser->getOption( 'watchdefault' ) || + ( $wgUser->getOption( 'watchcreations' ) && $this->mDestFile == '' ) ) ? 'checked="checked"' : ''; - + + // Prepare form for upload or upload/copy + if( $wgAllowCopyUploads && $wgUser->isAllowed( 'upload_by_url' ) ) { + $filename_form = + "" . + "mDestFile?"":"onchange='fillDestFilename(\"wpUploadFile\")' ") . "size='40' />" . + wfMsgHTML( 'upload_source_file' ) . "
    " . + "" . + "mDestFile?"":"onchange='fillDestFilename(\"wpUploadFileURL\")' ") . "size='40' DISABLED />" . + wfMsgHtml( 'upload_source_url' ) ; + } else { + $filename_form = + "mDestFile?"":"onchange='fillDestFilename(\"wpUploadFile\")' ") . + "size='40' />" . + "" ; + } + $wgOut->addHTML( "
    - + {$this->uploadFormTextTop} + @@ -606,15 +802,19 @@ class UploadForm { " ); - - if ( $licenseshtml != '' ) { - $wgOut->addHTML( " + + if ( $licenseshtml != '' ) { + global $wgStylePath; + $wgOut->addHTML( " "); - } + } - if ( $wgUseCopyrightUpload ) { - $filestatus = wfMsgHtml ( 'filestatus' ); - $copystatus = htmlspecialchars( $this->mUploadCopyStatus ); - $filesource = wfMsgHtml ( 'filesource' ); - $uploadsource = htmlspecialchars( $this->mUploadSource ); - - $wgOut->addHTML( " + if ( $wgUseCopyrightUpload ) { + $filestatus = wfMsgHtml ( 'filestatus' ); + $copystatus = htmlspecialchars( $this->mUploadCopyStatus ); + $filesource = wfMsgHtml ( 'filesource' ); + $uploadsource = htmlspecialchars( $this->mUploadSource ); + + $wgOut->addHTML( " @@ -640,25 +840,32 @@ class UploadForm { "); - } - - - $wgOut->addHtml( " + } + + + $wgOut->addHtml( " - + + + - + +
    - mDestFile?"":"onchange='fillDestFilename()' ") . "size='40' /> + {$filename_form}
    + {$this->uploadFormTextAfterSummary}
    - $licenseshtml @@ -622,15 +822,15 @@ class UploadForm {
    - +
    + " ); + $wgOut->addWikiText( wfMsgForContent( 'edittools' ) ); + $wgOut->addHTML( " +
    " ); } @@ -717,7 +924,7 @@ class UploadForm { */ function verify( $tmpfile, $extension ) { #magically determine mime type - $magic=& wfGetMimeMagic(); + $magic=& MimeMagic::singleton(); $mime= $magic->guessMimeType($tmpfile,false); $fname= "SpecialUpload::verify"; @@ -735,12 +942,12 @@ class UploadForm { global $wgMimeTypeBlacklist; if( isset($wgMimeTypeBlacklist) && !is_null($wgMimeTypeBlacklist) && $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) { - return new WikiErrorMsg( 'badfiletype', htmlspecialchars( $mime ) ); + return new WikiErrorMsg( 'filetype-badmime', htmlspecialchars( $mime ) ); } } #check for htmlish code and javascript - if( $this->detectScript ( $tmpfile, $mime ) ) { + if( $this->detectScript ( $tmpfile, $mime, $extension ) ) { return new WikiErrorMsg( 'uploadscripted' ); } @@ -766,7 +973,7 @@ class UploadForm { function verifyExtension( $mime, $extension ) { $fname = 'SpecialUpload::verifyExtension'; - $magic =& wfGetMimeMagic(); + $magic =& MimeMagic::singleton(); if ( ! $mime || $mime == 'unknown' || $mime == 'unknown/unknown' ) if ( ! $magic->isRecognizableExtension( $extension ) ) { @@ -800,9 +1007,11 @@ class UploadForm { * * @param string $file Pathname to the temporary upload file * @param string $mime The mime type of the file + * @param string $extension The extension of the file * @return bool true if the file contains something looking like embedded scripts */ - function detectScript($file,$mime) { + function detectScript($file, $mime, $extension) { + global $wgAllowTitlesInSVG; #ugly hack: for text files, always look at the entire file. #For binarie field, just check the first K. @@ -857,9 +1066,11 @@ class UploadForm { '&1",$output,$code); - $exit_code= $code; #remeber for user feedback + $exit_code= $code; #remember for user feedback if ($virus_scanner_codes) { #map exit code to AV_xxx constants. - if (isset($virus_scanner_codes[$code])) $code= $virus_scanner_codes[$code]; #explicite mapping - else if (isset($virus_scanner_codes["*"])) $code= $virus_scanner_codes["*"]; #fallback mapping + if (isset($virus_scanner_codes[$code])) { + $code= $virus_scanner_codes[$code]; # explicit mapping + } else if (isset($virus_scanner_codes["*"])) { + $code= $virus_scanner_codes["*"]; # fallback mapping + } } if ($code===AV_SCAN_FAILED) { #scan failed (code was mapped to false by $virus_scanner_codes) wfDebug("$fname: failed to scan $file (code $exit_code).\n"); - if ($wgAntivirusRequired) return "scan failed (code $exit_code)"; - else return NULL; + if ($wgAntivirusRequired) { return "scan failed (code $exit_code)"; } + else { return NULL; } } else if ($code===AV_SCAN_ABORTED) { #scan failed because filetype is unknown (probably imune) wfDebug("$fname: unsupported file type $file (code $exit_code).\n"); @@ -961,7 +1176,7 @@ class UploadForm { $output= join("\n",$output); $output= trim($output); - if (!$output) $output= true; #if ther's no output, return true + if (!$output) $output= true; #if there's no output, return true else if ($msg_pattern) { $groups= array(); if (preg_match($msg_pattern,$output,$groups)) { @@ -1011,7 +1226,7 @@ class UploadForm { unlink( $this->mUploadTempName ); } } - + /** * Check if there's an overwrite conflict and, if so, if restrictions * forbid this user from performing the upload. @@ -1020,18 +1235,13 @@ class UploadForm { * @access private */ function checkOverwrite( $name ) { - $img = Image::newFromName( $name ); - if( is_null( $img ) ) { - // Uh... this shouldn't happen ;) - // But if it does, fall through to previous behavior - return false; - } - + $img = wfFindFile( $name ); + $error = ''; - if( $img->exists() ) { + if( $img ) { global $wgUser, $wgOut; if( $img->isLocal() ) { - if( !$wgUser->isAllowed( 'reupload' ) ) { + if( !self::userCanReUpload( $wgUser, $img->name ) ) { $error = 'fileexists-forbidden'; } } else { @@ -1041,15 +1251,50 @@ class UploadForm { } } } - + if( $error ) { $errorText = wfMsg( $error, wfEscapeWikiText( $img->getName() ) ); return new WikiError( $wgOut->parse( $errorText ) ); } - + // Rockin', go ahead and upload return true; } + /** + * Check if a user is the last uploader + * + * @param User $user + * @param string $img, image name + * @return bool + */ + public static function userCanReUpload( User $user, $img ) { + if( $user->isAllowed( 'reupload' ) ) + return true; // non-conditional + if( !$user->isAllowed( 'reupload-own' ) ) + return false; + + $dbr = wfGetDB( DB_SLAVE ); + $row = $dbr->selectRow('image', + /* SELECT */ 'img_user', + /* WHERE */ array( 'img_name' => $img ) + ); + if ( !$row ) + return false; + + return $user->getID() == $row->img_user; + } + + /** + * Display an error from a wikitext-formatted WikiError object + */ + function showError( WikiError $error ) { + global $wgOut; + $wgOut->setPageTitle( wfMsg( "internalerror" ) ); + $wgOut->setRobotpolicy( "noindex,nofollow" ); + $wgOut->setArticleRelated( false ); + $wgOut->enableClientCache( false ); + $wgOut->addWikiText( $error->getMessage() ); + } } ?>