Merge branch '3.2.x'

* 3.2.x:
  [ticket/14774] Support partial downloads of attachments
This commit is contained in:
Tristan Darricau 2016-09-11 13:59:08 +02:00
commit d9aea27c75
No known key found for this signature in database
GPG key ID: 817043C2E29DB881
2 changed files with 119 additions and 59 deletions

View file

@ -254,12 +254,22 @@ function send_file_to_browser($attachment, $upload_dir, $category)
send_status_line(206, 'Partial Content'); send_status_line(206, 'Partial Content');
header('Content-Range: bytes ' . $range['byte_pos_start'] . '-' . $range['byte_pos_end'] . '/' . $range['bytes_total']); header('Content-Range: bytes ' . $range['byte_pos_start'] . '-' . $range['byte_pos_end'] . '/' . $range['bytes_total']);
header('Content-Length: ' . $range['bytes_requested']); header('Content-Length: ' . $range['bytes_requested']);
}
// First read chunks
while (!feof($fp) && ftell($fp) < $range['byte_pos_end'] - 8192)
{
echo fread($fp, 8192);
}
// Then, read the remainder
echo fread($fp, $range['bytes_requested'] % 8192);
}
else
{
while (!feof($fp)) while (!feof($fp))
{ {
echo fread($fp, 8192); echo fread($fp, 8192);
} }
}
fclose($fp); fclose($fp);
} }
else else
@ -529,6 +539,9 @@ function phpbb_find_range_request()
*/ */
function phpbb_parse_range_request($request_array, $filesize) function phpbb_parse_range_request($request_array, $filesize)
{ {
$first_byte_pos = -1;
$last_byte_pos = -1;
// Go through all ranges // Go through all ranges
foreach ($request_array as $range_string) foreach ($request_array as $range_string)
{ {
@ -540,36 +553,37 @@ function phpbb_parse_range_request($request_array, $filesize)
continue; continue;
} }
// Substitute defaults
if ($range[0] === '') if ($range[0] === '')
{ {
// Return last $range[1] bytes. $range[0] = 0;
if (!$range[1])
{
continue;
} }
if ($range[1] >= $filesize) if ($range[1] === '')
{ {
$range[1] = $filesize - 1;
}
if ($last_byte_pos >= 0 && $last_byte_pos + 1 != $range[0])
{
// We only support contiguous ranges, no multipart stuff :(
return false; return false;
} }
$first_byte_pos = $filesize - (int) $range[1]; if ($range[1] && $range[1] < $range[0])
$last_byte_pos = $filesize - 1;
}
else
{
// Return bytes from $range[0] to $range[1]
$first_byte_pos = (int) $range[0];
$last_byte_pos = (int) $range[1];
if ($last_byte_pos && $last_byte_pos < $first_byte_pos)
{ {
// The requested range contains 0 bytes. // The requested range contains 0 bytes.
continue; continue;
} }
// Return bytes from $range[0] to $range[1]
if ($first_byte_pos < 0)
{
$first_byte_pos = (int) $range[0];
}
$last_byte_pos = (int) $range[1];
if ($first_byte_pos >= $filesize) if ($first_byte_pos >= $filesize)
{ {
// Requested range not satisfiable // Requested range not satisfiable
@ -583,10 +597,9 @@ function phpbb_parse_range_request($request_array, $filesize)
} }
} }
// We currently do not support range requests that end before the end of the file if ($first_byte_pos < 0 || $last_byte_pos < 0)
if ($last_byte_pos != $filesize - 1)
{ {
continue; return false;
} }
return array( return array(
@ -595,7 +608,6 @@ function phpbb_parse_range_request($request_array, $filesize)
'bytes_requested' => $last_byte_pos - $first_byte_pos + 1, 'bytes_requested' => $last_byte_pos - $first_byte_pos + 1,
'bytes_total' => $filesize, 'bytes_total' => $filesize,
); );
}
} }
/** /**

View file

@ -45,23 +45,71 @@ class phpbb_download_http_byte_range_test extends phpbb_test_case
public function parse_range_request_data() public function parse_range_request_data()
{ {
return array( return array(
// Does not read until the end of file. // Valid request
array( array(
array('3-4'), array('3-4'),
10, 10,
false, array(
'byte_pos_start' => 3,
'byte_pos_end' => 4,
'bytes_requested' => 2,
'bytes_total' => 10,
),
), ),
// Valid request, handle second range. // Get the beginning
array(
array('-5'),
10,
array(
'byte_pos_start' => 0,
'byte_pos_end' => 5,
'bytes_requested' => 6,
'bytes_total' => 10,
),
),
// Get the end
array(
array('5-'),
10,
array(
'byte_pos_start' => 5,
'byte_pos_end' => 9,
'bytes_requested' => 5,
'bytes_total' => 10,
),
),
// Overlong request
array(
array('3-20'),
10,
array(
'byte_pos_start' => 3,
'byte_pos_end' => 9,
'bytes_requested' => 7,
'bytes_total' => 10,
),
),
// Multiple, contiguous range
array(
array('10-20', '21-30'),
125,
array(
'byte_pos_start' => 10,
'byte_pos_end' => 30,
'bytes_requested' => 21,
'bytes_total' => 125,
)
),
// We don't do multiple, non-contiguous range
array( array(
array('0-0', '120-125'), array('0-0', '120-125'),
125, 125,
array( false,
'byte_pos_start' => 120,
'byte_pos_end' => 124,
'bytes_requested' => 5,
'bytes_total' => 125,
)
), ),
); );
} }