Add better error message for files which exceeds $wgMaxImageArea
authorumherirrender <umherirrender_de.wp@web.de>
Wed, 25 Jun 2014 19:30:08 +0000 (21:30 +0200)
committerGergő Tisza <gtisza@wikimedia.org>
Mon, 15 Dec 2014 08:25:04 +0000 (08:25 +0000)
Added a TransformTooBigImageAreaError to allow setting an extra message.
Added also size-*pixel messages to show the value of $wgMaxImageArea
with some formatting.

This error is still throwing for all files, to fix bug T34387 this needs
a follow up with a proper check. I am not sure, if a File::isLocal() is
okay, because files from a DBForeignRepo maybe transformed on the same
server, so the check needs to be done also for this. For APIForeignRepo
the check is done on the foreign server.

Change-Id: Ieba12e424c8bddb1961a30d3f9ea5c8ff241abb5

autoload.php
includes/media/MediaTransformOutput.php
includes/media/TransformationalImageHandler.php
languages/i18n/en.json
languages/i18n/qqq.json
tests/phpunit/includes/media/BitmapScalingTest.php

index 175ab42..107ab81 100644 (file)
@@ -1179,6 +1179,7 @@ $wgAutoloadLocalClasses = array(
        'TraditionalImageGallery' => __DIR__ . '/includes/gallery/TraditionalImageGallery.php',
        'TransactionProfiler' => __DIR__ . '/includes/profiler/TransactionProfiler.php',
        'TransformParameterError' => __DIR__ . '/includes/media/MediaTransformOutput.php',
+       'TransformTooBigImageAreaError' => __DIR__ . '/includes/media/MediaTransformOutput.php',
        'TransformationalImageHandler' => __DIR__ . '/includes/media/TransformationalImageHandler.php',
        'UDPRCFeedEngine' => __DIR__ . '/includes/rcfeed/UDPRCFeedEngine.php',
        'UIDGenerator' => __DIR__ . '/includes/utils/UIDGenerator.php',
index 98f7552..1dd8519 100644 (file)
@@ -477,3 +477,24 @@ class TransformParameterError extends MediaTransformError {
                        wfMessage( 'thumbnail_invalid_params' )->text() );
        }
 }
+
+/**
+ * Shortcut class for parameter file size errors
+ *
+ * @ingroup Media
+ * @since 1.25
+ */
+class TransformTooBigImageAreaError extends MediaTransformError {
+       function __construct( $params, $maxImageArea ) {
+               $msg = wfMessage( 'thumbnail_toobigimagearea' );
+
+               parent::__construct( 'thumbnail_error',
+                       max( isset( $params['width'] ) ? $params['width'] : 0, 120 ),
+                       max( isset( $params['height'] ) ? $params['height'] : 0, 120 ),
+                       $msg->rawParams(
+                               $msg->getLanguage()->formatComputingNumbers(
+                                       $maxImageArea, 1000, "size-$1pixel" )
+                               )->text()
+                       );
+       }
+}
index 5b9982d..51cd28d 100644 (file)
@@ -61,29 +61,6 @@ abstract class TransformationalImageHandler extends ImageHandler {
                        }
                }
 
-               # Check if the file is smaller than the maximum image area for thumbnailing
-               # For historical reasons, hook starts with BitmapHandler
-               $checkImageAreaHookResult = null;
-               Hooks::run(
-                       'BitmapHandlerCheckImageArea',
-                       array( $image, &$params, &$checkImageAreaHookResult )
-               );
-
-               if ( is_null( $checkImageAreaHookResult ) ) {
-                       global $wgMaxImageArea;
-
-                       if ( $srcWidth * $srcHeight > $wgMaxImageArea
-                               && !( $image->getMimeType() == 'image/jpeg'
-                                       && $this->getScalerType( false, false ) == 'im' )
-                       ) {
-                               # Only ImageMagick can efficiently downsize jpg images without loading
-                               # the entire file in memory
-                               return false;
-                       }
-               } else {
-                       return $checkImageAreaHookResult;
-               }
-
                return true;
        }
 
