From f61956472099642cd30ac7ae215f9ddff69633dd Mon Sep 17 00:00:00 2001 From: Sam Reed Date: Thu, 19 Jan 2012 19:16:06 +0000 Subject: [PATCH] * (bug 32341) Add upload by URL domain limitation. --- RELEASE-NOTES-1.19 | 1 + includes/DefaultSettings.php | 4 ++++ includes/HttpFunctions.php | 2 +- includes/api/ApiBase.php | 1 + includes/api/ApiUpload.php | 5 ++++- includes/specials/SpecialUpload.php | 7 ++----- includes/upload/UploadFromUrl.php | 31 +++++++++++++++++++++++++---- languages/messages/MessagesEn.php | 1 + 8 files changed, 41 insertions(+), 11 deletions(-) diff --git a/RELEASE-NOTES-1.19 b/RELEASE-NOTES-1.19 index a12e656b84..1e6ddb7758 100644 --- a/RELEASE-NOTES-1.19 +++ b/RELEASE-NOTES-1.19 @@ -120,6 +120,7 @@ production. * (bug 29309) allow CSS class per tooltip (tipsy) * (bug 33565) Add accesskey/tooltip to submit buttons on Special:EditWatchlist. * (bug 17959) Inline rendering/thumbnailing for Gimp XCF images +* (bug 32341) Add upload by URL domain limitation. === Bug fixes in 1.19 === * $wgUploadNavigationUrl should be used for file redlinks if. diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 1a2c47adda..35c9de7250 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -451,6 +451,10 @@ $wgAllowCopyUploads = false; * This feature is experimental and broken as of r81612. */ $wgAllowAsyncCopyUploads = false; +/** + * A list of domains copy uploads can come from + */ +$wgCopyUploadsDomains = array(); /** * Max size for uploads, in bytes. If not set to an array, applies to all diff --git a/includes/HttpFunctions.php b/includes/HttpFunctions.php index f8e7b37a8d..147823fee7 100644 --- a/includes/HttpFunctions.php +++ b/includes/HttpFunctions.php @@ -233,7 +233,7 @@ class MWHttpRequest { * Generate a new request object * @param $url String: url to use * @param $options Array: (optional) extra params to pass (see Http::request()) - * @return \CurlHttpRequest|\PhpHttpRequest + * @return CurlHttpRequest|PhpHttpRequest * @see MWHttpRequest::__construct */ public static function factory( $url, $options = null ) { diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php index 133339a1b3..6105dec227 100644 --- a/includes/api/ApiBase.php +++ b/includes/api/ApiBase.php @@ -1231,6 +1231,7 @@ abstract class ApiBase extends ContextSource { 'nouploadmodule' => array( 'code' => 'nouploadmodule', 'info' => 'No upload module set' ), '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' ), 'copyuploaddisabled' => array( 'code' => 'copyuploaddisabled', 'info' => 'Uploads by URL is not enabled. Make sure $wgAllowCopyUploads is set to true in LocalSettings.php.' ), + 'copyuploadbaddomain' => array( 'code' => 'copyuploadbaddomain', 'info' => 'Uploads by URL are not allowed from this domain.' ), 'filename-tooshort' => array( 'code' => 'filename-tooshort', 'info' => 'The filename is too short' ), 'filename-toolong' => array( 'code' => 'filename-toolong', 'info' => 'The filename is too long' ), diff --git a/includes/api/ApiUpload.php b/includes/api/ApiUpload.php index e8fc52ade1..60016512b0 100644 --- a/includes/api/ApiUpload.php +++ b/includes/api/ApiUpload.php @@ -318,6 +318,10 @@ class ApiUpload extends ApiBase { $this->dieUsageMsg( 'copyuploaddisabled' ); } + if ( !UploadFromUrl::isAllowedHost( $this->mParams['url'] ) ) { + $this->dieUsageMsg( 'copyuploadbaddomain' ); + } + $async = false; if ( $this->mParams['asyncdownload'] ) { $this->checkAsyncDownloadEnabled(); @@ -336,7 +340,6 @@ class ApiUpload extends ApiBase { $this->mUpload = new UploadFromUrl; $this->mUpload->initialize( $this->mParams['filename'], $this->mParams['url'], $async ); - } return true; diff --git a/includes/specials/SpecialUpload.php b/includes/specials/SpecialUpload.php index fde1e12e6b..a3e700a2ae 100644 --- a/includes/specials/SpecialUpload.php +++ b/includes/specials/SpecialUpload.php @@ -177,8 +177,7 @@ class SpecialUpload extends SpecialPage { if ( $this->mTokenOk && !$this->mCancelUpload && ( $this->mUpload && $this->mUploadClicked ) - ) - { + ) { $this->processUpload(); } else { # Backwards compatibility hook @@ -186,8 +185,6 @@ class SpecialUpload extends SpecialPage { wfDebug( "Hook 'UploadForm:initial' broke output of the upload form" ); return; } - - $this->showUploadForm( $this->getUploadForm() ); } @@ -821,7 +818,7 @@ class UploadForm extends HTMLForm { ); } - $canUploadByUrl = UploadFromUrl::isEnabled() && $this->getUser()->isAllowed( 'upload_by_url' ); + $canUploadByUrl = UploadFromUrl::isEnabled() && UploadFromUrl::isAllowed( $this->getUser() ); $radio = $canUploadByUrl; $selectedSourceType = strtolower( $this->getRequest()->getText( 'wpSourceType', 'File' ) ); diff --git a/includes/upload/UploadFromUrl.php b/includes/upload/UploadFromUrl.php index 747b842cb3..cfedb792cc 100644 --- a/includes/upload/UploadFromUrl.php +++ b/includes/upload/UploadFromUrl.php @@ -37,6 +37,27 @@ class UploadFromUrl extends UploadBase { return $wgAllowCopyUploads && parent::isEnabled(); } + /** + * Checks whether the URL is for an allowed host + * + * @param $url string + * @return bool + */ + public static function isAllowedHost( $url ) { + global $wgCopyUploadsDomains; + if ( !count( $wgCopyUploadsDomains ) ) { + return true; + } + $valid = false; + foreach( $wgCopyUploadsDomains as $domain ) { + if ( strpos( $url, $domain ) !== false ) { + $valid = true; + break; + } + } + return $valid; + } + /** * Entry point for API upload * @@ -66,8 +87,9 @@ class UploadFromUrl extends UploadBase { */ public function initializeFromRequest( &$request ) { $desiredDestName = $request->getText( 'wpDestFile' ); - if ( !$desiredDestName ) + if ( !$desiredDestName ) { $desiredDestName = $request->getText( 'wpUploadFileURL' ); + } return $this->initialize( $desiredDestName, trim( $request->getVal( 'wpUploadFileURL' ) ), @@ -101,6 +123,9 @@ class UploadFromUrl extends UploadBase { return Status::newFatal( 'http-invalid-url' ); } + if( !self::isAllowedHost( $this->mUrl ) ) { + return Status::newFatal( 'upload-copy-upload-invalid-domain' ); + } if ( !$this->mAsync ) { return $this->reallyFetchFile(); } @@ -219,9 +244,7 @@ class UploadFromUrl extends UploadBase { if ( $this->mAsync ) { $sessionKey = $this->insertJob( $comment, $pageText, $watch, $user ); - $status = new Status; - $status->error( 'async', $sessionKey ); - return $status; + return Status::newFatal( 'async', $sessionKey ); } return parent::performUpload( $comment, $pageText, $watch, $user ); diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index aad39feb14..ee2d7578d8 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -2235,6 +2235,7 @@ If the problem persists, contact an [[Special:ListUsers/sysop|administrator]].', 'upload-too-many-redirects' => 'The URL contained too many redirects', 'upload-unknown-size' => 'Unknown size', 'upload-http-error' => 'An HTTP error occured: $1', +'upload-copy-upload-invalid-domain' => 'Copy uploads are not available from this domain.', # File backend 'backend-fail-stream' => 'Could not stream file $1.', -- 2.20.1