Merge pull request #3524 from marc1706/ticket/8672

[ticket/8672] Add class for retrieving imagesize without download
This commit is contained in:
Tristan Darricau 2015-04-27 16:26:40 +02:00
commit 734b89e75c
24 changed files with 221 additions and 58 deletions

View file

@ -26,6 +26,7 @@
},
"require": {
"lusitanian/oauth": "0.2.*",
"marc1706/fast-image-size": "1.0.*",
"patchwork/utf8": "1.1.*",
"php": ">=5.3.9",
"s9e/text-formatter": "dev-release/php5.3",

53
phpBB/composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "91cc998d47b703a7bc4f726217d7a3a9",
"hash": "d5368b75d221b5573b30307cb2f25f3b",
"packages": [
{
"name": "lusitanian/oauth",
@ -69,6 +69,57 @@
],
"time": "2013-08-29 21:40:04"
},
{
"name": "marc1706/fast-image-size",
"version": "v1.0.2",
"source": {
"type": "git",
"url": "https://github.com/marc1706/fast-image-size.git",
"reference": "ab7b594325cdf6b374d50b3934c8d16dd5249a2a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/marc1706/fast-image-size/zipball/ab7b594325cdf6b374d50b3934c8d16dd5249a2a",
"reference": "ab7b594325cdf6b374d50b3934c8d16dd5249a2a",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "4.*"
},
"type": "library",
"autoload": {
"psr-4": {
"fastImageSize\\": "lib",
"fastImageSize\\tests\\": "tests"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marc Alexander",
"email": "admin@m-a-styles.de",
"homepage": "https://www.m-a-styles.de",
"role": "Developer"
}
],
"description": "fast-image-size is a PHP library that does almost everything PHP's getimagesize() does but without the large overhead of downloading the complete file.",
"homepage": "https://www.m-a-styles.de",
"keywords": [
"fast",
"getimagesize",
"image",
"imagesize",
"php",
"size"
],
"time": "2015-04-09 11:19:59"
},
{
"name": "patchwork/utf8",
"version": "v1.1.26",

View file

@ -202,6 +202,9 @@ services:
template_context:
class: phpbb\template\context
upload_imagesize:
class: fastImageSize\fastImageSize
version_helper:
class: phpbb\version_helper
scope: prototype

View file

@ -17,6 +17,7 @@ services:
class: phpbb\avatar\driver\gravatar
arguments:
- @config
- @upload_imagesize
- %core.root_path%
- %core.php_ext%
- @path_helper
@ -30,6 +31,7 @@ services:
class: phpbb\avatar\driver\local
arguments:
- @config
- @upload_imagesize
- %core.root_path%
- %core.php_ext%
- @path_helper
@ -43,6 +45,7 @@ services:
class: phpbb\avatar\driver\remote
arguments:
- @config
- @upload_imagesize
- %core.root_path%
- %core.php_ext%
- @path_helper

View file

@ -402,28 +402,28 @@ class filespec
{
$this->width = $this->height = 0;
if (($this->image_info = @getimagesize($this->destination_file)) !== false)
{
$this->width = $this->image_info[0];
$this->height = $this->image_info[1];
// Get imagesize class
$imagesize = new \fastImageSize\fastImageSize();
if (!empty($this->image_info['mime']))
$this->image_info = $imagesize->getImageSize($this->destination_file, $this->mimetype);
if ($this->image_info !== false)
{
$this->mimetype = $this->image_info['mime'];
}
$this->width = $this->image_info['width'];
$this->height = $this->image_info['height'];
// Check image type
$types = fileupload::image_types();
if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]]))
if (!isset($types[$this->image_info['type']]) || !in_array($this->extension, $types[$this->image_info['type']]))
{
if (!isset($types[$this->image_info[2]]))
if (!isset($types[$this->image_info['type']]))
{
$this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype);
$this->error[] = $user->lang('IMAGE_FILETYPE_INVALID', $this->image_info['type'], $this->mimetype);
}
else
{
$this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info[2]][0], $this->extension);
$this->error[] = $user->lang('IMAGE_FILETYPE_MISMATCH', $types[$this->image_info['type']][0], $this->extension);
}
}

View file