@@ -190,6 +167,11 @@ abstract class TransformationalImageHandler extends ImageHandler {
                        return $this->getClientScalingThumbnailImage( $image, $scalerParams );
                }
 
+               if ( !$this->isImageAreaOkForThumbnaling( $image, $params ) ) {
+                       global $wgMaxImageArea;
+                       return new TransformTooBigImageAreaError( $params, $wgMaxImageArea );
+               }
+
                if ( $flags & self::TRANSFORM_LATER ) {
                        wfDebug( __METHOD__ . ": Transforming later per flags.\n" );
                        $newParams = array(
@@ -596,4 +578,43 @@ abstract class TransformationalImageHandler extends ImageHandler {
        public function mustRender( $file ) {
                return $this->canRotate() && $this->getRotation( $file ) != 0;
        }
+
+       /**
+        * Check if the file is smaller than the maximum image area for thumbnailing.
+        *
+        * Runs the 'BitmapHandlerCheckImageArea' hook.
+        *
+        * @param File $file
+        * @param array $params
+        * @return bool
+        * @since 1.25
+        */
+       public function isImageAreaOkForThumbnaling( $file, $params ) {
+               global $wgMaxImageArea;
+
+               # For historical reasons, hook starts with BitmapHandler
+               $checkImageAreaHookResult = null;
+               Hooks::run(
+                       'BitmapHandlerCheckImageArea',
+                       array( $file, $params, &$checkImageAreaHookResult )
+               );
+
+               if ( !is_null( $checkImageAreaHookResult ) ) {
+                       // was set by hook, so return that value
+                       return (bool)$checkImageAreaHookResult;
+               }
+
+               $srcWidth = $file->getWidth( $params['page'] );
+               $srcHeight = $file->getHeight( $params['page'] );
+
+               if ( $srcWidth * $srcHeight > $wgMaxImageArea
+                       && !( $file->getMimeType() == 'image/jpeg'
+                               && $this->getScalerType( false, false ) == 'im' )
+               ) {
+                       # Only ImageMagick can efficiently downsize jpg images without loading
+                       # the entire file in memory
+                       return false;
+               }
+               return true;
+       }
 }
index 52e3a78..583fc5d 100644 (file)
        "thumbnail-temp-create": "Unable to create temporary thumbnail file",
        "thumbnail-dest-create": "Unable to save thumbnail to destination",
        "thumbnail_invalid_params": "Invalid thumbnail parameters",
+       "thumbnail_toobigimagearea": "File with dimensions greater than $1",
        "thumbnail_dest_directory": "Unable to create destination directory",
        "thumbnail_image-type": "Image type not supported",
        "thumbnail_gd-library": "Incomplete GD library configuration: Missing function $1",
        "size-exabytes": "$1 EB",
        "size-zetabytes": "$1 ZB",
        "size-yottabytes": "$1 YB",
+       "size-pixel": "$1 P",
+       "size-kilopixel": "$1 KP",
+       "size-megapixel": "$1 MP",
+       "size-gigapixel": "$1 GP",
+       "size-terapixel": "$1 TP",
+       "size-petapixel": "$1 PP",
+       "size-exapixel": "$1 EP",
+       "size-zetapixel": "$1 ZP",
+       "size-yottapixel": "$1 YP",
        "bitrate-bits": "$1 bps",
        "bitrate-kilobits": "$1 kbps",
        "bitrate-megabits": "$1 Mbps",
index 2082104..813064d 100644 (file)
        "thumbnail-temp-create": "Used as thumbnail error message.\n\nSee also:\n* {{msg-mw|Thumbnail-dest-create}}\n* {{msg-mw|Thumbnail invalid params}}\n* {{msg-mw|Thumbnail dest directory}}",
        "thumbnail-dest-create": "Used as thumbnail error message.\n\nSee also:\n* {{msg-mw|Thumbnail error}}\n* {{msg-mw|Thumbnail-temp-create}}\n* {{msg-mw|Thumbnail invalid params}}\n* {{msg-mw|Thumbnail dest directory}}",
        "thumbnail_invalid_params": "Used as thumbnail error message.\n\nSee also:\n* {{msg-mw|Thumbnail-temp-create}}\n* {{msg-mw|Thumbnail-dest-create}}\n* {{msg-mw|Thumbnail dest directory}}",
+       "thumbnail_toobigimagearea": "Used as thumbnail error message.\n\n* $1 - Size in pixel (see {{msg-mw|size-megapixel}} and friends)",
        "thumbnail_dest_directory": "Used as thumbnail error message.\n\nSee also:\n* {{msg-mw|Thumbnail error}}\n* {{msg-mw|Thumbnail-temp-create}}\n* {{msg-mw|Thumbnail-dest-create}}\n* {{msg-mw|Thumbnail invalid params}}",
        "thumbnail_image-type": "This is the parameter 1 of the message {{msg-mw|thumbnail error}}",
        "thumbnail_gd-library": "This is the parameter 1 of the message {{msg-mw|thumbnail error}}.\n*$1 is a function name of the GD library",
        "size-exabytes": "{{optional}}\nSize (of a file, typically) in exbibytes (1 exbibytes = 1024×1024×1024×1024×1024×1024 bytes).",
        "size-zetabytes": "{{optional}}\nSize (of a file, typically) in zebibytes (1 zebibytes = 1024×1024×1024×1024×1024×1024×1024 bytes).",
        "size-yottabytes": "{{optional}}\nSize (of a file, typically) in yobibytes (1 yobibytes = 1024×1024×1024×1024×1024×1024×1024×1024 bytes).",
+       "size-pixel": "{{optional}}\nSize (of a file, typically) in pixel.",
+       "size-kilopixel": "{{optional}}\nSize (of a file, typically) in kilopixel (1 kilopixel = 1000 pixel).",
+       "size-megapixel": "{{optional}}\nSize (of a file, typically) in megapixel (1 megapixel = 1000×1000 pixel).",
+       "size-gigapixel": "{{optional}}\nSize (of a file, typically) in gigapixel (1 gigapixel = 1000×1000×1000 pixel).",
+       "size-terapixel": "{{optional}}\nSize (of a file, typically) in terapixel (1 terapixel = 1000×1000×1000×1000 pixel).",
+       "size-petapixel": "{{optional}}\nSize (of a file, typically) in petapixel (1 petapixel = 1000×1000×1000×1000×1000 pixel).",
+       "size-exapixel": "{{optional}}\nSize (of a file, typically) in exapixel (1 exapixel = 1000×1000×1000×1000×1000×1000 pixel).",
+       "size-zetapixel": "{{optional}}\nSize (of a file, typically) in zetapixel (1 zetapixel = 1000×1000×1000×1000×1000×1000×1000 pixel).",
+       "size-yottapixel": "{{optional}}\nSize (of a file, typically) in yottapixel (1 yottapixel = 1000×1000×1000×1000×1000×1000×1000×1000 pixel).",
        "bitrate-bits": "{{optional}}\nBitrate (of a file, typically) in bits.",
        "bitrate-kilobits": "{{optional}}\nBitrate (of a file, typically) in kilobits (1 kilobit = 1000 bits).",
        "bitrate-megabits": "{{optional}}\nBitrate (of a file, typically) in megabits (1 megabits = 1000×1000 bits).",
index 1972c96..e4415ec 100644 (file)
@@ -113,7 +113,7 @@ class BitmapScalingTest extends MediaWikiTestCase {
                $file = new FakeDimensionFile( array( 4000, 4000 ) );
                $handler = new BitmapHandler;
                $params = array( 'width' => '3700' ); // Still bigger than max size.
-               $this->assertEquals( 'TransformParameterError',
+               $this->assertEquals( 'TransformTooBigImageAreaError',
                        get_class( $handler->doTransform( $file, 'dummy path', '', $params ) ) );
        }
 
@@ -125,7 +125,7 @@ class BitmapScalingTest extends MediaWikiTestCase {
                $file->mustRender = true;
                $handler = new BitmapHandler;
                $params = array( 'width' => '5000' ); // Still bigger than max size.
-               $this->assertEquals( 'TransformParameterError',
+               $this->assertEquals( 'TransformTooBigImageAreaError',
                        get_class( $handler->doTransform( $file, 'dummy path', '', $params ) ) );
        }