server = $server; //priority 90 to make sure the plugin is called before //Sabre\DAV\CorePlugin::httpGet $this->server->on('method:GET', [$this, 'checkViewOnly'], 90); $this->server->on('method:COPY', [$this, 'checkViewOnly'], 90); $this->server->on('method:MOVE', [$this, 'checkViewOnly'], 90); } /** * Disallow download via DAV Api in case file being received share * and having special permission * * @throws Forbidden * @throws NotFoundException */ public function checkViewOnly(RequestInterface $request): bool { $path = $request->getPath(); try { assert($this->server !== null); $davNode = $this->server->tree->getNodeForPath($path); if ($davNode instanceof DavFile) { // Restrict view-only to nodes which are shared $node = $davNode->getNode(); } elseif ($davNode instanceof VersionFile) { $node = $davNode->getVersion()->getSourceFile(); $currentUserId = $this->userFolder?->getOwner()?->getUID(); // The version source file is relative to the owner storage. // But we need the node from the current user perspective. if ($node->getOwner()->getUID() !== $currentUserId) { $nodes = $this->userFolder->getById($node->getId()); $node = array_pop($nodes); if (!$node) { throw new NotFoundException('Version file not accessible by current user'); } } } else { return true; } $storage = $node->getStorage(); if (!$storage->instanceOfStorage(ISharedStorage::class)) { return true; } // Extract extra permissions /** @var ISharedStorage $storage */ $share = $storage->getShare(); $attributes = $share->getAttributes(); if ($attributes === null) { return true; } // Check if read-only and on whether permission can download is both set and disabled. $canDownload = $attributes->getAttribute('permissions', 'download'); if ($canDownload !== null && !$canDownload) { throw new Forbidden('Access to this shared resource has been denied because its download permission is disabled.'); } } catch (NotFound $e) { // File not found } return true; } }