From a49361fc7c711702d179ab41c3a477993fdeadc2 Mon Sep 17 00:00:00 2001 From: Mark Story Date: Mon, 7 Mar 2016 22:47:11 -0500 Subject: [PATCH] Handle malformed Range headers without warnings. Don't emit warnings on malformed/invalid range headers. Also make parsing more robust and allow whitespace between significant tokens. --- src/Network/Response.php | 11 +++-- tests/TestCase/Network/ResponseTest.php | 58 ++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/Network/Response.php b/src/Network/Response.php index 0d137b1ec06..0f060911306 100644 --- a/src/Network/Response.php +++ b/src/Network/Response.php @@ -1478,11 +1478,16 @@ public function getFile() */ protected function _fileRange($file, $httpRange) { - list(, $range) = explode('=', $httpRange); - list($start, $end) = explode('-', $range); - $fileSize = $file->size(); $lastByte = $fileSize - 1; + $start = 0; + $end = $lastByte; + + preg_match('/^bytes\s*=\s*(\d+)?\s*-\s*(\d+)?$/', $httpRange, $matches); + if ($matches) { + $start = $matches[1]; + $end = isset($matches[2]) ? $matches[2] : ''; + } if ($start === '') { $start = $fileSize - $end; diff --git a/tests/TestCase/Network/ResponseTest.php b/tests/TestCase/Network/ResponseTest.php index ebc9cc9e7bb..6e181aaa008 100644 --- a/tests/TestCase/Network/ResponseTest.php +++ b/tests/TestCase/Network/ResponseTest.php @@ -1631,12 +1631,19 @@ public static function rangeProvider() [ 'bytes=0-', 38, 'bytes 0-37/38' ], + [ 'bytes=10-', 28, 'bytes 10-37/38' ], + [ 'bytes=10-20', 11, 'bytes 10-20/38' ], + + // Spaced out + [ + 'bytes = 10 - 20', 11, 'bytes 10-20/38' + ], ]; } @@ -1746,12 +1753,61 @@ public function testFileRange() $this->assertNotSame(false, $result); } + /** + * Provider for invalid range header values. + * + * @return array + */ + public function invalidFileRangeProvider() + { + return [ + // malformed range + [ + 'bytes=0,38' + ], + + // malformed punctuation + [ + 'bytes: 0 - 38' + ], + ]; + } + /** * Test invalid file ranges. * + * @dataProvider invalidFileRangeProvider + * @return void + */ + public function testFileRangeInvalid($range) + { + $_SERVER['HTTP_RANGE'] = $range; + $response = $this->getMock('Cake\Network\Response', [ + '_sendHeader', + '_isActive', + ]); + + $response->file( + TEST_APP . 'vendor' . DS . 'css' . DS . 'test_asset.css', + ['download' => true] + ); + + $expected = [ + 'Content-Disposition' => 'attachment; filename="test_asset.css"', + 'Content-Transfer-Encoding' => 'binary', + 'Accept-Ranges' => 'bytes', + 'Content-Range' => 'bytes 0-37/38', + 'Content-Length' => 38, + ]; + $this->assertEquals($expected, $response->header()); + } + + /** + * Test reversed file ranges. + * * @return void */ - public function testFileRangeInvalid() + public function testFileRangeReversed() { $_SERVER['HTTP_RANGE'] = 'bytes=30-2'; $response = $this->getMock('Cake\Network\Response', [