Refactored UploadFromUrl to use HttpFunctions.
[lhc/web/wiklou.git] / includes / upload / UploadFromUrl.php
1 <?php
2 /**
3 * @file
4 * @ingroup upload
5 *
6 * Implements uploading from a HTTP resource.
7 *
8 * @author Bryan Tong Minh
9 * @author Michael Dale
10 */
11 class UploadFromUrl extends UploadBase {
12 protected $mTempDownloadPath;
13
14 /**
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.
17 */
18 public static function isAllowed( $user ) {
19 if( !$user->isAllowed( 'upload_by_url' ) )
20 return 'upload_by_url';
21 return parent::isAllowed( $user );
22 }
23
24 /**
25 * Checks if the upload from URL feature is enabled
26 */
27 public static function isEnabled() {
28 global $wgAllowCopyUploads;
29 return $wgAllowCopyUploads && parent::isEnabled();
30 }
31
32 /**
33 * Entry point for API upload
34 */
35 public function initialize( $name, $url, $na, $nb = false ) {
36 global $wgTmpDirectory;
37
38 $localFile = tempnam( $wgTmpDirectory, 'WEBUPLOAD' );
39 $this->initializePathInfo( $name, $localFile, 0, true );
40
41 $this->mUrl = trim( $url );
42 }
43
44 /**
45 * Entry point for SpecialUpload
46 * @param $request Object: WebRequest object
47 */
48 public function initializeFromRequest( &$request ) {
49 $desiredDestName = $request->getText( 'wpDestFile' );
50 if( !$desiredDestName )
51 $desiredDestName = $request->getText( 'wpUploadFileURL' );
52 return $this->initialize(
53 $desiredDestName,
54 $request->getVal( 'wpUploadFileURL' ),
55 false
56 );
57 }
58
59 /**
60 * @param $request Object: WebRequest object
61 */
62 public static function isValidRequest( $request ){
63 if( !$request->getVal( 'wpUploadFileURL' ) )
64 return false;
65 // check that is a valid url:
66 return self::isValidUrl( $request->getVal( 'wpUploadFileURL' ) );
67 }
68
69 public static function isValidUrl( $url ) {
70 // Only allow HTTP or FTP for now
71 return (bool)preg_match( '!^(http://|ftp://)!', $url );
72 }
73
74 /**
75 * Do the real fetching stuff
76 */
77 function fetchFile() {
78 if( !self::isValidUrl( $this->mUrl ) ) {
79 return Status::newFatal( 'upload-proto-error' );
80 }
81
82 # Open temporary file
83 $this->mCurlDestHandle = @fopen( $this->mTempPath, "wb" );
84 if( $this->mCurlDestHandle === false ) {
85 # Could not open temporary file to write in
86 return Status::newFatal( 'upload-file-error' );
87 }
88
89 $options = array(
90 'method' => 'GET',
91 'timeout' => 10,
92 );
93 $req = HttpRequest::factory( $this->mUrl, $options );
94 $req->setCallback( array( $this, 'uploadCurlCallback' ) );
95 $status = $req->execute();
96 fclose( $this->mCurlDestHandle );
97 unset( $this->mCurlDestHandle );
98
99 return $status;
100 }
101
102 /**
103 * Callback function for CURL-based web transfer
104 * Write data to file unless we've passed the length limit;
105 * if so, abort immediately.
106 * @access private
107 */
108 function uploadCurlCallback( $ch, $data ) {
109 global $wgMaxUploadSize;
110 $length = strlen( $data );
111 $this->mFileSize += $length;
112 if( $this->mFileSize > $wgMaxUploadSize ) {
113 return 0;
114 }
115 fwrite( $this->mCurlDestHandle, $data );
116 return $length;
117 }
118 }