Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/dav/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@
'OCA\\DAV\\Connector\\Sabre\\Server' => $baseDir . '/../lib/Connector/Sabre/Server.php',
'OCA\\DAV\\Connector\\Sabre\\ServerFactory' => $baseDir . '/../lib/Connector/Sabre/ServerFactory.php',
'OCA\\DAV\\Connector\\Sabre\\ShareTypeList' => $baseDir . '/../lib/Connector/Sabre/ShareTypeList.php',
'OCA\\DAV\\Connector\\Sabre\\ShareeList' => $baseDir . '/../lib/Connector/Sabre/ShareeList.php',
'OCA\\DAV\\Connector\\Sabre\\SharesPlugin' => $baseDir . '/../lib/Connector/Sabre/SharesPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\StreamedPropFindNotFoundPlugin' => $baseDir . '/../lib/Connector/Sabre/StreamedPropFindNotFoundPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\TagList' => $baseDir . '/../lib/Connector/Sabre/TagList.php',
Expand Down Expand Up @@ -347,6 +346,9 @@
'OCA\\DAV\\Files\\LazySearchBackend' => $baseDir . '/../lib/Files/LazySearchBackend.php',
'OCA\\DAV\\Files\\NodeAttributes\\FavoriteProvider' => $baseDir . '/../lib/Files/NodeAttributes/FavoriteProvider.php',
'OCA\\DAV\\Files\\NodeAttributes\\HasPreviewProvider' => $baseDir . '/../lib/Files/NodeAttributes/HasPreviewProvider.php',
'OCA\\DAV\\Files\\NodeAttributes\\IFolderListingPreload' => $baseDir . '/../lib/Files/NodeAttributes/IFolderListingPreload.php',
'OCA\\DAV\\Files\\NodeAttributes\\ShareAttributesProvider' => $baseDir . '/../lib/Files/NodeAttributes/ShareAttributesProvider.php',
'OCA\\DAV\\Files\\NodeAttributes\\SharesProvider' => $baseDir . '/../lib/Files/NodeAttributes/SharesProvider.php',
'OCA\\DAV\\Files\\RootCollection' => $baseDir . '/../lib/Files/RootCollection.php',
'OCA\\DAV\\Files\\Sharing\\FilesDropPlugin' => $baseDir . '/../lib/Files/Sharing/FilesDropPlugin.php',
'OCA\\DAV\\Files\\Sharing\\PublicLinkCheckPlugin' => $baseDir . '/../lib/Files/Sharing/PublicLinkCheckPlugin.php',
Expand Down
4 changes: 3 additions & 1 deletion apps/dav/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,6 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Connector\\Sabre\\Server' => __DIR__ . '/..' . '/../lib/Connector/Sabre/Server.php',
'OCA\\DAV\\Connector\\Sabre\\ServerFactory' => __DIR__ . '/..' . '/../lib/Connector/Sabre/ServerFactory.php',
'OCA\\DAV\\Connector\\Sabre\\ShareTypeList' => __DIR__ . '/..' . '/../lib/Connector/Sabre/ShareTypeList.php',
'OCA\\DAV\\Connector\\Sabre\\ShareeList' => __DIR__ . '/..' . '/../lib/Connector/Sabre/ShareeList.php',
'OCA\\DAV\\Connector\\Sabre\\SharesPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/SharesPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\StreamedPropFindNotFoundPlugin' => __DIR__ . '/..' . '/../lib/Connector/Sabre/StreamedPropFindNotFoundPlugin.php',
'OCA\\DAV\\Connector\\Sabre\\TagList' => __DIR__ . '/..' . '/../lib/Connector/Sabre/TagList.php',
Expand Down Expand Up @@ -362,6 +361,9 @@ class ComposerStaticInitDAV
'OCA\\DAV\\Files\\LazySearchBackend' => __DIR__ . '/..' . '/../lib/Files/LazySearchBackend.php',
'OCA\\DAV\\Files\\NodeAttributes\\FavoriteProvider' => __DIR__ . '/..' . '/../lib/Files/NodeAttributes/FavoriteProvider.php',
'OCA\\DAV\\Files\\NodeAttributes\\HasPreviewProvider' => __DIR__ . '/..' . '/../lib/Files/NodeAttributes/HasPreviewProvider.php',
'OCA\\DAV\\Files\\NodeAttributes\\IFolderListingPreload' => __DIR__ . '/..' . '/../lib/Files/NodeAttributes/IFolderListingPreload.php',
'OCA\\DAV\\Files\\NodeAttributes\\ShareAttributesProvider' => __DIR__ . '/..' . '/../lib/Files/NodeAttributes/ShareAttributesProvider.php',
'OCA\\DAV\\Files\\NodeAttributes\\SharesProvider' => __DIR__ . '/..' . '/../lib/Files/NodeAttributes/SharesProvider.php',
'OCA\\DAV\\Files\\RootCollection' => __DIR__ . '/..' . '/../lib/Files/RootCollection.php',
'OCA\\DAV\\Files\\Sharing\\FilesDropPlugin' => __DIR__ . '/..' . '/../lib/Files/Sharing/FilesDropPlugin.php',
'OCA\\DAV\\Files\\Sharing\\PublicLinkCheckPlugin' => __DIR__ . '/..' . '/../lib/Files/Sharing/PublicLinkCheckPlugin.php',
Expand Down
5 changes: 5 additions & 0 deletions apps/dav/lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use OCA\DAV\CardDAV\SyncService;
use OCA\DAV\ConfigLexicon;
use OCA\DAV\Connector\Sabre\FilesPlugin;
use OCA\DAV\Connector\Sabre\SharesPlugin;
use OCA\DAV\Connector\Sabre\TagsPlugin;
use OCA\DAV\Events\AddressBookCreatedEvent;
use OCA\DAV\Events\AddressBookDeletedEvent;
Expand All @@ -51,6 +52,8 @@
use OCA\DAV\Events\SubscriptionDeletedEvent;
use OCA\DAV\Files\NodeAttributes\FavoriteProvider;
use OCA\DAV\Files\NodeAttributes\HasPreviewProvider;
use OCA\DAV\Files\NodeAttributes\ShareAttributesProvider;
use OCA\DAV\Files\NodeAttributes\SharesProvider;
use OCA\DAV\Listener\ActivityUpdaterListener;
use OCA\DAV\Listener\AddMissingIndicesListener;
use OCA\DAV\Listener\AddressbookListener;
Expand Down Expand Up @@ -134,6 +137,8 @@ public function register(IRegistrationContext $context): void {
$context->registerServiceAlias('CardDAVSyncService', SyncService::class);
$context->registerNodeAttributeProvider(HasPreviewProvider::class, [FilesPlugin::HAS_PREVIEW_PROPERTYNAME]);
$context->registerNodeAttributeProvider(FavoriteProvider::class, [TagsPlugin::FAVORITE_PROPERTYNAME]);
$context->registerNodeAttributeProvider(SharesProvider::class, [SharesPlugin::SHARETYPES_PROPERTYNAME, SharesPlugin::SHAREES_PROPERTYNAME]);
$context->registerNodeAttributeProvider(ShareAttributesProvider::class, [FilesPlugin::SHARE_ATTRIBUTES_PROPERTYNAME]);
$context->registerService(AppCalendarPlugin::class, function (ContainerInterface $c) {
return new AppCalendarPlugin(
$c->get(ICalendarManager::class),
Expand Down
4 changes: 0 additions & 4 deletions apps/dav/lib/Connector/Sabre/FilesPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -346,10 +346,6 @@ public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node)
return json_encode($ocmPermissions, JSON_THROW_ON_ERROR);
});

$propFind->handle(self::SHARE_ATTRIBUTES_PROPERTYNAME, function () use ($node, $httpRequest) {
return json_encode($node->getShareAttributes(), JSON_THROW_ON_ERROR);
});

$propFind->handle(self::GETETAG_PROPERTYNAME, function () use ($node): string {
return $node->getETag();
});
Expand Down
21 changes: 0 additions & 21 deletions apps/dav/lib/Connector/Sabre/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
use OCP\PreConditionNotMetException;
use OCP\Server;
use OCP\Share\Exceptions\ShareNotFound;
use OCP\Share\IAttributes;
use OCP\Share\IManager;
use RuntimeException;
use Sabre\DAV\Exception;
Expand Down Expand Up @@ -289,26 +288,6 @@ public function getSharePermissions(?string $user): int {
return $permissions;
}

public function getShareAttributes(): array {
try {
$storage = $this->node->getStorage();
} catch (NotFoundException) {
return [];
}

$attributes = [];
if ($storage->instanceOfStorage(ISharedStorage::class)) {
$attributes = $storage->getShare()->getAttributes();
if (!$attributes instanceof IAttributes) {
return [];
}

return $attributes->toArray();
}

return $attributes;
}

public function getNoteFromShare(?string $user): ?string {
try {
$storage = $this->node->getStorage();
Expand Down
18 changes: 16 additions & 2 deletions apps/dav/lib/Connector/Sabre/NodeAttributeListXml.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
class NodeAttributeListXml implements XmlSerializable {
/**
* @param string $childElement child element name in Clark notation
* @param list<bool|int|float|string> $values
* @param list<bool|int|float|string|array<string, bool|int|float|string|null>> $values
*/
public function __construct(
private readonly string $childElement,
Expand All @@ -28,8 +28,22 @@ public function __construct(

#[\Override]
public function xmlSerialize(Writer $writer): void {
$namespace = substr($this->childElement, 0, (int)strrpos($this->childElement, '}') + 1);
foreach ($this->values as $value) {
$writer->writeElement($this->childElement, is_bool($value) ? ($value ? 'true' : 'false') : (string)$value);
if (!is_array($value)) {
$writer->writeElement($this->childElement, self::toText($value));
continue;
}

$writer->startElement($this->childElement);
foreach ($value as $field => $fieldValue) {
$writer->writeElement($namespace . $field, $fieldValue === null ? null : self::toText($fieldValue));
}
$writer->endElement();
}
}

private static function toText(bool|int|float|string $value): string {
return is_bool($value) ? ($value ? 'true' : 'false') : (string)$value;
}
}
18 changes: 13 additions & 5 deletions apps/dav/lib/Connector/Sabre/NodeAttributesPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
use NCU\Files\NodeAttributes\NodeAttributeContext;
use NCU\Files\NodeAttributes\NodeAttributeList;
use OC\Files\NodeAttributes\NodeAttributeRegistry;
use OCA\DAV\Files\NodeAttributes\IFolderListingPreload;
use OCP\Files\Folder;
use Sabre\DAV\ICollection;
use Sabre\DAV\INode;
use Sabre\DAV\PropFind;
Expand Down Expand Up @@ -52,13 +54,14 @@ private function preloadCollection(PropFind $propFind, ICollection $collection):
return;
}

$nodes = [$collection->getNode()];
$folder = $collection->getNode();
$children = [];
foreach ($collection->getChildren() as $child) {
if ($child instanceof Node) {
$nodes[] = $child->getNode();
$children[] = $child->getNode();
}
}
$this->preload($nodes, $attributes);
$this->preload([$folder, ...$children], $attributes, $folder);
}

/**
Expand Down Expand Up @@ -122,15 +125,20 @@ private function getRequestedAttributes(PropFind $propFind): array {
/**
* @param list<\OCP\Files\Node> $nodes
* @param list<string> $attributes
* @param ?Folder $listing the folder when the nodes are the folder followed by its children
*/
private function preload(array $nodes, array $attributes): void {
private function preload(array $nodes, array $attributes, ?Folder $listing = null): void {
$context = ($this->contextResolver)();
if ($context === null || $nodes === []) {
return;
}

foreach ($this->registry->getProvidersFor($attributes) as $group) {
$group['provider']->preload($context, $nodes, $group['attributes']);
if ($listing !== null && $group['provider'] instanceof IFolderListingPreload) {
$group['provider']->preloadListing($context, $listing, array_slice($nodes, 1), $group['attributes']);
} else {
$group['provider']->preload($context, $nodes, $group['attributes']);
}
}
foreach ($nodes as $node) {
$this->preloaded[$node->getId()] = true;
Expand Down
44 changes: 0 additions & 44 deletions apps/dav/lib/Connector/Sabre/ShareeList.php

This file was deleted.

113 changes: 2 additions & 111 deletions apps/dav/lib/Connector/Sabre/SharesPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,20 @@
use OC\Share20\Exception\BackendError;
use OCA\DAV\Connector\Sabre\Exception\Forbidden;
use OCA\DAV\Connector\Sabre\Node as DavNode;
use OCP\Files\Folder;
use OCP\Files\IRootFolder;
use OCP\Files\Mount\IShareOwnerlessMount;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\Files\Storage\ISharedStorage;
use OCP\IUserSession;
use OCP\Share\IManager;
use OCP\Share\IShare;
use Sabre\DAV\Exception\NotFound;
use Sabre\DAV\ICollection;
use Sabre\DAV\PropFind;
use Sabre\DAV\Server;
use Sabre\DAV\Tree;

/**
* Sabre Plugin to provide share-related properties
* Sabre Plugin to keep moves and copies from adding nodes to shares the user cannot reshare.
* The share-types and sharees properties are node attributes, served by SharesProvider
*/
class SharesPlugin extends \Sabre\DAV\ServerPlugin {
public const NS_OWNCLOUD = 'http://owncloud.org/ns';
Expand All @@ -38,18 +35,6 @@
private \Sabre\DAV\Server $server;
private string $userId;

/** @var IShare[][] */
private array $cachedShares = [];

/**
* Tracks which folders have been cached.
* When a folder is cached, it will appear with its path as key and true
* as value.
*
* @var bool[]
*/
private array $cachedFolders = [];

public function __construct(
private Tree $tree,
IUserSession $userSession,
Expand Down Expand Up @@ -77,8 +62,6 @@
$server->protectedProperties[] = self::SHAREES_PROPERTYNAME;

$this->server = $server;
$this->server->on('preloadCollection', $this->preloadCollection(...));
$this->server->on('propFind', $this->handleGetProperties(...));
$this->server->on('beforeCopy', $this->validateMoveOrCopy(...));
$this->server->on('beforeMove', $this->validateMoveOrCopy(...));
}
Expand Down Expand Up @@ -149,98 +132,6 @@
return array_merge($shares, ...$outgoingAncestorShares);
}

/**
* @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 (!isset($this->cachedFolders[$parentPath])) {
try {
$node = $sabreNode->getNode();
} catch (NotFoundException $e) {
return [];
}

$shares = $this->getShare($node);
$this->cachedShares[$sabreNode->getId()] = $shares;
return $shares;
}

return [];
}

private function preloadCollection(PropFind $propFind, ICollection $collection): void {
if (!$collection instanceof Directory
|| isset($this->cachedFolders[$collection->getPath()])
|| (
$propFind->getStatus(self::SHARETYPES_PROPERTYNAME) === null
&& $propFind->getStatus(self::SHAREES_PROPERTYNAME) === null
)
) {
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.
$folderNode = $collection->getNode();
$this->cachedFolders[$collection->getPath()] = true;
foreach ($this->getSharesFolder($folderNode) as $id => $shares) {
$this->cachedShares[$id] = $shares;
}
}

/**
* 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;
}

$propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode): ShareTypeList {
$shares = $this->getShares($sabreNode);
$shareTypes = array_unique(array_map(static fn (IShare $share): int => $share->getShareType(), $shares));

return new ShareTypeList($shareTypes);
});

$propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode): ShareeList {
$shares = $this->getShares($sabreNode);

return new ShareeList($shares);
});
}

/**
* Ensure that when copying or moving a node it is not transferred from one share to another,
* if the user is neither the owner nor has re-share permissions.
Expand Down Expand Up @@ -276,7 +167,7 @@
if (!$sourceIsShare && $sourceNode->getMountPoint() instanceof IShareOwnerlessMount) {
// we use the parent because we already know the source is not a share
$sourceParent = $sourceNode->getParent();
if (!$this->operationAddsShares($sourceParent, $targetNode->getNode())) {

Check failure on line 170 in apps/dav/lib/Connector/Sabre/SharesPlugin.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

InvalidArgument

apps/dav/lib/Connector/Sabre/SharesPlugin.php:170:36: InvalidArgument: Argument 1 of OCA\DAV\Connector\Sabre\SharesPlugin::operationAddsShares expects OCA\DAV\Connector\Sabre\Folder, but OCP\Files\Folder provided (see https://psalm.dev/004)
return true;
}

Expand Down Expand Up @@ -326,7 +217,7 @@
* on a path only for share-ownerless mounts and otherwise filters by initiator, so the same-mount shortcut is
* only safe on share-ownerless mounts.
*/
private function operationAddsShares(Node $sourceParent, Node $targetNode): bool {

Check failure on line 220 in apps/dav/lib/Connector/Sabre/SharesPlugin.php

View workflow job for this annotation

GitHub Actions / static-code-analysis

UndefinedClass

apps/dav/lib/Connector/Sabre/SharesPlugin.php:220:39: UndefinedClass: Class, interface or enum named OCA\DAV\Connector\Sabre\Folder does not exist (see https://psalm.dev/019)
$targetMountPoint = $targetNode->getMountPoint();
$sameMount = $sourceParent->getMountPoint()->getMountPoint() === $targetMountPoint->getMountPoint();
$sourceParentPath = $sourceParent->getPath();
Expand Down
Loading
Loading