Range support is broken. The test isset always returns true because the explode function will return empty strings if nothin is specified. As a result if parts[0] is an empty string no start is set; same for the endpoint. This is fixed here. Furthermore if the start is not specified, the range must be applied to the end of the file as specified in the the http 1.1 standard. Finally I added brackets to avoid malformed headers.
89 lines
2.3 KiB
PHP
89 lines
2.3 KiB
PHP
<?php
|
|
/**
|
|
* ownCloud - Documents App
|
|
*
|
|
* @author Victor Dubiniuk
|
|
* @copyright 2013 Victor Dubiniuk victor.dubiniuk@gmail.com
|
|
*
|
|
* This file is licensed under the Affero General Public License version 3 or
|
|
* later.
|
|
*/
|
|
|
|
namespace OCA\Documents;
|
|
|
|
/**
|
|
* Class processing range HTTP request (partial download)
|
|
*/
|
|
class Download_Range extends \OCA\Documents\Download {
|
|
|
|
// Start of the range
|
|
protected $start;
|
|
// End of the range
|
|
protected $end;
|
|
|
|
/**
|
|
* Build download model to serve HTTP_RANGE
|
|
* @param type $view - filesystem view
|
|
* @param type $filepath - path to the file relative to this view root
|
|
*/
|
|
public function __construct($owner, $filepath){
|
|
$this->view = $this->getView($owner);
|
|
$this->filepath = $filepath;
|
|
}
|
|
|
|
/**
|
|
* Send the requested parts of the file
|
|
*/
|
|
public function sendResponse(){
|
|
if (!preg_match('/^bytes=\d*-\d*(,\d*-\d*)*$/', $_SERVER['HTTP_RANGE'])){
|
|
$this->sendNotSatisfiable();
|
|
}
|
|
|
|
$mimetype = $this->getMimeType();
|
|
$content = $this->view->file_get_contents($this->filepath);
|
|
$data = Filter::read($content, $mimetype);
|
|
$size = strlen($data['content']);
|
|
|
|
$ranges = explode(',', substr($_SERVER['HTTP_RANGE'], 6));
|
|
foreach ($ranges as $range){
|
|
$parts = explode('-', $range);
|
|
|
|
if ($parts[0]==='' && $parts[1]=='') {$this->sendNotSatisfiable();}
|
|
if ($parts[0]==='') {
|
|
$start = $size - $parts[1];
|
|
$end = $size - 1;}
|
|
else {
|
|
$start = $parts[0];
|
|
$end = ($parts[1]==='') ? $size - 1 : $parts[1];}
|
|
|
|
if ($start > $end){
|
|
$this->sendNotSatisfiable();
|
|
}
|
|
|
|
$buffer = substr($data['content'], $start, $end - $start);
|
|
$md5Sum = md5($buffer);
|
|
|
|
// send the headers and data
|
|
header("Content-Length: " . ($end - $start));
|
|
header("Content-md5: " . $md5Sum);
|
|
header("Accept-Ranges: bytes");
|
|
header('Content-Range: bytes ' . $start . '-' . ($end) . '/' . $size);
|
|
header("Connection: close");
|
|
header("Content-type: " . $data['mimetype']);
|
|
header('Content-Disposition: attachment; filename=' . $this->getFilename());
|
|
\OC_Util::obEnd();
|
|
echo $buffer;
|
|
flush();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send 416 if we can't satisfy the requested ranges
|
|
*/
|
|
protected function sendNotSatisfiable(){
|
|
header('HTTP/1.1 416 Requested Range Not Satisfiable');
|
|
header('Content-Range: bytes */' . $this->getFilesize()); // Required in 416.
|
|
exit;
|
|
}
|
|
}
|