r16162 - Code Review

From MediaWiki.org

Jump to: navigation, search
Repository:MediaWiki
Revision:r16161 | r16162 (on ViewVC) | r16163 >
Date:12:37, 22 August 2006
Author:magnusmanske
Status:new
Tags:
Comment:Switched URL upload function to CURL
10 sec timeout, 0.5KB/sec minimum transfer rate
Default URL upload permission for sysops only
Modified paths:

Diff [purge]

Index: trunk/phase3/includes/SpecialUpload.php
===================================================================
--- trunk/phase3/includes/SpecialUpload.php	(revision 16161)
+++ trunk/phase3/includes/SpecialUpload.php	(revision 16162)
@@ -108,23 +108,60 @@
 	 * @access private
 	 */
 	function initialize_web_file( &$request ) {
-		global $wgTmpDirectory, $wgMaxUploadSize;
+		global $wgTmpDirectory, $wgMaxUploadSize, $wgUploadTempFileSize;
 		$url = $request->getText( 'wpUploadFile' );
 		$local_file = tempnam( $wgTmpDirectory, 'WEBUPLOAD' );
 
-		if ( $wgMaxUploadSize < @filesize ( $url ) ) $error = true ;
-		else $error = !@copy( $url, $local_file );
-		
 		$this->mUploadTempName = $local_file;
-		$this->mUploadSize     = filesize( $local_file );
+		$this->mUploadError    = $this->curl_copy( $url, $local_file );
+		$this->mUploadSize     = $wgUploadTempFileSize ;
 		$this->mOname          = array_pop( explode( '/', $url ) );
-		$this->mUploadError    = $error;
 		$this->mSessionKey     = false;
 		$this->mStashed        = false;
-		$this->mRemoveTempFile = false; // PHP will *not* handle this
+		$this->mRemoveTempFile = file_exists( $local_file ) ; // PHP will *not* handle this
 	}
 	
 	/**
+	 * Safe copy from URL
+	 * Returns true if there was an error, false otherwise
+	 * @access private
+	 */
+	function curl_copy ( $url , $dest ) {
+		global $wgMaxUploadSize, $wgUploadTempFile, $wgUploadTempFileSize, $wgUser;
+
+		if( !$wgUser->isAllowed( 'upload_by_url' ) ) {
+			$wgOut->permissionRequired( 'upload_by_url' );
+			return true;
+		}
+
+		$url = trim ( $url ) ; # Maybe remove some pasting blanks :-)
+		$u = strtolower ( $url ) ;
+		if( substr( $u, 0, 7 ) != 'http://' AND substr( $u, 0, 6 ) != 'ftp://' ) return true ; # Only HTTP or FTP URLs
+
+		# Open temporary file
+		$wgUploadTempFileSize = 0 ;
+		$wgUploadTempFile = @fopen ( $this->mUploadTempName , "wb" ) ;
+		if ( $wgUploadTempFile === false ) return true ; # Could not open temporary file to write in
+		
+		$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, 'wfUploadCurlCallback' ) ;
+		curl_exec ( $ch ) ;
+		$error = curl_errno ( $ch ) ? true : false ;
+#		if ( $error ) print curl_error ( $ch ) ; # Debugging output
+		curl_close ($ch); 
+		
+		fclose ( $wgUploadTempFile ) ;
+		unset ( $wgUploadTempFile ) ;
+		if ( $error ) unlink ( $dest ) ;
+		
+		return $error ;
+	}
+	
+	/**
 	 * Start doing stuff
 	 * @access public
 	 */
