X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FSpecialUpload.php;h=5873dfed0cd41969b3fc6a7b7f173781566f9f7a;hb=a3b490d2c4dfc25d7e0594eae8ee27ba69f6afea;hp=31c4f3c25763f6e10412ea5ab4a202e32ead1b18;hpb=c8f7249f9fc4d2bb1ef719aa006682b688cab3c2;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/SpecialUpload.php b/includes/SpecialUpload.php index 31c4f3c257..5873dfed0c 100644 --- a/includes/SpecialUpload.php +++ b/includes/SpecialUpload.php @@ -5,12 +5,7 @@ * @subpackage SpecialPage */ -/** - * - */ -require_once 'Image.php'; -require_once 'MacBinary.php'; -require_once 'Licenses.php'; + /** * Entry point */ @@ -32,7 +27,7 @@ class UploadForm { var $mUploadFile, $mUploadDescription, $mLicense ,$mIgnoreWarning, $mUploadError; var $mUploadSaveName, $mUploadTempName, $mUploadSize, $mUploadOldVersion; var $mUploadCopyStatus, $mUploadSource, $mReUpload, $mAction, $mUpload; - var $mOname, $mSessionKey, $mStashed, $mDestFile, $mRemoveTempFile; + var $mOname, $mSessionKey, $mStashed, $mDestFile, $mRemoveTempFile, $mSourceType; /**#@-*/ /** @@ -41,6 +36,7 @@ class UploadForm { * @param $request Data posted. */ function UploadForm( &$request ) { + global $wgAllowCopyUploads; $this->mDestFile = $request->getText( 'wpDestFile' ); if( !$request->wasPosted() ) { @@ -48,7 +44,7 @@ class UploadForm { return; } - $this->mIgnoreWarning = $request->getCheck( 'wpIgnoreWarning'); + $this->mIgnoreWarning = $request->getCheck( 'wpIgnoreWarning' ); $this->mReUpload = $request->getCheck( 'wpReUpload' ); $this->mUpload = $request->getCheck( 'wpUpload' ); @@ -57,6 +53,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,16 +78,112 @@ 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, $wgMaxUploadSize; + $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 $wgMaxUploadSize, $wgUser; + + if( !$wgUser->isAllowed( 'upload_by_url' ) ) { + $wgOut->permissionRequired( 'upload_by_url' ); + return true; + } + + # Maybe remove some pasting blanks :-) + $url = strtolower( trim( $url ) ); + if( substr( $url, 0, 7 ) != 'http://' && substr( $url, 0, 6 ) != 'ftp://' ) { + # Only HTTP or FTP URLs + return true; + } + + # Open temporary file + $this->mUploadTempFileSize = 0; + $this->mUploadTempFile = @fopen( $this->mUploadTempName, "wb" ); + if( $this->mUploadTempFile === false ) { + # Could not open temporary file to write in + 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; +# if ( $error ) print curl_error ( $ch ) ; # Debugging output + curl_close( $ch ); + + fclose( $this->mUploadTempFile ); + unset( $this->mUploadTempFile ); + if( $error ) { + unlink( $dest ); + } + + 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; + } + /** * Start doing stuff * @access public @@ -101,18 +194,17 @@ class UploadForm { # Check uploading enabled if( !$wgEnableUploads ) { - $wgOut->errorPage( 'uploaddisabled', 'uploaddisabledtext' ); + $wgOut->showErrorPage( 'uploaddisabled', 'uploaddisabledtext' ); return; } # Check permissions - if( $wgUser->isLoggedIn() ) { - if( !$wgUser->isAllowed( 'upload' ) ) { + if( !$wgUser->isAllowed( 'upload' ) ) { + if( !$wgUser->isLoggedIn() ) { + $wgOut->showErrorPage( 'uploadnologin', 'uploadnologintext' ); + } else { $wgOut->permissionRequired( 'upload' ); - return; } - } else { - $wgOut->errorPage( 'uploadnologin', 'uploadnologintext' ); return; } @@ -128,15 +220,17 @@ class UploadForm { } /** 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(); @@ -156,7 +250,7 @@ class UploadForm { global $wgUser, $wgOut; /* 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; } @@ -170,7 +264,7 @@ class UploadForm { } # Chop off any directories in the given filename - if ( $this->mDestFile ) { + if( $this->mDestFile ) { $basename = wfBaseName( $this->mDestFile ); } else { $basename = wfBaseName( $this->mOname ); @@ -196,7 +290,7 @@ class UploadForm { $partname .= '.' . $ext[$i]; } - if ( strlen( $partname ) < 3 ) { + if( strlen( $partname ) < 3 ) { $this->mainUploadForm( wfMsgHtml( 'minlength' ) ); return; } @@ -298,6 +392,16 @@ class UploadForm { $sk = $wgUser->getSkin(); $dlink = $sk->makeKnownLinkObj( $nt ); $warning .= '
  • '.wfMsgHtml( 'fileexists', $dlink ).'
  • '; + } else { + # If the file existed before and was deleted, warn the user of this + # Don't bother doing so if the image exists now, however + $image = new Image( $nt ); + if( $image->wasDeleted() ) { + $skin = $wgUser->getSkin(); + $ltitle = SpecialPage::getTitleFor( 'Log' ); + $llink = $skin->makeKnownLinkObj( $ltitle, wfMsgHtml( 'deletionlog' ), 'type=delete&page=' . $nt->getPrefixedUrl() ); + $warning .= wfOpenElement( 'li' ) . wfMsgWikiHtml( 'filewasdeleted', $llink ) . wfCloseElement( 'li' ); + } } if( $warning != '' ) { @@ -331,10 +435,11 @@ class UploadForm { if ( $success ) { $this->showSuccess(); + wfRunHooks( 'UploadComplete', array( &$img ) ); } else { // Image::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 ); } } } @@ -352,12 +457,17 @@ class UploadForm { * is a PHP-managed upload temporary */ function saveUploadedFile( $saveName, $tempName, $useRename = false ) { - global $wgOut; + global $wgOut, $wgAllowCopyUploads; + + if ( !$useRename AND $wgAllowCopyUploads AND $this->mSourceType == 'web' ) $useRename = true; $fname= "SpecialUpload::saveUploadedFile"; $dest = wfImageDir( $saveName ); $archive = wfImageArchiveDir( $saveName ); + if ( !is_dir( $dest ) ) wfMkdirParents( $dest ); + if ( !is_dir( $archive ) ) wfMkdirParents( $archive ); + $this->mSavedFile = "{$dest}/{$saveName}"; if( is_file( $this->mSavedFile ) ) { @@ -367,7 +477,7 @@ class UploadForm { wfRestoreWarnings(); if( ! $success ) { - $wgOut->fileRenameError( $this->mSavedFile, + $wgOut->showFileRenameError( $this->mSavedFile, "${archive}/{$this->mUploadOldVersion}" ); return false; } @@ -384,7 +494,7 @@ class UploadForm { wfRestoreWarnings(); if( ! $success ) { - $wgOut->fileCopyError( $tempName, $this->mSavedFile ); + $wgOut->showFileCopyError( $tempName, $this->mSavedFile ); return false; } else { wfDebug("$fname: wrote tempfile $tempName to ".$this->mSavedFile."\n"); @@ -409,13 +519,14 @@ class UploadForm { function saveTempUploadedFile( $saveName, $tempName ) { global $wgOut; $archive = wfImageArchiveDir( $saveName, 'temp' ); + if ( !is_dir ( $archive ) ) wfMkdirParents( $archive ); $stash = $archive . '/' . gmdate( "YmdHis" ) . '!' . $saveName; $success = $this->mRemoveTempFile ? rename( $tempName, $stash ) : move_uploaded_file( $tempName, $stash ); if ( !$success ) { - $wgOut->fileCopyError( $tempName, $stash ); + $wgOut->showFileCopyError( $tempName, $stash ); return false; } @@ -451,6 +562,7 @@ class UploadForm { /** * Remove a temporarily kept file stashed by saveTempUploadedFile(). * @access private + * @return success */ function unsaveUploadedFile() { global $wgOut; @@ -458,7 +570,10 @@ class UploadForm { $success = unlink( $this->mUploadTempName ); wfRestoreWarnings(); if ( ! $success ) { - $wgOut->fileDeleteError( $this->mUploadTempName ); + $wgOut->showFileDeleteError( $this->mUploadTempName ); + return false; + } else { + return true; } } @@ -517,7 +632,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 ) @@ -543,13 +658,13 @@ class UploadForm { - + $iw - + $reup @@ -567,6 +682,7 @@ class UploadForm { function mainUploadForm( $msg='' ) { global $wgOut, $wgUser; global $wgUseCopyrightUpload; + global $wgRequest, $wgAllowCopyUploads; $cols = intval($wgUser->getOption( 'cols' )); $ew = $wgUser->getOption( 'editwidth' ); @@ -596,22 +712,44 @@ class UploadForm { $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' ) ) { + $source_comment = wfMsgHtml( 'upload_source_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( "
    - + @@ -668,7 +806,7 @@ class UploadForm { @@ -748,7 +886,7 @@ class UploadForm { */ function verify( $tmpfile, $extension ) { #magically determine mime type - $magic=& wfGetMimeMagic(); + $magic=& MimeMagic::singleton(); $mime= $magic->guessMimeType($tmpfile,false); $fname= "SpecialUpload::verify"; @@ -771,7 +909,7 @@ class UploadForm { } #check for htmlish code and javascript - if( $this->detectScript ( $tmpfile, $mime ) ) { + if( $this->detectScript ( $tmpfile, $mime, $extension ) ) { return new WikiErrorMsg( 'uploadscripted' ); } @@ -797,7 +935,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 ) ) { @@ -831,9 +969,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. @@ -888,9 +1028,11 @@ class UploadForm { '
    - mDestFile?"":"onchange='fillDestFilename()' ") . "size='40' /> + {$filename_form}
    - +