Skip to content

Commit 84741d9

Browse files
committed
fix: add INodeByPath to Directory [wip]
Signed-off-by: Salvatore Martire <[email protected]>
1 parent e89a8d8 commit 84741d9

File tree

1 file changed

+88
-2
lines changed

1 file changed

+88
-2
lines changed

apps/dav/lib/Connector/Sabre/Directory.php

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace OCA\DAV\Connector\Sabre;
99

1010
use OC\Files\Mount\MoveableMount;
11+
use OC\Files\Utils\PathHelper;
1112
use OC\Files\View;
1213
use OCA\DAV\AppInfo\Application;
1314
use OCA\DAV\Connector\Sabre\Exception\FileLocked;
@@ -38,8 +39,14 @@
3839
use Sabre\DAV\Exception\ServiceUnavailable;
3940
use Sabre\DAV\IFile;
4041
use Sabre\DAV\INode;
41-
42-
class Directory extends Node implements \Sabre\DAV\ICollection, \Sabre\DAV\IQuota, \Sabre\DAV\IMoveTarget, \Sabre\DAV\ICopyTarget {
42+
use Sabre\DAV\INodeByPath;
43+
44+
class Directory extends Node implements
45+
\Sabre\DAV\ICollection,
46+
\Sabre\DAV\IQuota,
47+
\Sabre\DAV\IMoveTarget,
48+
\Sabre\DAV\ICopyTarget,
49+
INodeByPath {
4350
/**
4451
* Cached directory content
4552
* @var FileInfo[]
@@ -490,4 +497,83 @@ public function copyInto($targetName, $sourcePath, INode $sourceNode) {
490497
public function getNode(): Folder {
491498
return $this->node;
492499
}
500+
501+
public function getNodeForPath($path): INode {
502+
$storage = $this->info->getStorage();
503+
$allowDirectory = false;
504+
505+
// Checking if we're in a file drop
506+
// If we are, then only PUT and MKCOL are allowed (see plugin)
507+
// so we are safe to return the directory without a risk of
508+
// leaking files and folders structure.
509+
if ($storage->instanceOfStorage(PublicShareWrapper::class)) {
510+
$share = $storage->getShare();
511+
$allowDirectory = ($share->getPermissions() & Constants::PERMISSION_READ) !== Constants::PERMISSION_READ;
512+
}
513+
514+
// For file drop we need to be allowed to read the directory with the nickname
515+
if (!$allowDirectory && !$this->info->isReadable()) {
516+
// avoid detecting files through this way
517+
throw new NotFound();
518+
}
519+
520+
$destinationPath = $this->getPath() . '/' . $path;
521+
$destinationDir = $this->getPath();
522+
$destinationName = basename($destinationPath);
523+
524+
try {
525+
$this->fileView->verifyPath($destinationDir, $destinationName, true);
526+
$info = $this->fileView->getFileInfo($destinationPath);
527+
} catch (StorageNotAvailableException $e) {
528+
throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage(), 0, $e);
529+
} catch (InvalidPathException $ex) {
530+
throw new InvalidPath($ex->getMessage(), false, $ex);
531+
} catch (ForbiddenException $e) {
532+
throw new \Sabre\DAV\Exception\Forbidden($e->getMessage(), $e->getCode(), $e);
533+
}
534+
535+
if (!$info) {
536+
throw new \Sabre\DAV\Exception\NotFound('File with name ' . $fullPath
537+
. ' could not be located');
538+
}
539+
540+
// if not in a public share with no read permissions, throw Forbidden
541+
if (!$allowDirectory && !$info->isReadable()) {
542+
if (Server::get(IAppManager::class)->isEnabledForAnyone('files_accesscontrol')) {
543+
throw new Forbidden('No read permissions. This might be caused by files_accesscontrol, check your configured rules');
544+
}
545+
546+
throw new Forbidden('No read permissions');
547+
}
548+
549+
if ($info->getMimeType() === FileInfo::MIMETYPE_FOLDER) {
550+
$node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this->tree, $this->shareManager);
551+
} else {
552+
// In case reading a directory was allowed but it turns out the node was a not a directory, reject it now.
553+
if (!$this->info->isReadable()) {
554+
throw new NotFound();
555+
}
556+
557+
$node = new File($this->fileView, $info, $this->shareManager);
558+
}
559+
$this->tree?->cacheNode($node);
560+
561+
// recurse upwards until the root (for backwards-compatibility)
562+
// no need to get child information
563+
if ($destinationDir !== '') {
564+
/** @var Folder $scanNode */
565+
$scanNode = $node->getNode();
566+
$scanPath = $destinationName;
567+
while ($parent = $scanNode->getParent()) {
568+
$parent->get($scanPath);
569+
$scanPath = $parent->getName();
570+
if ($scanPath === '') {
571+
break;
572+
}
573+
$scanNode = $parent;
574+
}
575+
}
576+
577+
return $node;
578+
}
493579
}

0 commit comments

Comments
 (0)