1
0
Fork 0
mirror of https://github.com/Kozea/Radicale.git synced 2025-06-26 16:45:52 +00:00

processing expand property for REPORT

This commit is contained in:
Georgiy 2023-03-30 19:30:59 +03:00
parent 6ae831a324
commit ae731290c1

View file

@ -18,11 +18,16 @@
# along with Radicale. If not, see <http://www.gnu.org/licenses/>.
import contextlib
import datetime
import posixpath
import socket
import copy
import xml.etree.ElementTree as ET
from http import client
from typing import Callable, Iterable, Iterator, Optional, Sequence, Tuple
from typing import (
Callable, Iterable, Iterator,
Optional, Sequence, Tuple, List,
)
from urllib.parse import unquote, urlparse
import radicale.item as radicale_item
@ -64,9 +69,8 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
logger.warning("Invalid REPORT method %r on %r requested",
xmlutils.make_human_tag(root.tag), path)
return client.FORBIDDEN, xmlutils.webdav_error("D:supported-report")
prop_element = root.find(xmlutils.make_clark("D:prop"))
props = ([prop.tag for prop in prop_element]
if prop_element is not None else [])
props = root.find(xmlutils.make_clark("D:prop")) or []
hreferences: Iterable[str]
if root.tag in (
@ -138,18 +142,39 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
found_props = []
not_found_props = []
for tag in props:
element = ET.Element(tag)
if tag == xmlutils.make_clark("D:getetag"):
for prop in props:
element = ET.Element(prop.tag)
if prop.tag == xmlutils.make_clark("D:getetag"):
element.text = item.etag
found_props.append(element)
elif tag == xmlutils.make_clark("D:getcontenttype"):
elif prop.tag == xmlutils.make_clark("D:getcontenttype"):
element.text = xmlutils.get_content_type(item, encoding)
found_props.append(element)
elif tag in (
elif prop.tag in (
xmlutils.make_clark("C:calendar-data"),
xmlutils.make_clark("CR:address-data")):
element.text = item.serialize()
expand = prop.find(xmlutils.make_clark("C:expand"))
if expand is not None:
start = expand.get('start')
end = expand.get('end')
if (start is None) or (end is None):
return client.FORBIDDEN, \
xmlutils.webdav_error("C:expand")
start = datetime.datetime.strptime(
start, '%Y%m%dT%H%M%SZ'
).replace(tzinfo=datetime.timezone.utc)
end = datetime.datetime.strptime(
end, '%Y%m%dT%H%M%SZ'
).replace(tzinfo=datetime.timezone.utc)
expanded_elements = _expand(
element, copy.copy(item), start, end)
found_props.extend(expanded_elements)
else:
found_props.append(element)
else:
not_found_props.append(element)
@ -164,6 +189,35 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
return client.MULTI_STATUS, multistatus
def _expand(
element: ET.Element,
item: radicale_item.Item,
start: datetime.datetime,
end: datetime.datetime,
) -> List[ET.Element]:
expanded = [element]
for component in item.vobject_item.components():
if component.name != 'VEVENT':
continue
if hasattr(component, "rrule"):
rulleset = component.getrruleset()
instances = rulleset.between(start, end)
for instance in instances:
try:
delattr(item.vobject_item.vevent, 'recurrence-id')
except AttributeError:
pass
item.vobject_item.vevent.add('RECURRENCE-ID').value = instance
element.text = item.vobject_item.serialize()
expanded.append(element)
return expanded
def xml_item_response(base_prefix: str, href: str,
found_props: Sequence[ET.Element] = (),
not_found_props: Sequence[ET.Element] = (),