Skip to content

Commit 1413362

Browse files
Merge branch '4777-output-file-range-parsing'
2 parents 97dd74d + 9233d5c commit 1413362

1 file changed

Lines changed: 36 additions & 15 deletions

File tree

web/includes/functions.php

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2367,22 +2367,38 @@ function output_file($path, $chunkSize=1024) {
23672367
header("Content-Disposition: $contentDisposition;filename=\"$file\"");
23682368

23692369
header('Accept-Ranges: bytes');
2370-
$range = 0;
23712370
$size = filesize($path);
2371+
$start = 0;
2372+
$end = $size - 1;
23722373

23732374
if (isset($_SERVER['HTTP_RANGE'])) {
2374-
list($a, $range) = explode('=', $_SERVER['HTTP_RANGE']);
2375-
str_replace($range, '-', $range);
2376-
$range = (int)$range; #fseek etc require integers not strings
2377-
$size2 = $size - 1;
2378-
$new_length = $size - $range;
2375+
# RFC 7233: bytes=start-end | bytes=start- | bytes=-suffix
2376+
if (preg_match('/^bytes=(\d*)-(\d*)$/', trim($_SERVER['HTTP_RANGE']), $m)
2377+
and ($m[1] !== '' or $m[2] !== '')) {
2378+
if ($m[1] === '') {
2379+
# Suffix range: last N bytes
2380+
$suffix = (int)$m[2];
2381+
if ($suffix > $size) $suffix = $size;
2382+
$start = $size - $suffix;
2383+
} else {
2384+
$start = (int)$m[1];
2385+
if ($m[2] !== '') $end = (int)$m[2];
2386+
}
2387+
if ($end > $size - 1) $end = $size - 1;
2388+
}
2389+
if ($start > $end or $start >= $size) {
2390+
header('HTTP/1.1 416 Range Not Satisfiable');
2391+
header("Content-Range: bytes */$size");
2392+
return false;
2393+
}
2394+
$length = $end - $start + 1;
23792395
header('HTTP/1.1 206 Partial Content');
2380-
header("Content-Length: $new_length");
2381-
header("Content-Range: bytes $range-$size2/$size");
2396+
header("Content-Length: $length");
2397+
header("Content-Range: bytes $start-$end/$size");
23822398
} else {
2383-
$size2 = $size - 1;
2384-
header("Content-Range: bytes 0-$size2/$size");
2385-
header('Content-Length: ' . $size);
2399+
$length = $size;
2400+
header("Content-Range: bytes 0-$end/$size");
2401+
header("Content-Length: $size");
23862402
}
23872403

23882404
if ($size == 0) {
@@ -2391,13 +2407,18 @@ function output_file($path, $chunkSize=1024) {
23912407
@ini_set('magic_quotes_runtime', 0);
23922408
$fp = fopen($path, 'rb');
23932409

2394-
fseek($fp, $range);
2410+
fseek($fp, $start);
23952411

2396-
while (!feof($fp) and (connection_status() == 0)) {
2412+
$remaining = $length;
2413+
$buffer = 1024 * $chunkSize;
2414+
while ($remaining > 0 and !feof($fp) and (connection_status() == 0)) {
23972415
set_time_limit(0);
2398-
print(@fread($fp, 1024*$chunkSize));
2416+
$data = @fread($fp, min($buffer, $remaining));
2417+
if ($data === false or $data === '') break;
2418+
print($data);
23992419
flush();
2400-
ob_flush();
2420+
if (ob_get_level() > 0) ob_flush();
2421+
$remaining -= strlen($data);
24012422
}
24022423
fclose($fp);
24032424

0 commit comments

Comments
 (0)