diff options
author | Thomas Müller <thomas.mueller@tmit.eu> | 2015-10-06 11:47:43 +0200 |
---|---|---|
committer | Thomas Müller <thomas.mueller@tmit.eu> | 2015-10-06 11:47:43 +0200 |
commit | 319e61f0eabe02847c4dccdb9db86dc3181d7540 (patch) | |
tree | 2818ea74629585f5f77370c6397e57fa35211d4c | |
parent | d9ffb094793f8bfff2c4231e5bde65900f6224cd (diff) | |
parent | be46cd6737f7b4414d4583d0096d90b73929ce3d (diff) | |
download | nextcloud-server-319e61f0eabe02847c4dccdb9db86dc3181d7540.tar.gz nextcloud-server-319e61f0eabe02847c4dccdb9db86dc3181d7540.zip |
Merge pull request #19407 from owncloud/lock-zip-content
Lock zip content
-rw-r--r-- | lib/private/files.php | 207 | ||||
-rw-r--r-- | lib/private/streamer.php | 12 |
2 files changed, 135 insertions, 84 deletions
diff --git a/lib/private/files.php b/lib/private/files.php index 4862e1a7a5f..ad03904e036 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -35,7 +35,7 @@ * */ -use OC\Lock\NoopLockingProvider; +use OC\Files\View; use OC\Streamer; use OCP\Lock\ILockingProvider; @@ -58,10 +58,11 @@ class OC_Files { OC_Response::setContentDispositionHeader($name, 'attachment'); header('Content-Transfer-Encoding: binary'); OC_Response::disableCaching(); - $filesize = \OC\Files\Filesystem::filesize($filename); - header('Content-Type: '.\OC_Helper::getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename))); - if ($filesize > -1) { - OC_Response::setContentLengthHeader($filesize); + $fileSize = \OC\Files\Filesystem::filesize($filename); + $type = \OC::$server->getMimeTypeDetector()->getSecureMimeType(\OC\Files\Filesystem::getMimeType($filename)); + header('Content-Type: '.$type); + if ($fileSize > -1) { + OC_Response::setContentLengthHeader($fileSize); } } @@ -73,99 +74,75 @@ class OC_Files { * @param boolean $onlyHeader ; boolean to only send header of the request */ public static function get($dir, $files, $onlyHeader = false) { - $view = \OC\Files\Filesystem::getView(); - if (is_array($files) && count($files) === 1) { - $files = $files[0]; - } + $view = \OC\Files\Filesystem::getView(); + $getType = self::FILE; + $filename = $dir; + try { - if (is_array($files)) { - $getType = self::ZIP_FILES; - $basename = basename($dir); - if ($basename) { - $name = $basename; - } else { - $name = 'download'; + if (is_array($files) && count($files) === 1) { + $files = $files[0]; + $filename = $dir . '/' . $files; + if (!$view->is_dir($files)) { + self::getSingleFile($view, $dir, $files, $onlyHeader); + return; + } } - $filename = $dir . '/' . $name; - } else { - $filename = $dir . '/' . $files; - if (\OC\Files\Filesystem::is_dir($dir . '/' . $files)) { + $name = 'download'; + if (is_array($files)) { + $getType = self::ZIP_FILES; + $basename = basename($dir); + if ($basename) { + $name = $basename; + } + + $filename = $dir . '/' . $name; + } else { + $filename = $dir . '/' . $files; $getType = self::ZIP_DIR; // downloading root ? - if ($files === '') { - $name = 'download'; - } else { + if ($files !== '') { $name = $files; } - - } else { - $getType = self::FILE; - $name = $files; } - } - if ($getType === self::FILE) { - $streamer = false; - } else { $streamer = new Streamer(); - } - OC_Util::obEnd(); + OC_Util::obEnd(); - try { - if ($getType === self::FILE) { - $view->lockFile($filename, ILockingProvider::LOCK_SHARED); - } - - if ($streamer) { - $streamer->sendHeaders($name); - } elseif (\OC\Files\Filesystem::isReadable($filename)) { - self::sendHeaders($filename, $name); - } elseif (!\OC\Files\Filesystem::file_exists($filename)) { - header("HTTP/1.0 404 Not Found"); - $tmpl = new OC_Template('', '404', 'guest'); - $tmpl->printPage(); - exit(); - } else { - header("HTTP/1.0 403 Forbidden"); - die('403 Forbidden'); - } - if ($onlyHeader) { - return; - } - if ($streamer) { - $executionTime = intval(ini_get('max_execution_time')); - set_time_limit(0); - if ($getType === self::ZIP_FILES) { - foreach ($files as $file) { - $file = $dir . '/' . $file; - if (\OC\Files\Filesystem::is_file($file)) { - $fileSize = \OC\Files\Filesystem::filesize($file); - $fh = \OC\Files\Filesystem::fopen($file, 'r'); - $streamer->addFileFromStream($fh, basename($file), $fileSize); - fclose($fh); - } elseif (\OC\Files\Filesystem::is_dir($file)) { - $streamer->addDirRecursive($file); - } + self::lockFiles($view, $dir, $files); + + $streamer->sendHeaders($name); + $executionTime = intval(ini_get('max_execution_time')); + set_time_limit(0); + if ($getType === self::ZIP_FILES) { + foreach ($files as $file) { + $file = $dir . '/' . $file; + if (\OC\Files\Filesystem::is_file($file)) { + $fileSize = \OC\Files\Filesystem::filesize($file); + $fh = \OC\Files\Filesystem::fopen($file, 'r'); + $streamer->addFileFromStream($fh, basename($file), $fileSize); + fclose($fh); + } elseif (\OC\Files\Filesystem::is_dir($file)) { + $streamer->addDirRecursive($file); } - } elseif ($getType === self::ZIP_DIR) { - $file = $dir . '/' . $files; - $streamer->addDirRecursive($file); } - $streamer->finalize(); - set_time_limit($executionTime); - } else { - \OC\Files\Filesystem::readfile($filename); - } - if ($getType === self::FILE) { - $view->unlockFile($filename, ILockingProvider::LOCK_SHARED); + } elseif ($getType === self::ZIP_DIR) { + $file = $dir . '/' . $files; + $streamer->addDirRecursive($file); } + $streamer->finalize(); + set_time_limit($executionTime); + self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); } catch (\OCP\Lock\LockedException $ex) { + self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); + OC::$server->getLogger()->logException($ex); $l = \OC::$server->getL10N('core'); $hint = method_exists($ex, 'getHint') ? $ex->getHint() : ''; \OC_Template::printErrorPage($l->t('File is currently busy, please try again later'), $hint); } catch (\Exception $ex) { + self::unlockAllTheFiles($dir, $files, $getType, $view, $filename); + OC::$server->getLogger()->logException($ex); $l = \OC::$server->getL10N('core'); $hint = method_exists($ex, 'getHint') ? $ex->getHint() : ''; \OC_Template::printErrorPage($l->t('Can\'t read file'), $hint); @@ -173,6 +150,56 @@ class OC_Files { } /** + * @param View $view + * @param string $name + */ + private static function getSingleFile($view, $dir, $name, $onlyHeader) { + $filename = $dir . '/' . $name; + OC_Util::obEnd(); + $view->lockFile($filename, ILockingProvider::LOCK_SHARED); + + if (\OC\Files\Filesystem::isReadable($filename)) { + self::sendHeaders($filename, $name); + } elseif (!\OC\Files\Filesystem::file_exists($filename)) { + header("HTTP/1.0 404 Not Found"); + $tmpl = new OC_Template('', '404', 'guest'); + $tmpl->printPage(); + exit(); + } else { + header("HTTP/1.0 403 Forbidden"); + die('403 Forbidden'); + } + if ($onlyHeader) { + return; + } + $view->readfile($filename); + } + + /** + * @param View $view + * @param $dir + * @param string[]|string $files + */ + public static function lockFiles($view, $dir, $files) { + if (!is_array($files)) { + $file = $dir . '/' . $files; + $files = [$file]; + } + foreach ($files as $file) { + $file = $dir . '/' . $file; + $view->lockFile($file, ILockingProvider::LOCK_SHARED); + if ($view->is_dir($file)) { + $contents = $view->getDirectoryContent($file); + $contents = array_map(function($fileInfo) use ($file) { + /** @var \OCP\Files\FileInfo $fileInfo */ + return $file . '/' . $fileInfo->getName(); + }, $contents); + self::lockFiles($view, $dir, $contents); + } + } + } + + /** * set the maximum upload size limit for apache hosts using .htaccess * * @param int $size file size in bytes @@ -253,4 +280,28 @@ class OC_Files { } return false; } + + /** + * @param $dir + * @param $files + * @param $getType + * @param View $view + * @param $filename + */ + private static function unlockAllTheFiles($dir, $files, $getType, $view, $filename) { + if ($getType === self::FILE) { + $view->unlockFile($filename, ILockingProvider::LOCK_SHARED); + } + if ($getType === self::ZIP_FILES) { + foreach ($files as $file) { + $file = $dir . '/' . $file; + $view->unlockFile($file, ILockingProvider::LOCK_SHARED); + } + } + if ($getType === self::ZIP_DIR) { + $file = $dir . '/' . $files; + $view->unlockFile($file, ILockingProvider::LOCK_SHARED); + } + } + } diff --git a/lib/private/streamer.php b/lib/private/streamer.php index 383183f8119..6db6fe42a79 100644 --- a/lib/private/streamer.php +++ b/lib/private/streamer.php @@ -90,9 +90,9 @@ class Streamer { /** * Add a file to the archive at the specified location and file name. * - * @param string $stream Stream to read data from - * @param string $internalName Filepath and name to be used in the archive. - * @param int $size Filesize + * @param string $stream Stream to read data from + * @param string $internalName Filepath and name to be used in the archive. + * @param int $size Filesize * @return bool $success */ public function addFileFromStream($stream, $internalName, $size){ @@ -102,17 +102,17 @@ class Streamer { return $this->streamerInstance->addFileFromStream($stream, $internalName, $size); } } - + /** * Add an empty directory entry to the archive. * - * @param string $directoryPath Directory Path and name to be added to the archive. + * @param string $dirName Directory Path and name to be added to the archive. * @return bool $success */ public function addEmptyDir($dirName){ return $this->streamerInstance->addEmptyDir($dirName); } - + /** * Close the archive. * A closed archive can no longer have new files added to it. After |