6 * Implements uploading from a HTTP resource.
8 * @author Bryan Tong Minh
11 class UploadFromUrl
extends UploadBase
{
12 protected $mTempDownloadPath;
15 * Checks if the user is allowed to use the upload-by-URL feature. If the
16 * user is allowed, pass on permissions checking to the parent.
18 public static function isAllowed( $user ) {
19 if( !$user->isAllowed( 'upload_by_url' ) )
20 return 'upload_by_url';
21 return parent
::isAllowed( $user );
25 * Checks if the upload from URL feature is enabled
27 public static function isEnabled() {
28 global $wgAllowCopyUploads;
29 return $wgAllowCopyUploads && parent
::isEnabled();
33 * Entry point for API upload
35 public function initialize( $name, $url, $na, $nb = false ) {
36 global $wgTmpDirectory;
38 $localFile = tempnam( $wgTmpDirectory, 'WEBUPLOAD' );
39 $this->initializePathInfo( $name, $localFile, 0, true );
41 $this->mUrl
= trim( $url );
45 * Entry point for SpecialUpload
46 * @param $request Object: WebRequest object
48 public function initializeFromRequest( &$request ) {
49 $desiredDestName = $request->getText( 'wpDestFile' );
50 if( !$desiredDestName )
51 $desiredDestName = $request->getText( 'wpUploadFileURL' );
52 return $this->initialize(
54 $request->getVal( 'wpUploadFileURL' ),
60 * @param $request Object: WebRequest object
62 public static function isValidRequest( $request ){
63 if( !$request->getVal( 'wpUploadFileURL' ) )
65 // check that is a valid url:
66 return self
::isValidUrl( $request->getVal( 'wpUploadFileURL' ) );
69 public static function isValidUrl( $url ) {
70 // Only allow HTTP or FTP for now
71 return (bool)preg_match( '!^(http://|ftp://)!', $url );
75 * Do the real fetching stuff
77 function fetchFile() {
78 if( !self
::isValidUrl( $this->mUrl
) ) {
79 return Status
::newFatal( 'upload-proto-error' );
81 $res = $this->curlCopy();
83 return Status
::newFatal( $res );
85 return Status
::newGood();
90 * Returns true if there was an error, false otherwise
92 private function curlCopy() {
96 $this->mCurlDestHandle
= @fopen
( $this->mTempPath
, "wb" );
97 if( $this->mCurlDestHandle
=== false ) {
98 # Could not open temporary file to write in
99 return 'upload-file-error';
103 curl_setopt( $ch, CURLOPT_HTTP_VERSION
, 1.0); # Probably not needed, but apparently can work around some bug
104 curl_setopt( $ch, CURLOPT_TIMEOUT
, 10); # 10 seconds timeout
105 curl_setopt( $ch, CURLOPT_LOW_SPEED_LIMIT
, 512); # 0.5KB per second minimum transfer speed
106 curl_setopt( $ch, CURLOPT_URL
, $this->mUrl
);
107 curl_setopt( $ch, CURLOPT_WRITEFUNCTION
, array( $this, 'uploadCurlCallback' ) );
109 $error = curl_errno( $ch );
112 fclose( $this->mCurlDestHandle
);
113 unset( $this->mCurlDestHandle
);
116 return "upload-curl-error$errornum";
122 * Callback function for CURL-based web transfer
123 * Write data to file unless we've passed the length limit;
124 * if so, abort immediately.
127 function uploadCurlCallback( $ch, $data ) {
128 global $wgMaxUploadSize;
129 $length = strlen( $data );
130 $this->mFileSize +
= $length;
131 if( $this->mFileSize
> $wgMaxUploadSize ) {
134 fwrite( $this->mCurlDestHandle
, $data );