@@ -458,12 +495,15 @@
 	 * @access private
 	 */
 	function saveTempUploadedFile( $saveName, $tempName ) {
-		global $wgOut;
+		global $wgOut, $wgAllowCopyUploads;
 		$archive = wfImageArchiveDir( $saveName, 'temp' );
 		if ( !is_dir ( $archive ) ) wfMkdirParents( $archive );
 		$stash = $archive . '/' . gmdate( "YmdHis" ) . '!' . $saveName;
 
-		$success = $this->mRemoveTempFile
+		$remove_file = $this->mRemoveTempFile ;
+		if ( !$remove_file AND $wgAllowCopyUploads AND $this->mSourceType == 'web' ) $remove_file = true;
+
+		$success = $remove_file
 			? rename( $tempName, $stash )
 			: move_uploaded_file( $tempName, $stash );
 		if ( !$success ) {
@@ -661,8 +701,8 @@
 		$watchChecked = $wgUser->getOption( 'watchdefault' )
 			? 'checked="checked"'
 			: '';
-		
-		if ( $wgAllowCopyUploads AND $wgRequest->getText('source') == 'web' ) {
+
+		if ( $wgAllowCopyUploads AND $wgRequest->getText('source') == 'web' AND $wgUser->isAllowed( 'upload_by_url' ) ) {
 			$sourcetype = 'text';
 			$source_comment = '<input type="hidden" name="wpSourceType" value="web"/>' . wfMsgHtml( 'upload_source_url' );
 		} else {
@@ -1152,4 +1192,20 @@
 	}
 
 }
+
+/**
+ * Callback function for CURL-based web transfer
+ * Apparently needs to be global
+ * @access private
+ */
+function wfUploadCurlCallback ($ch, $data) {
+	global $wgUploadTempFile, $wgMaxUploadSize, $wgUploadTempFileSize;
+	$length = strlen($data);
+	$wgUploadTempFileSize += $length;
+	if( $wgUploadTempFileSize > $wgMaxUploadSize ) return 0;
+	fwrite( $wgUploadTempFile , $data );
+	return $length;
+}
+	
+
 ?>
Index: trunk/phase3/includes/DefaultSettings.php
===================================================================
--- trunk/phase3/includes/DefaultSettings.php	(revision 16161)
+++ trunk/phase3/includes/DefaultSettings.php	(revision 16162)
@@ -908,7 +908,7 @@
 $wgGroupPermissions['sysop']['block']           = true;
 $wgGroupPermissions['sysop']['createaccount']   = true;
 $wgGroupPermissions['sysop']['delete']          = true;
-$wgGroupPermissions['sysop']['deletedhistory']  = true; // can view deleted history entries, but not see or restore the text
+$wgGroupPermissions['sysop']['deletedhistory'] 	= true; // can view deleted history entries, but not see or restore the text
 $wgGroupPermissions['sysop']['editinterface']   = true;
 $wgGroupPermissions['sysop']['import']          = true;
 $wgGroupPermissions['sysop']['importupload']    = true;
@@ -921,8 +921,9 @@
 $wgGroupPermissions['sysop']['upload']          = true;
 $wgGroupPermissions['sysop']['reupload']        = true;
 $wgGroupPermissions['sysop']['reupload-shared'] = true;
-$wgGroupPermissions['sysop']['unwatchedpages']	= true;
+$wgGroupPermissions['sysop']['unwatchedpages']  = true;
 $wgGroupPermissions['sysop']['autoconfirmed']   = true;
+$wgGroupPermissions['sysop']['upload_by_url']   = true;
 
 // Permission to change users' group assignments
 $wgGroupPermissions['bureaucrat']['userrights'] = true;
Index: trunk/phase3/RELEASE-NOTES
===================================================================
--- trunk/phase3/RELEASE-NOTES	(revision 16161)
+++ trunk/phase3/RELEASE-NOTES	(revision 16162)
@@ -148,7 +148,7 @@
 * Pass page title as parameters to "linkshere" and "nolinkshere" and update
   default message text
 * Allows to upload from publicy accessible URL. Set $wgAllowCopyUploads = true ; in LocalSettings.php
-  Limited to $wgMaxUploadSize (default:100MB)
+  Limited to $wgMaxUploadSize (default:100MB); URL upload is limited to sysops by default
 
 == Languages updated ==
 
Views
Toolbox