diff options
author | Victor Dubiniuk <victor.dubiniuk@gmail.com> | 2014-10-29 00:52:43 +0300 |
---|---|---|
committer | Victor Dubiniuk <victor.dubiniuk@gmail.com> | 2014-10-29 00:58:28 +0300 |
commit | 7416b8b5d6d461eb8e172b25126fee77df00f358 (patch) | |
tree | e4abeed82174822edb6aef301109bd82f1304560 /lib | |
parent | 4180d6655552ce5287f07c3e7b09e55e3219c378 (diff) |
Implement downloadresponse via appframework
Diffstat (limited to 'lib')
-rw-r--r-- | lib/download.php | 113 | ||||
-rw-r--r-- | lib/download/range.php | 92 | ||||
-rw-r--r-- | lib/download/simple.php | 50 | ||||
-rw-r--r-- | lib/downloadresponse.php | 115 |
4 files changed, 115 insertions, 255 deletions
diff --git a/lib/download.php b/lib/download.php deleted file mode 100644 index 255591d4..00000000 --- a/lib/download.php +++ /dev/null @@ -1,113 +0,0 @@ -<?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; - -/** - * Generic download class - */ -class Download { - - /** - * Filesystem view - * @var \OC\Files\View - */ - protected $view; - - /** - * Path to the File to be served, relative to the view - * @var string - */ - protected $filepath; - - /** - * Subclassed object - * @var - */ - protected $instance; - - /** - * Build download model according to the headers - * @param type $view - filesystem view - * @param type $filepath - path to the file relative to this view root - */ - public function __construct($owner, $filepath){ - $this->filepath = $filepath; - - if (isset($_SERVER['HTTP_RANGE'])) { - $this->instance = new Download\Range($owner, $filepath); - } else { - $this->instance = new Download\Simple($owner, $filepath); - } - - $this->view = $this->getView($owner); - } - - protected function getView($owner){ - return new View('/' . $owner); - } - - /** - * Send the requested content - */ - public function sendResponse(){ - \OCP\Response::disableCaching(); - - if (!$this->fileExists()){ - $this->sendNotFound(); - } - - $this->instance->sendResponse(); - exit(); - } - - /** - * Get the name of the requested file - * @return String - */ - protected function getFilename(){ - return basename($this->filepath); - } - - /** - * Get the size of the requested file - */ - protected function getFilesize(){ - return $this->view->filesize($this->filepath); - } - - /** - * Get the mimetype of the requested file - * @return string - */ - protected function getMimeType(){ - return $this->view->getMimeType($this->filepath); - } - - /** - * Check if the requested file exists - * @return bool - */ - protected function fileExists(){ - return $this->view->file_exists($this->filepath); - } - - /** - * Send 404 Response - */ - protected function sendNotFound(){ - header("HTTP/1.0 404 Not Found"); - $tmpl = new \OCP\Template('', '404', 'guest'); - $tmpl->assign('file', $this->filepath); - $tmpl->printPage(); - exit; - } -} diff --git a/lib/download/range.php b/lib/download/range.php deleted file mode 100644 index 8344a531..00000000 --- a/lib/download/range.php +++ /dev/null @@ -1,92 +0,0 @@ -<?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\Download; - -/** - * Class processing range HTTP request (partial download) - */ -class 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 = \OCA\Documents\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; - } -} diff --git a/lib/download/simple.php b/lib/download/simple.php deleted file mode 100644 index 916249e7..00000000 --- a/lib/download/simple.php +++ /dev/null @@ -1,50 +0,0 @@ -<?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\Download; - -/** - * Class processing complete download - */ -class Simple extends \OCA\Documents\Download { - - public function __construct($owner, $filepath){ - $this->view = $this->getView($owner); - $this->filepath = $filepath; - } - - /** - * Send the whole file content as a response - */ - public function sendResponse(){ - $mimetype = $this->getMimeType(); - $content = $this->view->file_get_contents($this->filepath); - $data = \OCA\Documents\Filter::read($content, $mimetype); - - header( 'Content-Type:' . $data['mimetype'] ); - - $encodedName = rawurlencode($this->getFilename()); - if (preg_match("/MSIE/", $_SERVER["HTTP_USER_AGENT"])){ - header( - 'Content-Disposition: attachment; filepath="' . $encodedName . '"' - ); - } else { - header('Content-Disposition: attachment; filepath*=UTF-8\'\'' . $encodedName - . '; filepath="' . $encodedName . '"'); - } - - header('Content-Length: ' . strlen($data['content'])); - - \OC_Util::obEnd(); - - echo $data['content']; - } -} diff --git a/lib/downloadresponse.php b/lib/downloadresponse.php new file mode 100644 index 00000000..618aea9f --- /dev/null +++ b/lib/downloadresponse.php @@ -0,0 +1,115 @@ +<?php +/** + * ownCloud - Documents App + * + * @author Victor Dubiniuk + * @copyright 2014 Victor Dubiniuk victor.dubiniuk@gmail.com + * + * This file is licensed under the Affero General Public License version 3 or + * later. + */ + +namespace OCA\Documents; + +use \OCP\AppFramework\Http; + +class DownloadResponse extends \OCP\AppFramework\Http\Response { + private $request; + private $view; + private $path; + + public function __construct($request, $user, $path) { + $this->request = $request; + $this->user = $user; + $this->path = $path; + $this->view = new View('/' . $user); + if (!$this->view->file_exists($path)){ + $this->setStatus(Http::STATUS_NOT_FOUND); + } + } + + public function render(){ + if ($this->status === Http::STATUS_NOT_FOUND){ + return ''; + } + + $info = $this->view->getFileInfo($this->path); + $this->ETag = $info['etag']; + + $content = $this->view->file_get_contents($this->path); + $data = \OCA\Documents\Filter::read($content, $info['mimetype']); + $size = strlen($data['content']); + + + if (!is_null($this->request->server['HTTP_RANGE'])){ + $isValidRange = preg_match('/^bytes=\d*-\d*(,\d*-\d*)*$/', $this->request->server['HTTP_RANGE']); + if (!$isValidRange){ + return $this->sendRangeNotSatisfiable($size); + } + + $ranges = explode(',', substr($this->request->server['HTTP_RANGE'], 6)); + foreach ($ranges as $range){ + $parts = explode('-', $range); + + if ($parts[0]==='' && $parts[1]=='') { + $this->sendNotSatisfiable($size); + } + 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($size); + } + + $buffer = substr($data['content'], $start, $end - $start); + $md5Sum = md5($buffer); + + // send the headers and data + $this->addHeader('Content-Length', $end - $start); + $this->addHeader('Content-md5', $md5Sum); + $this->addHeader('Accept-Ranges', 'bytes'); + $this->addHeader('Content-Range', 'bytes ' . $start . '-' . ($end) . '/' . $size); + $this->addHeader('Connection', 'close'); + $this->addHeader('Content-Type', $data['mimetype']); + $this->addContentDispositionHeader(); + return $buffer; + } + } + + $this->addHeader('Content-Type', $data['mimetype']); + $this->addContentDispositionHeader(); + $this->addHeader('Content-Length', $size); + + return $data['content']; + } + + /** + * Send 416 if we can't satisfy the requested ranges + */ + protected function sendRangeNotSatisfiable($filesize){ + $this->setStatus(Http::STATUS_REQUEST_RANGE_NOT_SATISFIABLE); + $this->addHeader('Content-Range', 'bytes */' . $filesize); // Required in 416. + return ''; + } + + protected function addContentDispositionHeader(){ + $encodedName = rawurlencode(basename($this->path)); + $isIE = preg_match("/MSIE/", $this->request->server["HTTP_USER_AGENT"]); + if ($isIE){ + $this->addHeader( + 'Content-Disposition', + 'attachment; filename="' . $encodedName . '"' + ); + } else { + $this->addHeader( + 'Content-Disposition', + 'attachment; filename*=UTF-8\'\'' . $encodedName . '; filepath="' . $encodedName . '"' + ); + } + } +} |