1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
<?php
class UploadFromUrl extends UploadBase {
static function isAllowed( $user ) {
if( !$user->isAllowed( 'upload_by_url' ) )
return 'upload_by_url';
return parent::isAllowed( $user );
}
static function isEnabled() {
global $wgAllowCopyUploads;
return $wgAllowCopyUploads && parent::isEnabled();
}
function initialize( $name, $url ) {
global $wgTmpDirectory;
$local_file = tempnam( $wgTmpDirectory, 'WEBUPLOAD' );
$this-initialize( $name, $local_file, 0, true );
$this->mUrl = trim( $url );
}
/**
* Do the real fetching stuff
*/
function fetchFile() {
if( stripos($this->mUrl, 'http://') !== 0 && stripos($this->mUrl, 'ftp://') !== 0 ) {
return array(
'status' => self::BEFORE_PROCESSING,
'error' => 'upload-proto-error',
);
}
$res = $this->curlCopy();
if( $res !== true ) {
return array(
'status' => self::BEFORE_PROCESSING,
'error' => $res,
);
}
return self::OK;
}
/**
* Safe copy from URL
* Returns true if there was an error, false otherwise
*/
private function curlCopy() {
global $wgUser, $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';
}
$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;
}
}
|