Index: branches/wmf/1.18wmf1/docs/hooks.txt |
— | — | @@ -595,6 +595,11 @@ |
596 | 596 | &$scalerParams: Array with scaler parameters |
597 | 597 | &$mto: null, set to a MediaTransformOutput |
598 | 598 | |
| 599 | +'BitmapHandlerCheckImageArea': by BitmapHandler::normaliseParams, after all normalizations have been performed, except for the $wgMaxImageArea check |
| 600 | +$image: File |
| 601 | +&$params: Array of parameters |
| 602 | +&$checkImageAreaHookResult: null, set to true or false to override the $wgMaxImageArea check result |
| 603 | + |
599 | 604 | 'PerformRetroactiveAutoblock': called before a retroactive autoblock is applied to a user |
600 | 605 | $block: Block object (which is set to be autoblocking) |
601 | 606 | &$blockIds: Array of block IDs of the autoblock |
Index: branches/wmf/1.18wmf1/tests/phpunit/includes/media/BitmapScalingTest.php |
— | — | @@ -3,13 +3,16 @@ |
4 | 4 | class BitmapScalingTest extends MediaWikiTestCase { |
5 | 5 | |
6 | 6 | function setUp() { |
7 | | - global $wgMaxImageArea; |
| 7 | + global $wgMaxImageArea, $wgCustomConvertCommand; |
8 | 8 | $this->oldMaxImageArea = $wgMaxImageArea; |
| 9 | + $this->oldCustomConvertCommand = $wgCustomConvertCommand; |
9 | 10 | $wgMaxImageArea = 1.25e7; // 3500x3500 |
| 11 | + $wgCustomConvertCommand = 'dummy'; // Set so that we don't get client side rendering |
10 | 12 | } |
11 | 13 | function tearDown() { |
12 | | - global $wgMaxImageArea; |
| 14 | + global $wgMaxImageArea, $wgCustomConvertCommand; |
13 | 15 | $wgMaxImageArea = $this->oldMaxImageArea; |
| 16 | + $wgCustomConvertCommand = $this->oldCustomConvertCommand; |
14 | 17 | } |
15 | 18 | /** |
16 | 19 | * @dataProvider provideNormaliseParams |
— | — | @@ -105,22 +108,31 @@ |
106 | 109 | $file = new FakeDimensionFile( array( 4000, 4000 ) ); |
107 | 110 | $handler = new BitmapHandler; |
108 | 111 | $params = array( 'width' => '3700' ); // Still bigger than max size. |
109 | | - $this->assertFalse( $handler->normaliseParams( $file, $params ) ); |
| 112 | + $this->assertEquals( 'TransformParameterError', |
| 113 | + get_class( $handler->doTransform( $file, 'dummy path', '', $params ) ) ); |
110 | 114 | } |
111 | 115 | function testTooBigMustRenderImage() { |
112 | 116 | $file = new FakeDimensionFile( array( 4000, 4000 ) ); |
113 | 117 | $file->mustRender = true; |
114 | 118 | $handler = new BitmapHandler; |
115 | 119 | $params = array( 'width' => '5000' ); // Still bigger than max size. |
116 | | - $this->assertFalse( $handler->normaliseParams( $file, $params ) ); |
| 120 | + $this->assertEquals( 'TransformParameterError', |
| 121 | + get_class( $handler->doTransform( $file, 'dummy path', '', $params ) ) ); |
117 | 122 | } |
| 123 | + |
| 124 | + function testImageArea() { |
| 125 | + $file = new FakeDimensionFile( array( 7, 9 ) ); |
| 126 | + $handler = new BitmapHandler; |
| 127 | + $this->assertEquals( 63, $handler->getImageArea( $file ) ); |
| 128 | + } |
118 | 129 | } |
119 | 130 | |
120 | 131 | class FakeDimensionFile extends File { |
121 | 132 | public $mustRender = false; |
122 | 133 | |
123 | 134 | public function __construct( $dimensions ) { |
124 | | - parent::__construct( Title::makeTitle( NS_FILE, 'Test' ), null ); |
| 135 | + parent::__construct( Title::makeTitle( NS_FILE, 'Test' ), |
| 136 | + new NullRepo( null ) ); |
125 | 137 | |
126 | 138 | $this->dimensions = $dimensions; |
127 | 139 | } |
— | — | @@ -133,4 +145,7 @@ |
134 | 146 | public function mustRender() { |
135 | 147 | return $this->mustRender; |
136 | 148 | } |
| 149 | + public function getPath() { |
| 150 | + return ''; |
| 151 | + } |
137 | 152 | } |
Index: branches/wmf/1.18wmf1/includes/media/Bitmap.php |
— | — | @@ -21,12 +21,10 @@ |
22 | 22 | * @return bool |
23 | 23 | */ |
24 | 24 | function normaliseParams( $image, &$params ) { |
25 | | - global $wgMaxImageArea; |
26 | 25 | if ( !parent::normaliseParams( $image, $params ) ) { |
27 | 26 | return false; |
28 | 27 | } |
29 | 28 | |
30 | | - $mimeType = $image->getMimeType(); |
31 | 29 | # Obtain the source, pre-rotation dimensions |
32 | 30 | $srcWidth = $image->getWidth( $params['page'] ); |
33 | 31 | $srcHeight = $image->getHeight( $params['page'] ); |
— | — | @@ -42,15 +40,22 @@ |
43 | 41 | return true; |
44 | 42 | } |
45 | 43 | } |
46 | | - |
47 | | - # Don't thumbnail an image so big that it will fill hard drives and send servers into swap |
48 | | - # JPEG has the handy property of allowing thumbnailing without full decompression, so we make |
49 | | - # an exception for it. |
50 | | - # @todo FIXME: This actually only applies to ImageMagick |
51 | | - if ( $mimeType !== 'image/jpeg' && |
52 | | - $srcWidth * $srcHeight > $wgMaxImageArea ) |
53 | | - { |
54 | | - return false; |
| 44 | + |
| 45 | + # Check if the file is smaller than the maximum image area for thumbnailing |
| 46 | + $checkImageAreaHookResult = null; |
| 47 | + wfRunHooks( 'BitmapHandlerCheckImageArea', array( $image, &$params, &$checkImageAreaHookResult ) ); |
| 48 | + if ( is_null( $checkImageAreaHookResult ) ) { |
| 49 | + global $wgMaxImageArea; |
| 50 | + |
| 51 | + if ( $srcWidth * $srcHeight > $wgMaxImageArea && |
| 52 | + !( $image->getMimeType() == 'image/jpeg' && |
| 53 | + self::getScalerType( false, false ) == 'im' ) ) { |
| 54 | + # Only ImageMagick can efficiently downsize jpg images without loading |
| 55 | + # the entire file in memory |
| 56 | + return false; |
| 57 | + } |
| 58 | + } else { |
| 59 | + return $checkImageAreaHookResult; |
55 | 60 | } |
56 | 61 | |
57 | 62 | return true; |
Index: branches/wmf/1.18wmf1/includes/AutoLoader.php |
— | — | @@ -458,6 +458,7 @@ |
459 | 459 | 'LocalFileMoveBatch' => 'includes/filerepo/LocalFile.php', |
460 | 460 | 'LocalFileRestoreBatch' => 'includes/filerepo/LocalFile.php', |
461 | 461 | 'LocalRepo' => 'includes/filerepo/LocalRepo.php', |
| 462 | + 'NullRepo' => 'includes/filerepo/NullRepo.php', |
462 | 463 | 'OldLocalFile' => 'includes/filerepo/OldLocalFile.php', |
463 | 464 | 'RepoGroup' => 'includes/filerepo/RepoGroup.php', |
464 | 465 | 'UnregisteredLocalFile' => 'includes/filerepo/UnregisteredLocalFile.php', |