userId = $userSession->getUser()->getUID(); } /** * This initializes the plugin. * * This function is called by \Sabre\DAV\Server, after * addPlugin is called. * * This method should set up the required event subscriptions. * * @return void */ public function initialize(Server $server) { $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc'; $server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = ShareTypeList::class; $server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME; $server->protectedProperties[] = self::SHAREES_PROPERTYNAME; $this->server = $server; $this->server->on('propFind', [$this, 'handleGetProperties']); } /** * @param Node $node * @return IShare[] */ private function getShare(Node $node): array { $result = []; $requestedShareTypes = [ IShare::TYPE_USER, IShare::TYPE_GROUP, IShare::TYPE_LINK, IShare::TYPE_REMOTE, IShare::TYPE_EMAIL, IShare::TYPE_ROOM, IShare::TYPE_CIRCLE, IShare::TYPE_DECK, IShare::TYPE_SCIENCEMESH, ]; foreach ($requestedShareTypes as $requestedShareType) { $result = array_merge($result, $this->shareManager->getSharesBy( $this->userId, $requestedShareType, $node, false, -1 )); // Also check for shares where the user is the recipient try { $result = array_merge($result, $this->shareManager->getSharedWith( $this->userId, $requestedShareType, $node, -1 )); } catch (BackendError $e) { // ignore } } return $result; } /** * @param Folder $node * @return IShare[][] */ private function getSharesFolder(Folder $node): array { return $this->shareManager->getSharesInFolder( $this->userId, $node, true ); } /** * @param DavNode $sabreNode * @return IShare[] */ private function getShares(DavNode $sabreNode): array { if (isset($this->cachedShares[$sabreNode->getId()])) { return $this->cachedShares[$sabreNode->getId()]; } [$parentPath,] = \Sabre\Uri\split($sabreNode->getPath()); if ($parentPath === '') { $parentPath = '/'; } // if we already cached the folder containing this file // then we already know there are no shares here. if (array_search($parentPath, $this->cachedFolders) === false) { try { $node = $sabreNode->getNode(); } catch (NotFoundException $e) { return []; } $shares = $this->getShare($node); $this->cachedShares[$sabreNode->getId()] = $shares; return $shares; } return []; } /** * Adds shares to propfind response * * @param PropFind $propFind propfind object * @param \Sabre\DAV\INode $sabreNode sabre node */ public function handleGetProperties( PropFind $propFind, \Sabre\DAV\INode $sabreNode, ) { if (!($sabreNode instanceof DavNode)) { return; } // If the node is a directory and we are requesting share types or sharees // then we get all the shares in the folder and cache them. // This is more performant than iterating each files afterwards. if ($sabreNode instanceof Directory && $propFind->getDepth() !== 0 && ( !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) || !is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME)) ) ) { $folderNode = $sabreNode->getNode(); $this->cachedFolders[] = $sabreNode->getPath(); $childShares = $this->getSharesFolder($folderNode); foreach ($childShares as $id => $shares) { $this->cachedShares[$id] = $shares; } } $propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode): ShareTypeList { $shares = $this->getShares($sabreNode); $shareTypes = array_unique(array_map(function (IShare $share) { return $share->getShareType(); }, $shares)); return new ShareTypeList($shareTypes); }); $propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode): ShareeList { $shares = $this->getShares($sabreNode); return new ShareeList($shares); }); } }