* (bug 32341) Add upload by URL domain limitation.
authorSam Reed <reedy@users.mediawiki.org>
Thu, 19 Jan 2012 19:16:06 +0000 (19:16 +0000)
committerSam Reed <reedy@users.mediawiki.org>
Thu, 19 Jan 2012 19:16:06 +0000 (19:16 +0000)
RELEASE-NOTES-1.19
includes/DefaultSettings.php
includes/HttpFunctions.php
includes/api/ApiBase.php
includes/api/ApiUpload.php
includes/specials/SpecialUpload.php
includes/upload/UploadFromUrl.php
languages/messages/MessagesEn.php

index a12e656..1e6ddb7 100644 (file)
@@ -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.
index 1a2c47a..35c9de7 100644 (file)
@@ -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
index f8e7b37..147823f 100644 (file)
@@ -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 ) {
index 133339a..6105dec 100644 (file)
@@ -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' ),
index e8fc52a..6001651 100644 (file)
@@ -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;
index fde1e12..a3e700a 100644 (file)
@@ -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' ) );
 
index 747b842..cfedb79 100644 (file)
@@ -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 );
index aad39fe..ee2d757 100644 (file)
@@ -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.',