Index: branches/new-upload/phase3/includes/UploadFromUrl.php |
— | — | @@ -50,7 +50,10 @@ |
51 | 51 | } |
52 | 52 | //print "fetchFile:: $this->dl_mode"; |
53 | 53 | //now do the actual download to the shared target: |
54 | | - $status = Http::doDownload ( $this->mUrl, $this->mTempPath, $this->dl_mode); |
| 54 | + $status = Http::doDownload ( $this->mUrl, $this->mTempPath, $this->dl_mode); |
| 55 | + //update the local filesize var: |
| 56 | + $this->mFileSize = filesize($this->mTempPath); |
| 57 | + |
55 | 58 | return $status; |
56 | 59 | |
57 | 60 | /* |
— | — | @@ -64,39 +67,7 @@ |
65 | 68 | |
66 | 69 | } |
67 | 70 | |
68 | | - /** |
69 | | - * Safe copy from URL |
70 | | - * Returns true if there was an error, false otherwise |
71 | 71 | |
72 | | - private function curlCopy() { |
73 | | - global $wgOut, $wgCopyUploadTimeout; |
74 | | - |
75 | | - # Open temporary file |
76 | | - $this->mCurlDestHandle = @fopen( $this->mTempPath, "wb" ); |
77 | | - if( $this->mCurlDestHandle === false ) { |
78 | | - # Could not open temporary file to write in |
79 | | - return 'upload-file-error'; |
80 | | - } |
81 | | - |
82 | | - $ch = curl_init(); |
83 | | - curl_setopt( $ch, CURLOPT_HTTP_VERSION, 1.0); # Probably not needed, but apparently can work around some bug |
84 | | - curl_setopt( $ch, CURLOPT_TIMEOUT, $wgCopyUploadTimeout); # 1 hour timeout |
85 | | - curl_setopt( $ch, CURLOPT_LOW_SPEED_LIMIT, 512); # 0.5KB per second minimum transfer speed |
86 | | - curl_setopt( $ch, CURLOPT_URL, $this->mUrl); |
87 | | - curl_setopt( $ch, CURLOPT_WRITEFUNCTION, array( $this, 'uploadCurlCallback' ) ); |
88 | | - curl_exec( $ch ); |
89 | | - $error = curl_errno( $ch ); |
90 | | - curl_close( $ch ); |
91 | | - |
92 | | - fclose( $this->mCurlDestHandle ); |
93 | | - unset( $this->mCurlDestHandle ); |
94 | | - |
95 | | - if( $error ) |
96 | | - return "upload-curl-error$errornum"; |
97 | | - |
98 | | - return true; |
99 | | - } |
100 | | - */ |
101 | 72 | /** |
102 | 73 | * Callback function for CURL-based web transfer |
103 | 74 | * Write data to file unless we've passed the length limit; |
Index: branches/new-upload/phase3/includes/HttpFunctions.php |
— | — | @@ -18,17 +18,17 @@ |
19 | 19 | $req = newReq($url, $opts ); |
20 | 20 | return $req->request(); |
21 | 21 | } |
22 | | - //setup a new request |
23 | | - public static function newReq($url, $opts){ |
24 | | - $req = new Http(); |
25 | | - $req->url = $url; |
26 | | - $req->method = (isset($opt['method']))?$opt['method']:'GET'; |
27 | | - $req->target_file = (isset($opt['target_file']))?$opt['target_file']:false; |
28 | | - return $req; |
| 22 | + /** |
| 23 | + * Simple wrapper for Http::request( 'POST' ) |
| 24 | + */ |
| 25 | + public static function post( $url, $opts = array() ) { |
| 26 | + $opts['method']='POST'; |
| 27 | + $req = newReq($url, $opts ); |
| 28 | + return $req->request(); |
29 | 29 | } |
30 | | - public static function doDownload( $url, $target_path , $dl_mode = self::SYNC_DOWNLOAD ){ |
| 30 | + public static function doDownload( $url, $target_file_path , $dl_mode = self::SYNC_DOWNLOAD ){ |
31 | 31 | global $wgPhpCliPath, $wgMaxUploadSize; |
32 | | - |
| 32 | + print "doDownload:$target_file_path"; |
33 | 33 | //do a quick check to HEAD to insure the file size is not > $wgMaxUploadSize to large no need to download it |
34 | 34 | $head = get_headers($url, 1); |
35 | 35 | if(isset($head['Content-Length']) && $head['Content-Length'] > $wgMaxUploadSize){ |
— | — | @@ -36,29 +36,39 @@ |
37 | 37 | } |
38 | 38 | |
39 | 39 | //check if we can find phpCliPath (for doing a background shell request to php to do the download: |
40 | | - if( $wgPhpCliPath && wfShellExecEnabled() && $dl_mode == self::ASYNC_DOWNLOAD){ |
41 | | - //setup session |
42 | | - die('do shell exec'); |
43 | | - //do shell exec req |
| 40 | + if( $wgPhpCliPath && wfShellExecEnabled() && $dl_mode == self::ASYNC_DOWNLOAD){ |
| 41 | + //setup session and shell call: |
| 42 | + return self::initBackgroundDownload( $url, $target_file_path ); |
44 | 43 | |
45 | 44 | //return success status and download_session_key |
46 | 45 | |
47 | 46 | //(separate ajax request can now check on the status of the shell exec)... and even kill or cancel it) |
48 | 47 | |
49 | 48 | }else if( $dl_mode== self::SYNC_DOWNLOAD ){ |
50 | | - //else just download as much as we can in the time we have left: |
51 | | - return self::doDownloadtoFile($url, $target_path); |
| 49 | + //else just download as much as we can in the time we have left: |
| 50 | + $opts['method']='GET'; |
| 51 | + $opts['target_file_path'] = $target_file_path; |
| 52 | + $req = self::newReq($url, $opts ); |
| 53 | + return $req->request(); |
52 | 54 | } |
53 | 55 | } |
| 56 | + //setup a new request |
| 57 | + public static function newReq($url, $opt){ |
| 58 | + $req = new Http(); |
| 59 | + $req->url = $url; |
| 60 | + $req->method = (isset($opt['method']))?$opt['method']:'GET'; |
| 61 | + $req->target_file_path = (isset($opt['target_file_path']))?$opt['target_file_path']:false; |
| 62 | + return $req; |
| 63 | + } |
54 | 64 | /** |
55 | 65 | * a non blocking request (generally an exit point in the application) |
56 | 66 | * should write to a file location and give updates |
57 | 67 | * |
58 | 68 | */ |
59 | | - public static function initBackgroundDownload( $url ){ |
| 69 | + private function initBackgroundDownload( $url, $target_file_path ){ |
60 | 70 | global $wgMaxUploadSize; |
61 | 71 | $status = Status::newGood(); |
62 | | - //generate a session id with all the details for the download (pid, target_file ) |
| 72 | + //generate a session id with all the details for the download (pid, target_file_path ) |
63 | 73 | |
64 | 74 | //later add in (destName & description) |
65 | 75 | $session_id = session_id(); |
— | — | @@ -67,54 +77,43 @@ |
68 | 78 | |
69 | 79 | //return status |
70 | 80 | return $status; |
71 | | - } |
72 | | - //called from the command line: : |
| 81 | + } |
| 82 | + /** |
| 83 | + * used to run a session based download. Is initiated via the shell. |
| 84 | + * |
| 85 | + * @param string $dn_session_id // the session id to grab download details from |
| 86 | + */ |
73 | 87 | public static function doSessionIdDownload( $dn_session_id ){ |
74 | 88 | //get all the vars we need from session_id |
75 | 89 | session_id( $dn_session_id ); |
76 | 90 | $url = $_SESSION[ 'wsDownload' ][ 'url' ]; |
77 | | - $target_file_path = $_SESSION[ 'wsDownload' ][ 'target_file_path' ]; |
78 | | - self::doDownloadtoFile($url, $target_file_path); |
79 | | - return true; |
| 91 | + $target_file_path_path = $_SESSION[ 'wsDownload' ][ 'target_file_path_path' ]; |
| 92 | + |
| 93 | + //new req here: |
80 | 94 | } |
81 | | - public static function doDownloadtoFile($url, $target_file_path){ |
82 | | - global $wgCopyUploadTimeout; |
83 | | - $req = self::newReq($url, array( |
84 | | - 'target_file'=> $target_file_path |
85 | | - ) ); |
86 | | - $status = $req->request( $url ); |
87 | | - print "downloading $url \nto FILE target: $target_file_path \n" . filesize( $target_file_path ) . "\n"; |
88 | | - return Status::newGood('upload-ok'); |
89 | | - } |
90 | 95 | /** |
91 | | - * Simple wrapper for Http::request( 'POST' ) |
92 | | - */ |
93 | | - public static function post( $url, $opts = array() ) { |
94 | | - $opts['method']='POST'; |
95 | | - return Http::request( $url, $opts ); |
96 | | - } |
97 | | - /** |
98 | 96 | * Get the contents of a file by HTTP |
99 | 97 | * @param $url string Full URL to act on |
100 | 98 | * @param $Opt associative array Optional array of options: |
101 | 99 | * 'method' => 'GET', 'POST' etc. |
102 | | - * 'target_file' => if curl should output to a target file |
| 100 | + * 'target_file_path' => if curl should output to a target file |
103 | 101 | * 'adapter' => 'curl', 'soket' |
104 | 102 | */ |
105 | 103 | private function request() { |
106 | 104 | global $wgHTTPTimeout, $wgHTTPProxy, $wgTitle; |
107 | 105 | |
108 | | - wfDebug( __METHOD__ . ": $method $url\n" ); |
| 106 | + wfDebug( __METHOD__ . ": $method $url\n" ); |
109 | 107 | # Use curl if available |
110 | | - if ( function_exists( 'curl_init' ) ) { |
| 108 | + if ( function_exists( 'curl_init' ) ) { |
111 | 109 | return $this->doCurlReq(); |
112 | | - }else{ |
| 110 | + }else{ |
113 | 111 | return $this->doPhpReq(); |
114 | 112 | } |
115 | 113 | } |
116 | 114 | private function doCurlReq(){ |
| 115 | + $status = Status::newGood(); |
117 | 116 | $c = curl_init( $this->url ); |
118 | | - |
| 117 | + |
119 | 118 | //proxy setup: |
120 | 119 | if ( self::isLocalURL( $this->url ) ) { |
121 | 120 | curl_setopt( $c, CURLOPT_PROXY, 'localhost:80' ); |
— | — | @@ -144,28 +143,36 @@ |
145 | 144 | } |
146 | 145 | |
147 | 146 | //set the write back function (if we are writing to a file) |
148 | | - if( $this->target_file ){ |
149 | | - $cwrite = new simpleFileWriter( $this->target_file ); |
| 147 | + if( $this->target_file_path ){ |
| 148 | + $cwrite = new simpleFileWriter( $this->target_file_path ); |
150 | 149 | curl_setopt( $c, CURLOPT_WRITEFUNCTION, array($cwrite, 'callbackWriteBody') ); |
151 | 150 | } |
152 | 151 | |
153 | 152 | //start output grabber: |
154 | | - if(!$this->target_file) |
| 153 | + if(!$this->target_file_path) |
155 | 154 | ob_start(); |
156 | | - |
| 155 | + |
| 156 | + //run the actual curl_exec: |
157 | 157 | try { |
158 | 158 | if (false === curl_exec($c)) { |
159 | 159 | $status = Status::newFatal( 'Error sending request: #' . curl_errno($c) . |
160 | | - ' ' . curl_error($c) ); |
| 160 | + ' '. curl_error($c) ); |
161 | 161 | } |
162 | 162 | } catch (Exception $e) { |
163 | 163 | //do something with curl exec error? |
164 | 164 | } |
165 | 165 | //if direct request output the results to the stats value: |
166 | | - if( !$target_file && $status->isOK() ){ |
| 166 | + if( !$this->target_file_path && $status->isOK() ){ |
167 | 167 | $status->value = ob_get_contents(); |
168 | 168 | ob_end_clean(); |
169 | | - } |
| 169 | + } |
| 170 | + //if we wrote to a target file close up or return error |
| 171 | + if( $this->target_file_path ){ |
| 172 | + $cwrite->close(); |
| 173 | + if( ! $cwrite->status->isOK() ){ |
| 174 | + return $cwrite->status; |
| 175 | + } |
| 176 | + } |
170 | 177 | |
171 | 178 | # Don't return the text of error messages, return false on error |
172 | 179 | $retcode = curl_getinfo( $c, CURLINFO_HTTP_CODE ); |
— | — | @@ -180,10 +187,8 @@ |
181 | 188 | wfDebug( __METHOD__ . ": CURL error code $errno: $errstr\n" ); |
182 | 189 | $status = Status::newFatal( " CURL error code $errno: $errstr\n" ); |
183 | 190 | } |
184 | | - curl_close( $c ); |
185 | | - |
186 | | - |
187 | | - |
| 191 | + curl_close( $c ); |
| 192 | + |
188 | 193 | //return the result obj |
189 | 194 | return $status; |
190 | 195 | } |
— | — | @@ -255,14 +260,35 @@ |
256 | 261 | * a simpleFileWriter |
257 | 262 | */ |
258 | 263 | class simpleFileWriter{ |
259 | | - var $target_file; |
260 | | - function __constructor($target_file){ |
261 | | - $this->target_file = $target_file; |
| 264 | + var $target_file_path; |
| 265 | + var $status = null; |
| 266 | + function simpleFileWriter($target_file_path){ |
| 267 | + $this->target_file_path = $target_file_path; |
| 268 | + $this->status = Status::newGood(); |
| 269 | + //open the file: |
| 270 | + $this->fp = fopen( $this->target_file_path, 'w'); |
| 271 | + if( $this->fp === false ){ |
| 272 | + $this->status = Status::newFatal('HTTP::could-not-open-file-for-writing'); |
| 273 | + } |
262 | 274 | } |
263 | | - public function callbackWriteBody($ch, $string){ |
264 | | - $wgMaxUploadSize; |
265 | | - //write out to the target file |
266 | | - |
267 | | - // |
| 275 | + public function callbackWriteBody($ch, $data_packet){ |
| 276 | + global $wgMaxUploadSize; |
| 277 | + //check file size: |
| 278 | + clearstatcache(); |
| 279 | + if( filesize( $this->target_file_path) > $wgMaxUploadSize){ |
| 280 | + $this->status = Status::newFatal('HTTP::file-has-grown-beyond-upload-limit-killing: '. filesize( $this->target_file_path) . ' > ' . $wgMaxUploadSize); |
| 281 | + return ; |
| 282 | + } |
| 283 | + //write out the content |
| 284 | + if( fwrite($this->fp, $data_packet) === false){ |
| 285 | + $this->status = Status::newFatal('HTTP::could-not-write-to-file'); |
| 286 | + return 0; |
| 287 | + } |
| 288 | + return strlen($data_packet); |
268 | 289 | } |
| 290 | + public function close(){ |
| 291 | + if(false === fclose( $this->fp )){ |
| 292 | + $this->status = Status::newFatal('HTTP::could-not-close-file'); |
| 293 | + } |
| 294 | + } |
269 | 295 | } |
\ No newline at end of file |