Index: trunk/phase3/RELEASE-NOTES-1.19 |
— | — | @@ -120,6 +120,7 @@ |
121 | 121 | * (bug 29309) allow CSS class per tooltip (tipsy) |
122 | 122 | * (bug 33565) Add accesskey/tooltip to submit buttons on Special:EditWatchlist. |
123 | 123 | * (bug 17959) Inline rendering/thumbnailing for Gimp XCF images |
| 124 | +* (bug 32341) Add upload by URL domain limitation. |
124 | 125 | |
125 | 126 | === Bug fixes in 1.19 === |
126 | 127 | * $wgUploadNavigationUrl should be used for file redlinks if. |
Index: trunk/phase3/includes/upload/UploadFromUrl.php |
— | — | @@ -38,6 +38,27 @@ |
39 | 39 | } |
40 | 40 | |
41 | 41 | /** |
| 42 | + * Checks whether the URL is for an allowed host |
| 43 | + * |
| 44 | + * @param $url string |
| 45 | + * @return bool |
| 46 | + */ |
| 47 | + public static function isAllowedHost( $url ) { |
| 48 | + global $wgCopyUploadsDomains; |
| 49 | + if ( !count( $wgCopyUploadsDomains ) ) { |
| 50 | + return true; |
| 51 | + } |
| 52 | + $valid = false; |
| 53 | + foreach( $wgCopyUploadsDomains as $domain ) { |
| 54 | + if ( strpos( $url, $domain ) !== false ) { |
| 55 | + $valid = true; |
| 56 | + break; |
| 57 | + } |
| 58 | + } |
| 59 | + return $valid; |
| 60 | + } |
| 61 | + |
| 62 | + /** |
42 | 63 | * Entry point for API upload |
43 | 64 | * |
44 | 65 | * @param $name string |
— | — | @@ -66,8 +87,9 @@ |
67 | 88 | */ |
68 | 89 | public function initializeFromRequest( &$request ) { |
69 | 90 | $desiredDestName = $request->getText( 'wpDestFile' ); |
70 | | - if ( !$desiredDestName ) |
| 91 | + if ( !$desiredDestName ) { |
71 | 92 | $desiredDestName = $request->getText( 'wpUploadFileURL' ); |
| 93 | + } |
72 | 94 | return $this->initialize( |
73 | 95 | $desiredDestName, |
74 | 96 | trim( $request->getVal( 'wpUploadFileURL' ) ), |
— | — | @@ -101,6 +123,9 @@ |
102 | 124 | return Status::newFatal( 'http-invalid-url' ); |
103 | 125 | } |
104 | 126 | |
| 127 | + if( !self::isAllowedHost( $this->mUrl ) ) { |
| 128 | + return Status::newFatal( 'upload-copy-upload-invalid-domain' ); |
| 129 | + } |
105 | 130 | if ( !$this->mAsync ) { |
106 | 131 | return $this->reallyFetchFile(); |
107 | 132 | } |
— | — | @@ -219,9 +244,7 @@ |
220 | 245 | if ( $this->mAsync ) { |
221 | 246 | $sessionKey = $this->insertJob( $comment, $pageText, $watch, $user ); |
222 | 247 | |
223 | | - $status = new Status; |
224 | | - $status->error( 'async', $sessionKey ); |
225 | | - return $status; |
| 248 | + return Status::newFatal( 'async', $sessionKey ); |
226 | 249 | } |
227 | 250 | |
228 | 251 | return parent::performUpload( $comment, $pageText, $watch, $user ); |
Index: trunk/phase3/includes/api/ApiBase.php |
— | — | @@ -1231,6 +1231,7 @@ |
1232 | 1232 | 'nouploadmodule' => array( 'code' => 'nouploadmodule', 'info' => 'No upload module set' ), |
1233 | 1233 | 'uploaddisabled' => array( 'code' => 'uploaddisabled', 'info' => 'Uploads are not enabled. Make sure $wgEnableUploads is set to true in LocalSettings.php and the PHP ini setting file_uploads is true' ), |
1234 | 1234 | 'copyuploaddisabled' => array( 'code' => 'copyuploaddisabled', 'info' => 'Uploads by URL is not enabled. Make sure $wgAllowCopyUploads is set to true in LocalSettings.php.' ), |
| 1235 | + 'copyuploadbaddomain' => array( 'code' => 'copyuploadbaddomain', 'info' => 'Uploads by URL are not allowed from this domain.' ), |
1235 | 1236 | |
1236 | 1237 | 'filename-tooshort' => array( 'code' => 'filename-tooshort', 'info' => 'The filename is too short' ), |
1237 | 1238 | 'filename-toolong' => array( 'code' => 'filename-toolong', 'info' => 'The filename is too long' ), |
Index: trunk/phase3/includes/api/ApiUpload.php |
— | — | @@ -318,6 +318,10 @@ |
319 | 319 | $this->dieUsageMsg( 'copyuploaddisabled' ); |
320 | 320 | } |
321 | 321 | |
| 322 | + if ( !UploadFromUrl::isAllowedHost( $this->mParams['url'] ) ) { |
| 323 | + $this->dieUsageMsg( 'copyuploadbaddomain' ); |
| 324 | + } |
| 325 | + |
322 | 326 | $async = false; |
323 | 327 | if ( $this->mParams['asyncdownload'] ) { |
324 | 328 | $this->checkAsyncDownloadEnabled(); |
— | — | @@ -336,7 +340,6 @@ |
337 | 341 | $this->mUpload = new UploadFromUrl; |
338 | 342 | $this->mUpload->initialize( $this->mParams['filename'], |
339 | 343 | $this->mParams['url'], $async ); |
340 | | - |
341 | 344 | } |
342 | 345 | |
343 | 346 | return true; |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -451,6 +451,10 @@ |
452 | 452 | * This feature is experimental and broken as of r81612. |
453 | 453 | */ |
454 | 454 | $wgAllowAsyncCopyUploads = false; |
| 455 | +/** |
| 456 | + * A list of domains copy uploads can come from |
| 457 | + */ |
| 458 | +$wgCopyUploadsDomains = array(); |
455 | 459 | |
456 | 460 | /** |
457 | 461 | * Max size for uploads, in bytes. If not set to an array, applies to all |
Index: trunk/phase3/includes/HttpFunctions.php |
— | — | @@ -233,7 +233,7 @@ |
234 | 234 | * Generate a new request object |
235 | 235 | * @param $url String: url to use |
236 | 236 | * @param $options Array: (optional) extra params to pass (see Http::request()) |
237 | | - * @return \CurlHttpRequest|\PhpHttpRequest |
| 237 | + * @return CurlHttpRequest|PhpHttpRequest |
238 | 238 | * @see MWHttpRequest::__construct |
239 | 239 | */ |
240 | 240 | public static function factory( $url, $options = null ) { |
Index: trunk/phase3/includes/specials/SpecialUpload.php |
— | — | @@ -177,8 +177,7 @@ |
178 | 178 | if ( |
179 | 179 | $this->mTokenOk && !$this->mCancelUpload && |
180 | 180 | ( $this->mUpload && $this->mUploadClicked ) |
181 | | - ) |
182 | | - { |
| 181 | + ) { |
183 | 182 | $this->processUpload(); |
184 | 183 | } else { |
185 | 184 | # Backwards compatibility hook |
— | — | @@ -186,8 +185,6 @@ |
187 | 186 | wfDebug( "Hook 'UploadForm:initial' broke output of the upload form" ); |
188 | 187 | return; |
189 | 188 | } |
190 | | - |
191 | | - |
192 | 189 | $this->showUploadForm( $this->getUploadForm() ); |
193 | 190 | } |
194 | 191 | |
— | — | @@ -821,7 +818,7 @@ |
822 | 819 | ); |
823 | 820 | } |
824 | 821 | |
825 | | - $canUploadByUrl = UploadFromUrl::isEnabled() && $this->getUser()->isAllowed( 'upload_by_url' ); |
| 822 | + $canUploadByUrl = UploadFromUrl::isEnabled() && UploadFromUrl::isAllowed( $this->getUser() ); |
826 | 823 | $radio = $canUploadByUrl; |
827 | 824 | $selectedSourceType = strtolower( $this->getRequest()->getText( 'wpSourceType', 'File' ) ); |
828 | 825 | |
Index: trunk/phase3/languages/messages/MessagesEn.php |
— | — | @@ -2235,6 +2235,7 @@ |
2236 | 2236 | 'upload-too-many-redirects' => 'The URL contained too many redirects', |
2237 | 2237 | 'upload-unknown-size' => 'Unknown size', |
2238 | 2238 | 'upload-http-error' => 'An HTTP error occured: $1', |
| 2239 | +'upload-copy-upload-invalid-domain' => 'Copy uploads are not available from this domain.', |
2239 | 2240 | |
2240 | 2241 | # File backend |
2241 | 2242 | 'backend-fail-stream' => 'Could not stream file $1.', |