8000 [Form] Moved POST_MAX_SIZE validation from FormValidator to request h… · symfony/symfony@47f5fde · GitHub
[go: up one dir, main page]

Skip to content

Commit 47f5fde

Browse files
committed
[Form] Moved POST_MAX_SIZE validation from FormValidator to request handler
1 parent 15d3fc5 commit 47f5fde

File tree

11 files changed

+178
-170
lines changed

11 files changed

+178
-170
lines changed

src/Symfony/Component/Form/Extension/Core/Type/FormType.php

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -170,25 +170,26 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
170170
));
171171

172172
$resolver->setDefaults(array(
173-
'data_class' => $dataClass,
174-
'empty_data' => $emptyData,
175-
'trim' => true,
176-
'required' => true,
177-
'read_only' => false,
178-
'max_length' => null,
179-
'pattern' => null,
180-
'property_path' => null,
181-
'mapped' => true,
182-
'by_reference' => true,
183-
'error_bubbling' => $errorBubbling,
184-
'label_attr' => array(),
185-
'virtual' => null,
186-
'inherit_data' => $inheritData,
187-
'compound' => true,
188-
'method' => 'POST',
173+
'data_class' => $dataClass,
174+
'empty_data' => $emptyData,
175+
'trim' => true,
176+
'required' => true,
177+
'read_only' => false,
178+
'max_length' 9E88 => null,
179+
'pattern' => null,
180+
'property_path' => null,
181+
'mapped' => true,
182+
'by_reference' => true,
183+
'error_bubbling' => $errorBubbling,
184+
'label_attr' => array(),
185+
'virtual' => null,
186+
'inherit_data' => $inheritData,
187+
'compound' => true,
188+
'method' => 'POST',
189189
// According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt)
190190
// section 4.2., empty URIs are considered same-document references
191-
'action' => '',
191+
'action' => '',
192+
'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.',
192193
));
193194

