From 128b32856905df9c87f75be9f4d489ae7d1abcb5 Mon Sep 17 00:00:00 2001 From: Peter Bieringer Date: Tue, 24 Feb 2026 06:44:16 +0100 Subject: [PATCH] sharing: add support for proppatch --- radicale/app/proppatch.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/radicale/app/proppatch.py b/radicale/app/proppatch.py index 197591b2..9c527c12 100644 --- a/radicale/app/proppatch.py +++ b/radicale/app/proppatch.py @@ -24,7 +24,7 @@ import re import socket import xml.etree.ElementTree as ET from http import client -from typing import Dict, Optional, cast +from typing import Dict, Optional, Union, cast import defusedxml.ElementTree as DefusedET @@ -37,7 +37,7 @@ from radicale.log import logger def xml_proppatch(base_prefix: str, path: str, xml_request: Optional[ET.Element], - collection: storage.BaseCollection) -> ET.Element: + collection: storage.BaseCollection, sharing: Union[dict, None] = None) -> ET.Element: """Read and answer PROPPATCH requests. Read rfc4918-9.2 for info. @@ -48,6 +48,9 @@ def xml_proppatch(base_prefix: str, path: str, multistatus.append(response) href = ET.Element(xmlutils.make_clark("D:href")) href.text = xmlutils.make_href(base_prefix, path) + if sharing: + # backmap + href.text = href.text.replace(sharing['PathMapped'], sharing['PathOrToken']) response.append(href) # Create D:propstat element for props with status 200 OK propstat = ET.Element(xmlutils.make_clark("D:propstat")) @@ -76,6 +79,15 @@ class ApplicationPartProppatch(ApplicationBase): path: str, user: str, remote_host: str, remote_useragent: str) -> types.WSGIResponse: """Manage PROPPATCH request.""" permissions_filter = None + sharing = None + if self._sharing._enabled: + # Sharing by token or map (if enabled) + sharing = self._sharing.sharing_collection_resolver(path, user) + if sharing: + # overwrite and run through extended permission check + path = sharing['PathMapped'] + user = sharing['Owner'] + permissions_filter = sharing['Permissions'] access = Access(self._rights, user, path, permissions_filter) if not access.check("w"): return httputils.NOT_ALLOWED @@ -100,7 +112,7 @@ class ApplicationPartProppatch(ApplicationBase): "Content-Type": "text/xml; charset=%s" % self._encoding} try: xml_answer = xml_proppatch(base_prefix, path, xml_content, - item) + item, sharing) if xml_content is not None: content = DefusedET.tostring( xml_content,