Merge pull request #18488 from nextcloud/backport/18433/stable17

[stable17] Use File Node API for more download cases, skip unreadable files
This commit is contained in:
Roeland Jago Douma 2019-12-23 15:25:12 +01:00 committed by GitHub
commit 4f8589c894
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 33 deletions

View file

@ -24,6 +24,12 @@
namespace OC; namespace OC;
use OC\Files\Filesystem;
use OCP\Files\File;
use OCP\Files\Folder;
use OCP\Files\InvalidPathException;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\IRequest; use OCP\IRequest;
use ownCloud\TarStreamer\TarStreamer; use ownCloud\TarStreamer\TarStreamer;
use ZipStreamer\ZipStreamer; use ZipStreamer\ZipStreamer;
@ -88,10 +94,12 @@ class Streamer {
/** /**
* Stream directory recursively * Stream directory recursively
* @param string $dir *
* @param string $internalDir * @throws NotFoundException
* @throws NotPermittedException
* @throws InvalidPathException
*/ */
public function addDirRecursive($dir, $internalDir='') { public function addDirRecursive(string $dir, string $internalDir = ''): void {
$dirname = basename($dir); $dirname = basename($dir);
$rootDir = $internalDir . $dirname; $rootDir = $internalDir . $dirname;
if (!empty($rootDir)) { if (!empty($rootDir)) {
@ -101,18 +109,29 @@ class Streamer {
// prevent absolute dirs // prevent absolute dirs
$internalDir = ltrim($internalDir, '/'); $internalDir = ltrim($internalDir, '/');
$files= \OC\Files\Filesystem::getDirectoryContent($dir); $userFolder = \OC::$server->getRootFolder()->get(Filesystem::getRoot());
/** @var Folder $dirNode */
$dirNode = $userFolder->get($dir);
$files = $dirNode->getDirectoryListing();
foreach($files as $file) { foreach($files as $file) {
$filename = $file['name']; if($file instanceof File) {
$file = $dir . '/' . $filename; try {
if(\OC\Files\Filesystem::is_file($file)) { $fh = $file->fopen('r');
$filesize = \OC\Files\Filesystem::filesize($file); } catch (NotPermittedException $e) {
$fileTime = \OC\Files\Filesystem::filemtime($file); continue;
$fh = \OC\Files\Filesystem::fopen($file, 'r'); }
$this->addFileFromStream($fh, $internalDir . $filename, $filesize, $fileTime); $this->addFileFromStream(
$fh,
$internalDir . $file->getName(),
$file->getSize(),
$file->getMTime()
);
fclose($fh); fclose($fh);
}elseif(\OC\Files\Filesystem::is_dir($file)) { } elseif ($file instanceof Folder) {
$this->addDirRecursive($file, $internalDir); if($file->isReadable()) {
$this->addDirRecursive($dir . '/' . $file->getName(), $internalDir);
}
} }
} }
} }

View file

@ -180,7 +180,11 @@ class OC_Files {
$userFolder = \OC::$server->getRootFolder()->get(\OC\Files\Filesystem::getRoot()); $userFolder = \OC::$server->getRootFolder()->get(\OC\Files\Filesystem::getRoot());
$file = $userFolder->get($file); $file = $userFolder->get($file);
if($file instanceof \OC\Files\Node\File) { if($file instanceof \OC\Files\Node\File) {
try {
$fh = $file->fopen('r'); $fh = $file->fopen('r');
} catch (\OCP\Files\NotPermittedException $e) {
continue;
}
$fileSize = $file->getSize(); $fileSize = $file->getSize();
$fileTime = $file->getMTime(); $fileTime = $file->getMTime();
} else { } else {
@ -284,30 +288,44 @@ class OC_Files {
*/ */
private static function getSingleFile($view, $dir, $name, $params) { private static function getSingleFile($view, $dir, $name, $params) {
$filename = $dir . '/' . $name; $filename = $dir . '/' . $name;
$file = null;
try {
$userFolder = \OC::$server->getRootFolder()->get(\OC\Files\Filesystem::getRoot());
$file = $userFolder->get($filename);
if(!$file instanceof \OC\Files\Node\File || !$file->isReadable()) {
http_response_code(403);
die('403 Forbidden');
}
$fileSize = $file->getSize();
} catch (\OCP\Files\NotPermittedException $e) {
http_response_code(403);
die('403 Forbidden');
} catch (\OCP\Files\InvalidPathException $e) {
http_response_code(403);
die('403 Forbidden');
} catch (\OCP\Files\NotFoundException $e) {
http_response_code(404);
$tmpl = new OC_Template('', '404', 'guest');
$tmpl->printPage();
exit();
}
OC_Util::obEnd(); OC_Util::obEnd();
$view->lockFile($filename, ILockingProvider::LOCK_SHARED); $view->lockFile($filename, ILockingProvider::LOCK_SHARED);
$rangeArray = array(); $rangeArray = array();
if (isset($params['range']) && substr($params['range'], 0, 6) === 'bytes=') { if (isset($params['range']) && substr($params['range'], 0, 6) === 'bytes=') {
$rangeArray = self::parseHttpRangeHeader(substr($params['range'], 6), $rangeArray = self::parseHttpRangeHeader(substr($params['range'], 6), $fileSize);
\OC\Files\Filesystem::filesize($filename));
} }
if (\OC\Files\Filesystem::isReadable($filename)) {
self::sendHeaders($filename, $name, $rangeArray); self::sendHeaders($filename, $name, $rangeArray);
} elseif (!\OC\Files\Filesystem::file_exists($filename)) {
http_response_code(404);
$tmpl = new OC_Template('', '404', 'guest');
$tmpl->printPage();
exit();
} else {
http_response_code(403);
die('403 Forbidden');
}
if (isset($params['head']) && $params['head']) { if (isset($params['head']) && $params['head']) {
return; return;
} }
if (!empty($rangeArray)) { if (!empty($rangeArray)) {
try { try {
if (count($rangeArray) == 1) { if (count($rangeArray) == 1) {