194195
$resolver->setAllowedTypes(array(

src/Symfony/Component/Form/Extension/HttpFoundation/HttpFoundationRequestHandler.php

Lines changed: 18 additions & 5 deletions
Original file line numberDiff lin F438 e numberDiff line change
@@ -12,10 +12,10 @@
1212
namespace Symfony\Component\Form\Extension\HttpFoundation;
1313

1414
use Symfony\Component\Form\Exception\UnexpectedTypeException;
15-
use Symfony\Component\Form\Extension\Validator\Util\ServerParams;
1615
use Symfony\Component\Form\FormError;
1716
use Symfony\Component\Form\FormInterface;
1817
use Symfony\Component\Form\RequestHandlerInterface;
18+
use Symfony\Component\Form\Util\ServerParams;
1919
use Symfony\Component\HttpFoundation\Request;
2020

2121
/**
@@ -68,6 +68,23 @@ public function handleRequest(FormInterface $form, $request = null)
6868
$data = $request->query->get($name);
6969
}
7070
} else {
71+
// Mark the form with an error if the uploaded size was too large
72+
// This is done here and not in FormValidator because $_POST is
73+
// empty when that error occurs. Hence the form is never submitted.
74+
$contentLength = $this->serverParams->getContentLength();
75+
$maxContentLength = $this->serverParams->getPostMaxSize();
76+
77+
if (!empty($maxContentLength) && $contentLength > $maxContentLength) {
78+
$form->addError(new FormError(
79+
$form->getConfig()->getOption('post_max_size_message'),
80+
null,
81+
array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize())
82+
));
83+
84+
// The form stays unsubmitted, since we have no data to submit
85+
return;
86+
}
87+
7188
if ('' === $name) {
7289
$params = $request->request->all();
7390
$files = $request->files->all();
@@ -76,10 +93,6 @@ public function handleRequest(FormInterface $form, $request = null)
7693
$params = $request->request->get($name, $default);
7794
$files = $request->files->get($name, $default);
7895
} else {
79-
if ($this->serverParams->getContentLength() > $this->serverParams->getPostMaxSize()) {
80-
$form->addError(new FormError('Max post size exceeded.'));
81-
}
82-
8396
// Don't submit the form if it is not present in the request
8497
return;
8598
}

src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -113,21 +113,6 @@ public function validate($form, Constraint $constraint)
113113
$form->getExtraData()
114114
);
115115
}
116-
117-
// Mark the form with an error if the uploaded size was too large
118-
$length = $this->serverParams->getContentLength();
119-
120-
if ($form->isRoot() && null !== $length) {
121-
$max = $this->serverParams->getPostMaxSize();
122-
123-
if (!empty($max) && $length > $max) {
124-
$this->context->addViolation(
125-
$config->getOption('post_max_size_message'),
126-
array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()),
127-
$length
128-
);
129-
}
130-
}
131116
}
132117

133118
/**

src/Symfony/Component/Form/Extension/Validator/Type/FormTypeValidatorExtension.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver)
6666
'invalid_message' => 'This value is not valid.',
6767
'invalid_message_parameters' => array(),
6868
'extra_fields_message' => 'This form should not contain extra fields.',
69-
'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.',
7069
));
7170

7271
$resolver->setNormalizers(array(

src/Symfony/Component/Form/Extension/Validator/Util/ServerParams.php

Lines changed: 4 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -13,61 +13,10 @@
1313

1414
/**
1515
* @author Bernhard Schussek <bschussek@gmail.com>
16+
*
17+
* @deprecated To be removed in Symfony 3.0. Use {@link \Symfony\Component\Form\Util\ServerParams}
18+
* instead.
1619
*/
17-
class ServerParams
20+
class ServerParams extends \Symfony\Component\Form\Util\ServerParams
1821
{
19-
/**
20-
* Returns maximum post size in bytes.
21-
*
22-
* @return null|int The maximum post size in bytes
23-
*/
24-
public function getPostMaxSize()
25-
{
26-
$iniMax = strtolower($this->getNormalizedIniPostMaxSize());
27-
28-
if ('' === $iniMax) {
29-
return;
30-
}
31-
32-
$max = ltrim($iniMax, '+');
33-
if (0 === strpos($max, '0x')) {
34-
$max = intval($max, 16);
35-
} elseif (0 === strpos($max, '0')) {
36-
$max = intval($max, 8);
37-
} else {
38-
$max = intval($max);
39-
}
40-
41-
switch (substr($iniMax, -1)) {
42-
case 't': $max *= 1024;
43-
case 'g': $max *= 1024;
44-
case 'm': $max *= 1024;
45-
case 'k': $max *= 1024;
46-
}
47-
48-
return $max;
49-
}
50-
51-
/**
52-
* Returns the normalized "post_max_size" ini setting.
53-
*
54-
* @return string
55-
*/
56-
public function getNormalizedIniPostMaxSize()
57-
{
58-
return strtoupper(trim(ini_get('post_max_size')));
59-
}
60-
61-
/**
62-
* Returns the content length of the request.
63-
*
64-
* @return mixed The request content length.
65-
*/
66-
public function getContentLength()
67-
{
68-
return isset($_SERVER['CONTENT_LENGTH'])
69-
? (int) $_SERVER['CONTENT_LENGTH']
70-
: null;
71-
}
72-
7322
}

src/Symfony/Component/Form/NativeRequestHandler.php

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
namespace Symfony\Component\Form;
1313

1414
use Symfony\Component\Form\Exception\UnexpectedTypeException;
15-
use Symfony\Component\Form\Extension\Validator\Util\ServerParams;
15+
use Symfony\Component\Form\Util\ServerParams;
1616

1717
/**
1818
* A request handler using PHP's super globals $_GET, $_POST and $_SERVER.
@@ -76,6 +76,23 @@ public function handleRequest(FormInterface $form, $request = null)
7676
$data = $_GET[$name];
7777
}
7878
} else {
79+
// Mark the form with an error if the uploaded size was too large
80+
// This is done here and not in FormValidator because $_POST is
81+
// empty when that error occurs. Hence the form is never submitted.
82+
$contentLength = $this->serverParams->getContentLength();
83+
$maxContentLength = $this->serverParams->getPostMaxSize();
84+
85+
if (!empty($maxContentLength) && $contentLength > $maxContentLength) {
86+
$form->addError(new FormError(
87+
$form->getConfig()->getOption('post_max_size_message'),
88+
null,
89+
array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize())
90+
));
91+
92+
// The form stays unsubmitted, since we have no data to submit
93+
return;
94+
}
95+
7996
$fixedFiles = array();
8097
foreach ($_FILES as $name => $file) {
8198
$fixedFiles[$name] = self::stripEmptyFiles(self::fixPhpFilesArray($file));
@@ -89,10 +106,6 @@ public function handleRequest(FormInterface $form, $request = null)
89106
$params = array_key_exists($name, $_POST) ? $_POST[$name] : $default;
90107
$files = array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default;
91108
} else {
92-
if ($this->serverParams->getContentLength() > $this->serverParams->getPostMaxSize()) {
93-
$form->addError(new FormError('Max post size exceeded.'));
94-
}
95-
96109
// Don't submit the form if it is not present in the request
97110
return;
98111
}

src/Symfony/Component/Form/Tests/AbstractRequestHandlerTest.php

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,36 @@
1111

1212
namespace Symfony\Component\Form\Tests;
1313

14+
use Symfony\Component\Form\FormError;
15+
use Symfony\Component\Form\FormFactory;
1416
use Symfony\Component\Form\Forms;
17+
use Symfony\Component\Form\RequestHandlerInterface;
1518

1619
/**
1720
* @author Bernhard Schussek <bschussek@gmail.com>
1821
*/
1922
abstract class AbstractRequestHandlerTest extends \PHPUnit_Framework_TestCase
2023
{
2124
/**
22-
* @var \Symfony\Component\Form\RequestHandlerInterface
25+
* @var RequestHandlerInterface
2326
*/
2427
protected $requestHandler;
2528

2629
/**
27-
* @var \Symfony\Component\Form\FormFactory
30+
* @var FormFactory
2831
*/
2932
protected $factory;
3033

3134
protected $request;
3235

36+
protected $serverParams;
37+
3338
protected function setUp()
3439
{
40+
$this->serverParams = $this->getMock(
41+
'Symfony\Component\Form\Util\ServerParams',
42+
array('getNormalizedIniPostMaxSize', 'getContentLength')
43+
);
3544
$this->requestHandler = $this->getRequestHandler();
3645
$this->factory = Forms::createFormFactoryBuilder()->getFormFactory();
3746
$this->request = null;
@@ -257,17 +266,46 @@ public function testSubmitFileIfNoParam($method)
257266
$this->requestHandler->handleRequest($form, $this->request);
258267
}
259268

260-
public function testAddFormErrorIfPostMaxSizeExceeded()
269+
/**
270+
* @dataProvider getPostMaxSizeFixtures
271+
*/
272+
public function testAddFormErrorIfPostMaxSizeExceeded($contentLength, $iniMax, $shouldFail, array $errorParams = array())
261273
{
262-
$form = $this->factory->createNamed('name', 'text');
274+
$this->serverParams->expects($this->once())
275+
->method('getContentLength')
276+
->will($this->returnValue($contentLength));
277+
$this->serverParams->expects($this->any())
278+
->method('getNormalizedIniPostMaxSize')
279+
->will($this->returnValue($iniMax));
280+
281+
$options = array('post_max_size_message' => 'Max {{ max }}!');
282+
$form = $this->factory->createNamed('name', 'text', null, $options);
263283
$this->setRequestData('POST', array(), array());
264-
$_SERVER['CONTENT_LENGTH'] = 1000000000;
265284

266285
$this->requestHandler->handleRequest($form, $this->request);
267286

268-
$this->assertEquals("ERROR: Max post size exceeded.\n", $form->getErrorsAsString());
287+
if ($shouldFail) {
288+
$errors = array(new FormError($options['post_max_size_message'], null, $errorParams));
269289

270-
unset($_SERVER['CONTENT_LENGTH']);
290+
$this->assertEquals($errors, $form->getErrors());
291+
} else {
292+
$this->assertCount(0, $form->getErrors());
293+
}
294+
}
295+
296+
public function getPostMaxSizeFixtures()
297+
{
298+
return array(
299+
array(pow(1024, 3) + 1, '1G', true, array('{{ max }}' => '1G')),
300+
array(pow(1024, 3), '1G', false),
301+
array(pow(1024, 2) + 1, '1M', true, array('{{ max }}' => '1M')),
302+
array(pow(1024, 2), '1M', false),
303+
array(1024 + 1, '1K', true, array('{{ max }}' => '1K')),
304+
array(1024, '1K', false),
305+
array(null, '1K', false),
306+
array(1024, '', false),
307+
array(1024, 0, false),
308+
);
271309
}
272310

273311
abstract protected function setRequestData($method, $data, $files = array());

src/Symfony/Component/Form/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ protected function setRequestData($method, $data, $files = array())
4343

4444
protected function getRequestHandler()
4545
{
46-
return new HttpFoundationRequestHandler();
46+
return new HttpFoundationRequestHandler($this->serverParams);
4747
}
4848

4949
protected function getMockFile()

0 commit comments

Comments
 (0)
0