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:
commit
4f8589c894
2 changed files with 70 additions and 33 deletions
|
@ -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;
|
||||||
|
@ -75,23 +81,25 @@ class Streamer {
|
||||||
$this->streamerInstance = new ZipStreamer(['zip64' => PHP_INT_SIZE !== 4]);
|
$this->streamerInstance = new ZipStreamer(['zip64' => PHP_INT_SIZE !== 4]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send HTTP headers
|
* Send HTTP headers
|
||||||
* @param string $name
|
* @param string $name
|
||||||
*/
|
*/
|
||||||
public function sendHeaders($name){
|
public function sendHeaders($name){
|
||||||
$extension = $this->streamerInstance instanceof ZipStreamer ? '.zip' : '.tar';
|
$extension = $this->streamerInstance instanceof ZipStreamer ? '.zip' : '.tar';
|
||||||
$fullName = $name . $extension;
|
$fullName = $name . $extension;
|
||||||
$this->streamerInstance->sendHeaders($fullName);
|
$this->streamerInstance->sendHeaders($fullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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,22 +109,33 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a file to the archive at the specified location and file name.
|
* Add a file to the archive at the specified location and file name.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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) {
|
||||||
$fh = $file->fopen('r');
|
try {
|
||||||
|
$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;
|
||||||
OC_Util::obEnd();
|
$file = null;
|
||||||
$view->lockFile($filename, ILockingProvider::LOCK_SHARED);
|
|
||||||
|
|
||||||
$rangeArray = array();
|
|
||||||
|
|
||||||
if (isset($params['range']) && substr($params['range'], 0, 6) === 'bytes=') {
|
try {
|
||||||
$rangeArray = self::parseHttpRangeHeader(substr($params['range'], 6),
|
$userFolder = \OC::$server->getRootFolder()->get(\OC\Files\Filesystem::getRoot());
|
||||||
\OC\Files\Filesystem::filesize($filename));
|
$file = $userFolder->get($filename);
|
||||||
}
|
if(!$file instanceof \OC\Files\Node\File || !$file->isReadable()) {
|
||||||
|
http_response_code(403);
|
||||||
if (\OC\Files\Filesystem::isReadable($filename)) {
|
die('403 Forbidden');
|
||||||
self::sendHeaders($filename, $name, $rangeArray);
|
}
|
||||||
} elseif (!\OC\Files\Filesystem::file_exists($filename)) {
|
$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);
|
http_response_code(404);
|
||||||
$tmpl = new OC_Template('', '404', 'guest');
|
$tmpl = new OC_Template('', '404', 'guest');
|
||||||
$tmpl->printPage();
|
$tmpl->printPage();
|
||||||
exit();
|
exit();
|
||||||
} else {
|
|
||||||
http_response_code(403);
|
|
||||||
die('403 Forbidden');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OC_Util::obEnd();
|
||||||
|
$view->lockFile($filename, ILockingProvider::LOCK_SHARED);
|
||||||
|
|
||||||
|
$rangeArray = array();
|
||||||
|
|
||||||
|
if (isset($params['range']) && substr($params['range'], 0, 6) === 'bytes=') {
|
||||||
|
$rangeArray = self::parseHttpRangeHeader(substr($params['range'], 6), $fileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::sendHeaders($filename, $name, $rangeArray);
|
||||||
|
|
||||||
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) {
|
||||||
|
|
Loading…
Reference in a new issue