Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Validator] Support "maxSize" given in KiB #11027

Closed
wants to merge 3 commits into from
Closed
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

Prev

Add option binaryFormat in constraint File

  • Loading branch information...
jderusse committed Jun 1, 2014
commit 7bff160f4a7ffdb1cd1cd66721b60501be55260e
@@ -24,11 +24,8 @@
*/
class File extends Constraint
{
const SIZE_FORMAT_BINARY = 2;
const SIZE_FORMAT_DECIMAL = 10;
public $maxSize = null;
public $maxSizeFormat = self::SIZE_FORMAT_BINARY;
public $binaryFormat = null;
public $mimeTypes = array();
public $notFoundMessage = 'The file could not be found.';
public $notReadableMessage = 'The file is not readable.';
@@ -46,31 +43,24 @@ class File extends Constraint
public function __construct($options = null)
{
if (is_array($options) && array_key_exists('maxSizeFormat', $options)) {
throw new ConstraintDefinitionException(sprintf(
'The option "maxSizeFormat" is not supported by the constraint %s',
__CLASS__
));
}
parent::__construct($options);
if ($this->maxSize) {
if (ctype_digit((string) $this->maxSize)) {
$this->maxSize = (int) $this->maxSize;
$this->maxSizeFormat = self::SIZE_FORMAT_DECIMAL;
$this->binaryFormat = $this->binaryFormat === null ? false : $this->binaryFormat;
} elseif (preg_match('/^\d++k$/i', $this->maxSize)) {
$this->maxSize = $this->maxSize * 1000;
$this->maxSizeFormat = self::SIZE_FORMAT_DECIMAL;
$this->binaryFormat = $this->binaryFormat === null ? false : $this->binaryFormat;
} elseif (preg_match('/^\d++M$/i', $this->maxSize)) {
$this->maxSize = $this->maxSize * 1000000;
$this->maxSizeFormat = self::SIZE_FORMAT_DECIMAL;
$this->binaryFormat = $this->binaryFormat === null ? false : $this->binaryFormat;
} elseif (preg_match('/^\d++ki$/i', $this->maxSize)) {
$this->maxSize = $this->maxSize << 10;
$this->maxSizeFormat = self::SIZE_FORMAT_BINARY;
$this->binaryFormat = $this->binaryFormat === null ? true : $this->binaryFormat;
} elseif (preg_match('/^\d++Mi$/i', $this->maxSize)) {
$this->maxSize = $this->maxSize << 20;
$this->maxSizeFormat = self::SIZE_FORMAT_BINARY;
$this->binaryFormat = $this->binaryFormat === null ? true : $this->binaryFormat;
} else {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $this->maxSize));
}
@@ -15,7 +15,6 @@
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\ConstraintDefinitionException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
/**
@@ -55,10 +54,6 @@ public function validate($value, Constraint $constraint)
switch ($value->getError()) {
case UPLOAD_ERR_INI_SIZE:
if ($constraint->maxSize) {
if (!ctype_digit((string) $constraint->maxSize)) {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize));
}
$limitInBytes = min(UploadedFile::getMaxFilesize(), (int) $constraint->maxSize);
} else {
$limitInBytes = UploadedFile::getMaxFilesize();
@@ -123,19 +118,15 @@ public function validate($value, Constraint $constraint)
$sizeInBytes = filesize($path);
$limitInBytes = (int) $constraint->maxSize;
if (!ctype_digit((string) $constraint->maxSize)) {
throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum size', $constraint->maxSize));
}
if ($sizeInBytes > $limitInBytes) {
// Convert the limit to the smallest possible number
// (i.e. try "MB", then "kB", then "bytes")
if (File::SIZE_FORMAT_DECIMAL === $constraint->maxSizeFormat) {
$coef = self::MB_BYTES;
$coefFactor = self::KB_BYTES;
} else {
if ($constraint->binaryFormat) {
$coef = self::MIB_BYTES;
$coefFactor = self::KIB_BYTES;
} else {
$coef = self::MB_BYTES;
$coefFactor = self::KB_BYTES;
}
$limitAsString = (string) ($limitInBytes / $coef);
@@ -18,19 +18,21 @@ class FileTest extends \PHPUnit_Framework_TestCase
/**
* @param mixed $maxSize
* @param mixed $bytes
* @param int bytes
* @param bool $bytes
* @dataProvider provideValidSizes
*/
public function testMaxSize($maxSize, $bytes)
public function testMaxSize($maxSize, $bytes, $binaryFormat)
{
$file = new File(array('maxSize' => $maxSize));
$this->assertSame($bytes, $file->maxSize);
$this->assertSame($binaryFormat, $file->binaryFormat);
}
/**
* @param mixed $maxSize
* @param mixed $bytes
* @param int $bytes
* @dataProvider provideInValidSizes
* @expectedException Symfony\Component\Validator\Exception\ConstraintDefinitionException
*/
@@ -45,16 +47,16 @@ public function testInvalideMaxSize($maxSize)
public function provideValidSizes()
{
return array(
array('500', 500),
array(12300, 12300),
array('1ki', 1024),
array('1KI', 1024),
array('2k', 2000),
array('2K', 2000),
array('1mi', 1048576),
array('1MI', 1048576),
array('3m', 3000000),
array('3M', 3000000),
array('500', 500, false),
array(12300, 12300, false),
array('1ki', 1024, true),
array('1KI', 1024, true),
array('2k', 2000, false),
array('2K', 2000, false),
array('1mi', 1048576, true),
array('1MI', 1048576, true),
array('3m', 3000000, false),
array('3M', 3000000, false),
);
}
@@ -72,4 +74,35 @@ public function provideInvalidSizes()
array('1Gi'),
);
}
/**
* @param mixed $maxSize
* @param bool $guessedFormat
* @param bool $binaryFormat
* @dataProvider provideFormats
*/
public function testBinaryFormat($maxSize, $guessedFormat, $binaryFormat)
{
$file = new File(array('maxSize' => $maxSize, 'binaryFormat' => $guessedFormat));
$this->assertSame($binaryFormat, $file->binaryFormat);
}
/**
* @return array
*/
public function provideFormats()
{
return array(
array(100, null, false),
array(100, true, true),
array(100, false, false),
array('100K', null, false),
array('100K', true, true),
array('100K', false, false),
array('100Ki', null, true),
array('100Ki', true, true),
array('100Ki', false, false),
);
}
}
@@ -99,35 +99,35 @@ public function provideMaxSizeExceededTests()
// round(size) == 1.01kB, limit == 1kB
array(ceil(1.005*1000), 1000, '1.01', '1', 'kB'),
array(ceil(1.005*1000), '1k', '1.01', '1', 'kB'),
array(ceil(1.005*1024), '1ki', '1.01', '1', 'KiB'),
array(ceil(1.005*1024), '1Ki', '1.01', '1', 'KiB'),
// round(size) == 1kB, limit == 1kB -> use bytes
array(ceil(1.004*1000), 1000, '1004', '1000', 'bytes'),
array(ceil(1.004*1000), '1k', '1004', '1000', 'bytes'),
array(ceil(1.004*1024), '1ki', '1029', '1024', 'bytes'),
array(ceil(1.004*1024), '1Ki', '1029', '1024', 'bytes'),
array(1000 + 1, 1000, '1001', '1000', 'bytes'),
array(1000 + 1, '1k', '1001', '1000', 'bytes'),
array(1024 + 1, '1ki', '1025', '1024', 'bytes'),
array(1024 + 1, '1Ki', '1025', '1024', 'bytes'),
// round(size) == 1.01MB, limit == 1MB
array(ceil(1.005*1000*1000), 1000*1000, '1.01', '1', 'MB'),
array(ceil(1.005*1000*1000), '1000k', '1.01', '1', 'MB'),
array(ceil(1.005*1000*1000), '1M', '1.01', '1', 'MB'),
array(ceil(1.005*1024*1024), '1024ki', '1.01', '1', 'MiB'),
array(ceil(1.005*1024*1024), '1024Ki', '1.01', '1', 'MiB'),
array(ceil(1.005*1024*1024), '1Mi', '1.01', '1', 'MiB'),
// round(size) == 1MB, limit == 1MB -> use kB
array(ceil(1.004*1000*1000), 1000*1000, '1004', '1000', 'kB'),
array(ceil(1.004*1000*1000), '1000k', '1004', '1000', 'kB'),
array(ceil(1.004*1000*1000), '1M', '1004', '1000', 'kB'),
array(ceil(1.004*1024*1024), '1024ki', '1028.1', '1024', 'KiB'),
array(ceil(1.004*1024*1024), '1024Ki', '1028.1', '1024', 'KiB'),
array(ceil(1.004*1024*1024), '1Mi', '1028.1', '1024', 'KiB'),
array(1000*1000 + 1, 1000*1000, '1000001', '1000000', 'bytes'),
array(1000*1000 + 1, '1000k', '1000001', '1000000', 'bytes'),
array(1000*1000 + 1, '1M', '1000001', '1000000', 'bytes'),
array(1024*1024 + 1, '1024ki', '1048577', '1048576', 'bytes'),
array(1024*1024 + 1, '1024Ki', '1048577', '1048576', 'bytes'),
array(1024*1024 + 1, '1Mi', '1048577', '1048576', 'bytes'),
);
}
@@ -166,9 +166,13 @@ public function provideMaxSizeNotExceededTests()
array(1000, '1k'),
array(1000 - 1, '1k'),
array(1024, '1Ki'),
array(1024 - 1, '1Ki'),
array(1000*1000, '1M'),
array(1000*1000 - 1, '1M'),
array(1024*1024, '1Mi'),
array(1024*1024 - 1, '1Mi'),
);
}
@@ -204,6 +208,55 @@ public function testInvalidMaxSize()
$this->validator->validate($this->path, $constraint);
}
public function provideBinaryFormatTests()
{
return array(
array(11, 10, null, '11', '10', 'bytes'),
array(11, 10, true, '11', '10', 'bytes'),
array(11, 10, false, '11', '10', 'bytes'),
// round(size) == 1.01kB, limit == 1kB
array(ceil(1000*1.01), 1000, null, '1.01', '1', 'kB'),
array(ceil(1000*1.01), '1k', null, '1.01', '1', 'kB'),
array(ceil(1024*1.01), '1Ki', null, '1.01', '1', 'KiB'),
array(ceil(1024*1.01), 1024, true, '1.01', '1', 'KiB'),
array(ceil(1024*1.01*1000), '1024k', true, '1010', '1000', 'KiB'),
array(ceil(1024*1.01), '1Ki', true, '1.01', '1', 'KiB'),
array(ceil(1000*1.01), 1000, false, '1.01', '1', 'kB'),
array(ceil(1000*1.01), '1k', false, '1.01', '1', 'kB'),
array(ceil(1024*1.01*10), '10Ki', false, '10.34', '10.24', 'kB'),
);
}
/**
* @dataProvider provideBinaryFormatTests
*/
public function testBinaryFormat($bytesWritten, $limit, $binaryFormat, $sizeAsString, $limitAsString, $suffix)
{
fseek($this->file, $bytesWritten-1, SEEK_SET);
fwrite($this->file, '0');
fclose($this->file);
$constraint = new File(array(
'maxSize' => $limit,
'binaryFormat' => $binaryFormat,
'maxSizeMessage' => 'myMessage',
));
$this->context->expects($this->once())
->method('addViolation')
->with('myMessage', array(
'{{ limit }}' => $limitAsString,
'{{ size }}' => $sizeAsString,
'{{ suffix }}' => $suffix,
'{{ file }}' => $this->path,
));
$this->validator->validate($this->getFile($this->path), $constraint);
}
public function testValidMimeType()
{
$file = $this
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.