@ -339,22 +339,23 @@ class bbcode_firstpass extends bbcode
if ($config['max_' . $this->mode . '_img_height'] || $config['max_' . $this->mode . '_img_width'])
{
$stats = @getimagesize(htmlspecialchars_decode($in));
$imagesize = new \fastImageSize\fastImageSize();
$size_info = $imagesize->getImageSize(htmlspecialchars_decode($in));
if ($stats === false)
if ($size_info === false)
{
$error = true;
$this->warn_msg[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
}
else
{
if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $stats[1])
if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $size_info['height'])
{
$error = true;
$this->warn_msg[] = $user->lang('MAX_IMG_HEIGHT_EXCEEDED', (int) $config['max_' . $this->mode . '_img_height']);
}
if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $stats[0])
if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $size_info['width'])
{
$error = true;
$this->warn_msg[] = $user->lang('MAX_IMG_WIDTH_EXCEEDED', (int) $config['max_' . $this->mode . '_img_width']);

View file

@ -30,6 +30,9 @@ abstract class driver implements \phpbb\avatar\driver\driver_interface
*/
protected $config;
/** @var \fastImageSize\fastImageSize */
protected $imagesize;
/**
* Current $phpbb_root_path
* @var string
@ -73,14 +76,16 @@ abstract class driver implements \phpbb\avatar\driver\driver_interface
* Construct a driver object
*
* @param \phpbb\config\config $config phpBB configuration
* @param \fastImageSize\fastImageSize $imagesize fastImageSize class
* @param string $phpbb_root_path Path to the phpBB root
* @param string $php_ext PHP file extension
* @param \phpbb\path_helper $path_helper phpBB path helper
* @param \phpbb\cache\driver\driver_interface $cache Cache driver
*/
public function __construct(\phpbb\config\config $config, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\cache\driver\driver_interface $cache = null)
public function __construct(\phpbb\config\config $config, \fastImageSize\fastImageSize $imagesize, $phpbb_root_path, $php_ext, \phpbb\path_helper $path_helper, \phpbb\cache\driver\driver_interface $cache = null)
{
$this->config = $config;
$this->imagesize = $imagesize;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->path_helper = $path_helper;

View file

@ -98,8 +98,8 @@ class gravatar extends \phpbb\avatar\driver\driver
return false;
}
// Make sure getimagesize works...
if (function_exists('getimagesize') && ($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0))
// Get image dimensions if they are not set
if ($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0)
{
/**
* default to the minimum of the maximum allowed avatar size if the size
@ -108,20 +108,20 @@ class gravatar extends \phpbb\avatar\driver\driver
$row['avatar_width'] = $row['avatar_height'] = min($this->config['avatar_max_width'], $this->config['avatar_max_height']);
$url = $this->get_gravatar_url($row);
if (($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0) && (($image_data = getimagesize($url)) === false))
if (($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0) && (($image_data = $this->imagesize->getImageSize($url)) === false))
{
$error[] = 'UNABLE_GET_IMAGE_SIZE';
return false;
}
if (!empty($image_data) && ($image_data[0] <= 0 || $image_data[1] <= 0))
if (!empty($image_data) && ($image_data['width'] <= 0 || $image_data['width'] <= 0))
{
$error[] = 'AVATAR_NO_SIZE';
return false;
}
$row['avatar_width'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_width'] : $image_data[0];
$row['avatar_height'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_height'] : $image_data[1];
$row['avatar_width'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_width'] : $image_data['width'];
$row['avatar_height'] = ($row['avatar_width'] && $row['avatar_height']) ? $row['avatar_height'] : $image_data['height'];
}
if ($row['avatar_width'] <= 0 || $row['avatar_height'] <= 0)

View file

@ -172,13 +172,15 @@ class local extends \phpbb\avatar\driver\driver
// Match all images in the gallery folder
if (preg_match('#^[^&\'"<>]+\.(?:' . implode('|', $this->allowed_extensions) . ')$#i', $image) && is_file($file_path . '/' . $image))
{
if (function_exists('getimagesize'))
$dims = $this->imagesize->getImageSize($file_path . '/' . $image);
if ($dims === false)
{
$dims = getimagesize($file_path . '/' . $image);
$dims = array(0, 0);
}
else
{
$dims = array(0, 0);
$dims = array($dims['width'], $dims['height']);
}
$cat = ($path == $file_path) ? $user->lang['NO_AVATAR_CATEGORY'] : str_replace("$path/", '', $file_path);
$avatar_list[$cat][$image] = array(

View file

@ -92,24 +92,21 @@ class remote extends \phpbb\avatar\driver\driver
return false;
}
// Make sure getimagesize works...
if (function_exists('getimagesize'))
{
if (($width <= 0 || $height <= 0) && (($image_data = @getimagesize($url)) === false))
// Get image dimensions
if (($width <= 0 || $height <= 0) && (($image_data = $this->imagesize->getImageSize($url)) === false))
{
$error[] = 'UNABLE_GET_IMAGE_SIZE';
return false;
}
if (!empty($image_data) && ($image_data[0] <= 0 || $image_data[1] <= 0))
if (!empty($image_data) && ($image_data['width'] <= 0 || $image_data['height'] <= 0))
{
$error[] = 'AVATAR_NO_SIZE';
return false;
}
$width = ($width && $height) ? $width : $image_data[0];
$height = ($width && $height) ? $height : $image_data[1];
}
$width = ($width && $height) ? $width : $image_data['width'];
$height = ($width && $height) ? $height : $image_data['height'];
if ($width <= 0 || $height <= 0)
{
@ -172,15 +169,15 @@ class remote extends \phpbb\avatar\driver\driver
return false;
}
if (!empty($image_data) && (!isset($types[$image_data[2]]) || !in_array($extension, $types[$image_data[2]])))
if (!empty($image_data) && (!isset($types[$image_data['type']]) || !in_array($extension, $types[$image_data['type']])))
{
if (!isset($types[$image_data[2]]))
if (!isset($types[$image_data['type']]))
{
$error[] = 'UNABLE_GET_IMAGE_SIZE';
}
else
{
$error[] = array('IMAGE_FILETYPE_MISMATCH', $types[$image_data[2]][0], $extension);
$error[] = array('IMAGE_FILETYPE_MISMATCH', $types[$image_data['type']][0], $extension);
}
return false;

View file

@ -367,7 +367,6 @@ class parser implements \phpbb\textformatter\parser_interface
{
// Validate the URL
$url = BuiltInFilters::filterUrl($url, $url_config, $logger);
if ($url === false)
{
return false;
@ -375,26 +374,23 @@ class parser implements \phpbb\textformatter\parser_interface
if ($max_height || $max_width)
{
$stats = @getimagesize($url);
if ($stats === false)
$imagesize = new \fastImageSize\fastImageSize();
$size_info = $imagesize->getImageSize($url);
if ($size_info === false)
{
$logger->err('UNABLE_GET_IMAGE_SIZE');
return false;
}
if ($max_height && $max_height < $stats[1])
if ($max_height && $max_height < $size_info['height'])
{
$logger->err('MAX_IMG_HEIGHT_EXCEEDED', array('max_height' => $max_height));
return false;
}
if ($max_width && $max_width < $stats[0])
if ($max_width && $max_width < $size_info['width'])
{
$logger->err('MAX_IMG_WIDTH_EXCEEDED', array('max_width' => $max_width));
return false;
}
}

View file

@ -57,9 +57,10 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
new \phpbb\mimetype\content_guesser,
);
$guesser = new \phpbb\mimetype\guesser($guessers);
$imagesize = new \fastImageSize\fastImageSize();
// $this->avatar_foobar will be needed later on
$this->avatar_foobar = $this->getMock('\phpbb\avatar\driver\foobar', array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $cache));
$this->avatar_foobar = $this->getMock('\phpbb\avatar\driver\foobar', array('get_name'), array($this->config, $imagesize, $phpbb_root_path, $phpEx, $path_helper, $cache));
$this->avatar_foobar->expects($this->any())
->method('get_name')
->will($this->returnValue('avatar.driver.foobar'));
@ -74,7 +75,7 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case
{
if ($driver !== 'upload')
{
$cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $phpbb_root_path, $phpEx, $path_helper, $cache));
$cur_avatar = $this->getMock('\phpbb\avatar\driver\\' . $driver, array('get_name'), array($this->config, $imagesize, $phpbb_root_path, $phpEx, $path_helper, $cache));
}
else
{

View file

@ -458,6 +458,10 @@ class phpbb_test_case_helpers
{
$dispatcher = new phpbb_mock_event_dispatcher;
}
if (!isset($phpbb_dispatcher))
{
$phpbb_dispatcher = $dispatcher;
}
// Create and register the text_formatter.s9e.factory service
$factory = new \phpbb\textformatter\s9e\factory($dal, $cache, $dispatcher, $cache_dir, $cache_key_parser, $cache_key_renderer);

View file

@ -289,7 +289,7 @@ class phpbb_filespec_test extends phpbb_test_case
array('txt_copy', 'txt_as_img', 'image/jpg', 'txt', false, true),
array('txt_copy_2', 'txt_moved', 'text/plain', 'txt', false, true),
array('jpg_copy', 'jpg_moved', 'image/png', 'jpg', false, true),
array('png_copy', 'png_moved', 'image/png', 'jpg', 'IMAGE_FILETYPE_MISMATCH', true),
array('png_copy', 'png_moved', 'image/png', 'jpg', 'IMAGE_FILETYPE_MISMATCH png jpg', true),
);
}

BIN
tests/upload/fixture/bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 B

BIN
tests/upload/fixture/iff Normal file

Binary file not shown.

Binary file not shown.

BIN
tests/upload/fixture/jp2 Normal file

Binary file not shown.

BIN
tests/upload/fixture/jpx Normal file

Binary file not shown.

BIN
tests/upload/fixture/psd Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
tests/upload/fixture/wbmp Normal file

Binary file not shown.

View file

@ -0,0 +1,99 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
require_once(__DIR__ . '/../../phpBB/includes/functions.php');
class phpbb_upload_imagesize_test extends \phpbb_test_case
{
/** @var \fastImageSize\fastImageSize */
protected $imagesize;
/** @var string Path to fixtures */
protected $path;
public function setUp()
{
parent::setUp();
$this->imagesize = new \fastImageSize\fastImageSize();
$this->path = __DIR__ . '/fixture/';
}
public function data_get_imagesize()
{
return array(
array('foobar', 'image/bmp', false),
array('png', 'image/png', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_PNG)),
array('gif', 'image/png', false),
array('png', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_PNG)),
array('gif', 'image/gif', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_GIF)),
array('jpg', 'image/gif', false),
array('gif', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_GIF)),
array('jpg', 'image/jpg', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)),
array('jpg', 'image/jpeg', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)),
array('png', 'image/jpg', false),
array('jpg', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_JPEG)),
array('psd', 'image/psd', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)),
array('psd', 'image/photoshop', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)),
array('jpg', 'image/psd', false),
array('psd', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_PSD)),
array('bmp', 'image/bmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_BMP)),
array('png', 'image/bmp', false),
array('bmp', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_BMP)),
array('tif', 'image/tif', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)),
array('png', 'image/tif', false),
array('tif', '', array('width' => 1, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)),
array('tif_compressed', 'image/tif', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)),
array('png', 'image/tiff', false),
array('tif_compressed', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_II)),
array('tif_msb', 'image/tif', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_MM)),
array('tif_msb', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_TIFF_MM)),
array('wbmp', 'image/wbmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)),
array('wbmp', 'image/vnd.wap.wbmp', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)),
array('png', 'image/vnd.wap.wbmp', false),
array('wbmp', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_WBMP)),
array('iff', 'image/iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)),
array('iff', 'image/x-iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)),
array('iff_maya', 'iamge/iff', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)),
array('png', 'image/iff', false),
array('png', 'image/x-iff', false),
array('iff', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)),
array('iff_maya', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_IFF)),
array('jp2', 'image/jp2', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
array('jp2', 'image/jpx', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
array('jp2', 'image/jpm', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
array('jpg', 'image/jp2', false),
array('jpx', 'image/jpx', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
array('jp2', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
array('jpx', '', array('width' => 2, 'height' => 1, 'type' => IMAGETYPE_JPEG2000)),
);
}
/**
* @dataProvider data_get_imagesize
*/
public function test_get_imagesize($file, $mime_type, $expected)
{
$this->assertEquals($expected, $this->imagesize->getImageSize($this->path . $file, $mime_type));
}
public function test_get_imagesize_remote()
{
$this->assertSame(array(
'width' => 80,
'height' => 80,
'type' => IMAGETYPE_JPEG,
),
$this->imagesize->getImageSize('https://secure.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0.jpg'));
}
}