Skip to content

Commit

Permalink
Handle malformed Range headers without warnings.
Browse files Browse the repository at this point in the history
Don't emit warnings on malformed/invalid range headers. Also make
parsing more robust and allow whitespace between significant tokens.
  • Loading branch information
markstory committed Mar 8, 2016
1 parent 5a20418 commit a49361f
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 4 deletions.
11 changes: 8 additions & 3 deletions src/Network/Response.php
Expand Up @@ -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;
Expand Down
58 changes: 57 additions & 1 deletion tests/TestCase/Network/ResponseTest.php
Expand Up @@ -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'
],
];
}

Expand Down Expand Up @@ -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', [
Expand Down

0 comments on commit a49361f

Please sign in to comment.