diff --git a/src/Io/MultipartParser.php b/src/Io/MultipartParser.php index 47422009..0c196f97 100644 --- a/src/Io/MultipartParser.php +++ b/src/Io/MultipartParser.php @@ -68,7 +68,7 @@ final class MultipartParser private $emptyCount = 0; /** - * @param int|null $uploadMaxFilesize + * @param int|string|null $uploadMaxFilesize * @param int|null $maxFileUploads */ public function __construct($uploadMaxFilesize = null, $maxFileUploads = null) @@ -83,10 +83,10 @@ public function __construct($uploadMaxFilesize = null, $maxFileUploads = null) } if ($uploadMaxFilesize === null) { - $uploadMaxFilesize = IniUtil::iniSizeToBytes(ini_get('upload_max_filesize')); + $uploadMaxFilesize = ini_get('upload_max_filesize'); } - $this->uploadMaxFilesize = (int)$uploadMaxFilesize; + $this->uploadMaxFilesize = IniUtil::iniSizeToBytes($uploadMaxFilesize); $this->maxFileUploads = $maxFileUploads === null ? (ini_get('file_uploads') === '' ? 0 : (int)ini_get('max_file_uploads')) : (int)$maxFileUploads; } diff --git a/src/Middleware/RequestBodyBufferMiddleware.php b/src/Middleware/RequestBodyBufferMiddleware.php index 7ef2503b..503bc9fd 100644 --- a/src/Middleware/RequestBodyBufferMiddleware.php +++ b/src/Middleware/RequestBodyBufferMiddleware.php @@ -14,18 +14,19 @@ final class RequestBodyBufferMiddleware private $sizeLimit; /** - * @param int|null $sizeLimit Either an int with the max request body size - * or null to use post_max_size from PHP's - * configuration. (Note that the value from - * the CLI configuration will be used.) + * @param int|string|null $sizeLimit Either an int with the max request body size + * in bytes or an ini like size string + * or null to use post_max_size from PHP's + * configuration. (Note that the value from + * the CLI configuration will be used.) */ public function __construct($sizeLimit = null) { if ($sizeLimit === null) { - $sizeLimit = IniUtil::iniSizeToBytes(ini_get('post_max_size')); + $sizeLimit = ini_get('post_max_size'); } - $this->sizeLimit = $sizeLimit; + $this->sizeLimit = IniUtil::iniSizeToBytes($sizeLimit); } public function __invoke(ServerRequestInterface $request, $stack) diff --git a/src/Middleware/RequestBodyParserMiddleware.php b/src/Middleware/RequestBodyParserMiddleware.php index 63759642..005c28cd 100644 --- a/src/Middleware/RequestBodyParserMiddleware.php +++ b/src/Middleware/RequestBodyParserMiddleware.php @@ -10,7 +10,7 @@ final class RequestBodyParserMiddleware private $multipart; /** - * @param int|null $uploadMaxFilesize + * @param int|string|null $uploadMaxFilesize * @param int|null $maxFileUploads */ public function __construct($uploadMaxFilesize = null, $maxFileUploads = null) diff --git a/tests/Io/MultipartParserTest.php b/tests/Io/MultipartParserTest.php index b070c93b..45ac0c4d 100644 --- a/tests/Io/MultipartParserTest.php +++ b/tests/Io/MultipartParserTest.php @@ -721,6 +721,39 @@ public function testUploadTooLargeFile() $this->assertSame(UPLOAD_ERR_INI_SIZE, $file->getError()); } + public function testUploadTooLargeFileWithIniLikeSize() + { + $boundary = "---------------------------12758086162038677464950549563"; + + $data = "--$boundary\r\n"; + $data .= "Content-Disposition: form-data; name=\"file\"; filename=\"hello\"\r\n"; + $data .= "Content-type: text/plain\r\n"; + $data .= "\r\n"; + $data .= str_repeat('world', 1024) . "\r\n"; + $data .= "--$boundary--\r\n"; + + $request = new ServerRequest('POST', 'http://example.com/', array( + 'Content-Type' => 'multipart/form-data; boundary=' . $boundary, + ), $data, 1.1); + + $parser = new MultipartParser('1K'); + $parsedRequest = $parser->parse($request); + + $files = $parsedRequest->getUploadedFiles(); + + $this->assertCount(1, $files); + $this->assertTrue(isset($files['file'])); + $this->assertInstanceOf('Psr\Http\Message\UploadedFileInterface', $files['file']); + + /* @var $file \Psr\Http\Message\UploadedFileInterface */ + $file = $files['file']; + + $this->assertSame('hello', $file->getClientFilename()); + $this->assertSame('text/plain', $file->getClientMediaType()); + $this->assertSame(5120, $file->getSize()); + $this->assertSame(UPLOAD_ERR_INI_SIZE, $file->getError()); + } + public function testUploadNoFile() { $boundary = "---------------------------12758086162038677464950549563"; diff --git a/tests/Middleware/RequestBodyBufferMiddlewareTest.php b/tests/Middleware/RequestBodyBufferMiddlewareTest.php index 91bd14cc..913a733f 100644 --- a/tests/Middleware/RequestBodyBufferMiddlewareTest.php +++ b/tests/Middleware/RequestBodyBufferMiddlewareTest.php @@ -46,7 +46,7 @@ public function testAlreadyBufferedResolvesImmediately() { $size = 1024; $body = str_repeat('x', $size); - $stream = new BufferStream($size); + $stream = new BufferStream(1024); $stream->write($body); $serverRequest = new ServerRequest( 'GET', @@ -93,6 +93,33 @@ function (ServerRequestInterface $request) { $this->assertSame('', $response->getBody()->getContents()); } + public function testKnownExcessiveSizedWithIniLikeSize() + { + $loop = Factory::create(); + + $stream = new ThroughStream(); + $loop->addTimer(0.001, function () use ($stream) { + $stream->end(str_repeat('a', 2048)); + }); + $serverRequest = new ServerRequest( + 'GET', + 'https://example.com/', + array(), + new HttpBodyStream($stream, 2048) + ); + + $buffer = new RequestBodyBufferMiddleware('1K'); + $response = Block\await($buffer( + $serverRequest, + function (ServerRequestInterface $request) { + return new Response(200, array(), $request->getBody()->getContents()); + } + ), $loop); + + $this->assertSame(200, $response->getStatusCode()); + $this->assertSame('', $response->getBody()->getContents()); + } + public function testAlreadyBufferedExceedingSizeResolvesImmediatelyWithEmptyBody() { $serverRequest = new ServerRequest(