Removed JS2 work (has been moved to the js2-work branch). Has been lightly tested...
[lhc/web/wiklou.git] / includes / upload / UploadFromUrl.php
index 39cfb53..bae9236 100644 (file)
@@ -11,9 +11,6 @@
 class UploadFromUrl extends UploadBase {
        protected $mTempDownloadPath;
 
-       // by default do a SYNC_DOWNLOAD
-       protected $dl_mode =  Http::SYNC_DOWNLOAD;
-
        /**
         * Checks if the user is allowed to use the upload-by-URL feature. If the 
         * user is allowed, pass on permissions checking to the parent.
@@ -33,19 +30,10 @@ class UploadFromUrl extends UploadBase {
        }
 
        /** 
-        * Entry point for API upload:: ASYNC_DOWNLOAD (if possible) 
+        * Entry point for API upload 
         */
-       public function initialize( $name, $url, $asyncdownload, $na = false ) {
-               global $wgTmpDirectory, $wgPhpCli;
-
-               // check for $asyncdownload request:
-               if( $asyncdownload ){
-                       if( $wgPhpCli && wfShellExecEnabled() ){
-                               $this->dl_mode = Http::ASYNC_DOWNLOAD;
-                       } else {
-                               $this->dl_mode = Http::SYNC_DOWNLOAD;
-                       }
-               }
+       public function initialize( $name, $url, $na = false ) {
+               global $wgTmpDirectory;
 
                $localFile = tempnam( $wgTmpDirectory, 'WEBUPLOAD' );
                parent::initialize( $name, $localFile, 0, true );
@@ -53,12 +41,8 @@ class UploadFromUrl extends UploadBase {
                $this->mUrl = trim( $url );
        }
 
-       public function isAsync(){
-               return $this->dl_mode == Http::ASYNC_DOWNLOAD;
-       }
-
        /**
-        * Entry point for SpecialUpload no ASYNC_DOWNLOAD possible
+        * Entry point for SpecialUpload
         * @param $request Object: WebRequest object
         */
        public function initializeFromRequest( &$request ) {
@@ -72,24 +56,6 @@ class UploadFromUrl extends UploadBase {
                );
        }
 
-       /**
-        * Do the real fetching stuff
-        */
-       public function fetchFile() {
-               // Entry point for SpecialUpload
-               if( Http::isValidURI( $this->mUrl ) === false ) {
-                       return Status::newFatal( 'upload-proto-error' );
-               }
-
-               // Now do the actual download to the target file:
-               $status = Http::doDownload( $this->mUrl, $this->mTempPath, $this->dl_mode );
-
-               // Update the local filesize var:
-               $this->mFileSize = filesize( $this->mTempPath );
-
-               return $status;
-       }
-
        /**
         * @param $request Object: WebRequest object
         */
@@ -97,9 +63,75 @@ class UploadFromUrl extends UploadBase {
                if( !$request->getVal( 'wpUploadFileURL' ) )
                        return false;
                // check that is a valid url:
-               return Http::isValidURI( $request->getVal( 'wpUploadFileURL' ) );
+               return self::isValidUrl( $request->getVal( 'wpUploadFileURL' ) );
        }
 
+       public static function isValidUrl( $url ) {
+               // Only allow HTTP or FTP for now
+               return (bool)preg_match( '!^(http://|ftp://)!', $url );
+       }
+       
+       /**
+        * Do the real fetching stuff
+        */
+       function fetchFile() {
+               if( !self::isValidUrl( $this->mUrl ) ) {
+                       return Status::newFatal( 'upload-proto-error' );
+               }
+               $res = $this->curlCopy();
+               if( $res !== true ) {
+                       return Status::newFatal( $res );
+               }
+               return Status::newGood();
+       }
+       
+       /**
+        * Safe copy from URL
+        * Returns true if there was an error, false otherwise
+        */
+       private function curlCopy() {
+               global $wgOut;
+
+               # Open temporary file
+               $this->mCurlDestHandle = @fopen( $this->mTempPath, "wb" );
+               if( $this->mCurlDestHandle === false ) {
+                       # Could not open temporary file to write in
+                       return 'upload-file-error';
+               }
 
-
-}
\ No newline at end of file
+               $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, $this->mUrl);
+               curl_setopt( $ch, CURLOPT_WRITEFUNCTION, array( $this, 'uploadCurlCallback' ) );
+               curl_exec( $ch );
+               $error =  curl_errno( $ch );
+               curl_close( $ch );
+
+               fclose( $this->mCurlDestHandle );
+               unset( $this->mCurlDestHandle );
+               
+               if( $error ) 
+                       return "upload-curl-error$errornum";
+
+               return true;
+       }
+       
+       /**
+        * 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->mFileSize += $length; 
+               if( $this->mFileSize > $wgMaxUploadSize ) {
+                       return 0;
+               }
+               fwrite( $this->mCurlDestHandle, $data );
+               return $length;
+       }
+}