From 57fae2637da2fa49602c5d014e4759bf3525f719 Mon Sep 17 00:00:00 2001 From: Victor Dubiniuk Date: Fri, 19 Jul 2013 18:52:33 +0300 Subject: [PATCH] Range download support --- ajax/genesis.php | 28 ++++-------------- appinfo/app.php | 4 ++- lib/download.php | 56 ++++++++++++++++++++++++++++++++++++ lib/download/range.php | 63 +++++++++++++++++++++++++++++++++++++++++ lib/download/simple.php | 31 ++++++++++++++++++++ 5 files changed, 158 insertions(+), 24 deletions(-) create mode 100644 lib/download.php create mode 100644 lib/download/range.php create mode 100644 lib/download/simple.php diff --git a/ajax/genesis.php b/ajax/genesis.php index b88ebe7f..0e15d1b3 100644 --- a/ajax/genesis.php +++ b/ajax/genesis.php @@ -12,30 +12,12 @@ // hardcoding the served file with /welcome.odt for now is enough to unblock development // (that saves all db work for now) +namespace OCA\Office; + // Check if we are a user -OCP\User::checkLoggedIn(); +\OCP\User::checkLoggedIn(); $filename = "/welcome.odt"; -if(!\OC\Files\Filesystem::file_exists($filename)) { - header("HTTP/1.0 404 Not Found"); - $tmpl = new OCP\Template( '', '404', 'guest' ); - $tmpl->assign('file', $filename); - $tmpl->printPage(); - exit; -} - -$ftype=\OC\Files\Filesystem::getMimeType( $filename ); - -header('Content-Type:'.$ftype); -if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) { - header( 'Content-Disposition: attachment; filename="' . rawurlencode( basename($filename) ) . '"' ); -} else { - header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode( basename($filename) ) - . '; filename="' . rawurlencode( basename($filename) ) . '"' ); -} -OCP\Response::disableCaching(); -header('Content-Length: '.\OC\Files\Filesystem::filesize($filename)); - -OC_Util::obEnd(); -\OC\Files\Filesystem::readfile( $filename ); +$download = new Download($filename); +$download->sendResponse(); \ No newline at end of file diff --git a/appinfo/app.php b/appinfo/app.php index 138748c7..a08e43c3 100755 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -33,4 +33,6 @@ OCP\App::addNavigationEntry(array( 'name' => 'Office') ); -OC::$CLASSPATH['OCA\Office\Storage'] = 'office/lib/storage.php'; \ No newline at end of file +OC::$CLASSPATH['OCA\Office\Storage'] = 'office/lib/storage.php'; +OC::$CLASSPATH['OCA\Office\Download\Simple'] = 'office/lib/download/simple.php'; +OC::$CLASSPATH['OCA\Office\Download\Range'] = 'office/lib/download/range.php'; \ No newline at end of file diff --git a/lib/download.php b/lib/download.php new file mode 100644 index 00000000..52ae41f9 --- /dev/null +++ b/lib/download.php @@ -0,0 +1,56 @@ +filepath = $filepath; + if (isset($_SERVER['HTTP_RANGE'])) { + $this->instance = new Download\Range($filepath); + } else { + $this->instance = new Download\Simple($filepath); + } + } + + public function sendResponse(){ + \OCP\Response::disableCaching(); + + if (!$this->fileExists()){ + $this->sendNotFound(); + } + + $this->instance->sendResponse(); + exit(); + } + + protected function getFilename(){ + return basename($this->filepath); + } + + protected function getFilesize(){ + return \OC\Files\Filesystem::filesize($this->filepath); + } + + protected function getMimeType(){ + return \OC\Files\Filesystem::getMimeType($this->filepath); + } + + protected function fileExists(){ + return \OC\Files\Filesystem::file_exists($this->filepath); + } + + 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 new file mode 100644 index 00000000..3992fd6d --- /dev/null +++ b/lib/download/range.php @@ -0,0 +1,63 @@ +filepath = $filepath; + } + + public function sendResponse(){ + if (!preg_match('/^bytes=\d*-\d*(,\d*-\d*)*$/', $_SERVER['HTTP_RANGE'])){ + $this->sendNotSatisfiable(); + } + $ranges = explode(',', substr($_SERVER['HTTP_RANGE'], 6)); + foreach ($ranges as $range){ + $parts = explode('-', $range); + if (isset($parts[0])){ + $start = $parts[0]; + } else { + $start = 0; + } + + if (isset($parts[1])){ + $end = $parts[1]; + } else { + $end = $this->getFilesize() - 1; + } + + if ($start > $end){ + $this->sendNotSatisfiable(); + } + + $handle = \OC\Files\Filesystem::fopen($this->filepath, 'r'); + \fseek($handle, $start); + $buffer = \fread($handle, $end - $start); + $md5Sum = md5($buffer); + \fclose($handle); + // send the headers and data + header("Content-Length: " . $end - $start); + header("Content-md5: " . $md5Sum); + header("Accept-Ranges: bytes"); + header('Content-Range: bytes ' . $start . '-' . ($end) . '/' . $this->getFilesize()); + header("Connection: close"); + header("Content-type: " . $this->getMimeType()); + header('Content-Disposition: attachment; filename=' . $this->getFilename()); + echo $buffer; + flush(); + } + } + + 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 new file mode 100644 index 00000000..6e5a0ea3 --- /dev/null +++ b/lib/download/simple.php @@ -0,0 +1,31 @@ +filepath = $filepath; + } + + public function sendResponse(){ + header( 'Content-Type:' . $this->getMimeType() ); + + $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: ' . \OC\Files\Filesystem::filesize($this->filepath)); + + \OC_Util::obEnd(); + \OC\Files\Filesystem::readfile($this->filepath); + exit(); + } + +}