From 4bdac18d251acf6f653587c1a272f4443eeb0a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Fri, 14 Aug 2026 12:22:00 +0200 Subject: [PATCH 1/2] fix(dav): Ensure we access a shareable node if multiple exist MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Müller --- apps/dav/appinfo/v1/publicwebdav.php | 11 +++++++++++ apps/dav/appinfo/v2/publicremote.php | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/apps/dav/appinfo/v1/publicwebdav.php b/apps/dav/appinfo/v1/publicwebdav.php index f993a8104294e..e51d1a71320f3 100644 --- a/apps/dav/appinfo/v1/publicwebdav.php +++ b/apps/dav/appinfo/v1/publicwebdav.php @@ -129,6 +129,17 @@ function (\Sabre\DAV\Server $server) use ( if (!$node) { throw new \Sabre\DAV\Exception\NotFound(); } + + // getFirstNodeById might return a node without share permission -> try to find a node which is shareable + if (!$node->isShareable()) { + foreach ($userFolder->getById($fileId) as $candidate) { + if ($candidate->isShareable()) { + $node = $candidate; + break; + } + } + } + $linkCheckPlugin->setFileInfo($node); // If not readable (files_drop) enable the filesdrop plugin diff --git a/apps/dav/appinfo/v2/publicremote.php b/apps/dav/appinfo/v2/publicremote.php index 6fb5cafe6cbef..fedb202bd9f32 100644 --- a/apps/dav/appinfo/v2/publicremote.php +++ b/apps/dav/appinfo/v2/publicremote.php @@ -162,6 +162,17 @@ if (!$node) { throw new NotFound(); } + + // getFirstNodeById might return a node without share permission -> try to find a node which is shareable + if (!$node->isShareable()) { + foreach ($userFolder->getById($fileId) as $candidate) { + if ($candidate->isShareable()) { + $node = $candidate; + break; + } + } + } + $linkCheckPlugin->setFileInfo($node); // If not readable (files_drop) enable the filesdrop plugin From 4c9ecf6ec2e8a1f3641f99a7a959d59da403d1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20M=C3=BCller?= Date: Fri, 14 Aug 2026 12:22:35 +0200 Subject: [PATCH 2/2] test: Add test for multi-mount public links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Marcel Müller --- .../dav_features/dav-v2-public.feature | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/build/integration/dav_features/dav-v2-public.feature b/build/integration/dav_features/dav-v2-public.feature index 9b36ef4ff20f9..cc06795364e80 100644 --- a/build/integration/dav_features/dav-v2-public.feature +++ b/build/integration/dav_features/dav-v2-public.feature @@ -110,3 +110,33 @@ Feature: dav-v2-public Then the downloaded zip file contains a folder named "testFolder/" And the downloaded zip file contains a file named "testFolder/text.txt" with the contents of "/testshare/testFolder/text.txt" from "user0" data And the downloaded zip file contains a file named "testFolder/image.png" with the contents of "/testshare/testFolder/image.png" from "user0" data + + # After the link share was created the initiator gets a second, read-only path to the + # shared folder. Nodes are ordered by path descending, so "/z-child" is found before + # "/parent/z-child" and the shareable path has to be picked explicitly. + Scenario: Downloading a file from a public share of a folder the initiator can also reach without share permission + Given using new dav path + And As an "admin" + And user "user0" exists + And user "user1" exists + And As an "user0" + And user "user0" created a folder "/parent" + And user "user0" created a folder "/parent/z-child" + And User "user0" uploads file with content "shared content" to "/parent/z-child/text.txt" + And folder "/parent" of user "user0" is shared with user "user1" with permissions 31 + And user "user1" accepts last share + And as "user1" creating a share with + | path | parent/z-child | + | shareType | 3 | + | permissions | 1 | + Then the OCS status code should be "100" + And the HTTP status code should be "200" + And save the last share data as "publicLink" + And folder "/parent/z-child" of user "user0" is shared with user "user1" with permissions 1 + And user "user1" accepts last share + And restore the last share data from "publicLink" + And As an "user0" + Given using new public dav path + When Downloading public file "/text.txt" + Then the HTTP status code should be "200" + And Downloaded content should be "shared content"