diff --git a/aleksis/core/util/dav_handler/base.py b/aleksis/core/util/dav_handler/base.py index abdfcd8adc8c4c4762763417c20c863a24539490..652373b6a68d45164dda763f1f0b9bec3bff86dd 100644 --- a/aleksis/core/util/dav_handler/base.py +++ b/aleksis/core/util/dav_handler/base.py @@ -39,7 +39,7 @@ class ElementHandler(RegistryObject, is_registry=True): self.invisible = invisible else: self.invisible = self.__class__.invisible - self.children = {} + self.children = [] @classmethod def get_name(cls, attrs): @@ -49,14 +49,11 @@ class ElementHandler(RegistryObject, is_registry=True): """Create instance of ElementHandler `child_class` and append to children or return existing child.""" - name = child_class.get_name(attrs) + child = child_class(self.request, self, attrs, invisible=invisible) + self.children.append(child) + self.request.current_object = child - if name not in self.children: - child = child_class(self.request, self, attrs, invisible=invisible) - self.children[name] = child - self.request.current_object = self.children[name] - - return self.children[name] + return child def process(self, stage: str, base: "DAVMultistatus", response: "DAVResponse" = None): """Build elements of the DAV multistatus response.""" @@ -77,7 +74,7 @@ class ElementHandler(RegistryObject, is_registry=True): except Http404: response.handle_unknown(self.name) - for name, child in self.children.items(): + for child in self.children: if child is not None: child.process(stage, base, response) else: @@ -176,7 +173,8 @@ class DAVRequest(ElementHandler, ContentHandler): if hasattr(obj, "pre_handle"): self.current_object.pre_handle() else: - self.current_object.children[xml_sub] = None + child = NotImplementedObject(xml_sub) + self.current_object.children.append(child) warnings.warn(f"DAVRequest could not parse {xml_sub}.") def endElementNS(self, name, qname): @@ -221,10 +219,21 @@ class DAVMultistatus: """ for stage in ("xml",): - for child in self.request.children.values(): + for child in self.request.children: child.process(stage, self) +class NotImplementedObject: + """Class to represent requested props that are not implemented.""" + + def __init__(self, xml_sub): + self.xml_sub = xml_sub + + + def process(self, stage, base, response = None): + pass + + class NotFoundObject: """Class to represent requested objects that do not exist.""" @@ -317,7 +326,7 @@ class QueryBase: continue base.current_xml = response.propstats[200] - for name, child in self.children.items(): + for child in self.children: if child is not None: child.process(stage, base, response) elif stage == "xml": diff --git a/aleksis/core/util/dav_handler/calendar.py b/aleksis/core/util/dav_handler/calendar.py index c363853c330487037c3fc6c881cf8d5e810db298..c615f14111eec5aafe32787e2d65bf3ee9aba2a6 100644 --- a/aleksis/core/util/dav_handler/calendar.py +++ b/aleksis/core/util/dav_handler/calendar.py @@ -16,7 +16,7 @@ class TimeRangeFilter(ElementHandler): def post_handle(self): filters = {} - report_base = next(iter(self.request.children.values())) + report_base = next(iter(self.request.children)) for k, v in self.attrs.items(): if k in [(None, "start"), (None, "end")]: @@ -43,7 +43,7 @@ class TextMatch(ElementHandler): ] q = Q(pk__in=[objs]) - report_base = next(iter(self.request.children.values())) + report_base = next(iter(self.request.children)) if "additional_filter" in report_base.get_objects_args: q = report_base.get_objects_args["additional_filter"] & q @@ -110,11 +110,7 @@ class CalDAVComp(ElementHandler): return f"{cls.name}-{name}" def pre_handle(self): - if self.attrs.get((None, "name")) == "VCALENDAR": - self.children = {} - self.parent.params["VTIMEZONE"] = False - - elif self.attrs.get((None, "name")) == "VTIMEZONE": + if self.attrs.get((None, "name")) == "VTIMEZONE": self.parent.parent.params["VTIMEZONE"] = True @@ -123,7 +119,7 @@ class Expand(ElementHandler): def post_handle(self): filters = {} - report_base = next(iter(self.request.children.values())) + report_base = next(iter(self.request.children)) for k, v in self.attrs.items(): if k in [(None, "start"), (None, "end")]: @@ -137,21 +133,23 @@ class CalendarData(ElementHandler): def pre_handle(self): self.params = {} - attrs = {(None, "name"): "VCALENDAR"} - vcalendar = CalDAVComp(self.request, self, attrs) - self.children[CalDAVComp.name] = vcalendar + def post_handle(self): + if not self.params: + attrs = {(None, "name"): "VCALENDAR"} + vcalendar = CalDAVComp(self.request, self, attrs) + self.children.append(vcalendar) - self.params["VTIMEZONE"] = True + self.params["VTIMEZONE"] = True - for comp_name in ("VTIMEZONE", "VEVENT"): - attrs = {(None, "name"): comp_name} - comp = CalDAVComp(self.request, self, attrs) - vcalendar.children[CalDAVComp.name] = comp + for comp_name in ("VTIMEZONE", "VEVENT"): + attrs = {(None, "name"): comp_name} + comp = CalDAVComp(self.request, self, attrs) + vcalendar.children.append(comp) def process_xml(self, base, response): super().process_xml(base, response) if not self.invisible: - report_base = next(iter(base.request.children.values())) + report_base = next(iter(base.request.children)) if response.obj is not None: objects = response.resource.objects.filter(pk=response.obj.pk) @@ -241,10 +239,14 @@ class ReportBase(QueryBase): self.request.objects = self.request.resource.get_objects(**self.get_objects_args) - if Timezone.name in self.children: - timezone = self.children.get(Timezone.name) - prop = self.children.get(DAVProp.name) - calendar_data = prop.children.get(CalendarData.name) + try: + timezone = next(filter(lambda child: isinstance(child, Timezone), self.children)) + except StopIteration: + timezone = None + + if timezone is not None: + prop = next(filter(lambda child: isinstance(child, DAVProp), self.children)) + calendar_data = next(filter(lambda child: isinstance(child, CalendarData), prop.children)) calendar_data.params["timezone"] = timezone.content @@ -265,6 +267,6 @@ class CalendarMultiget(ReportBase, ElementHandler): def post_handle(self): super().post_handle() - for child in self.children.values(): + for child in self.children: if child.name == DAVHref.name: child.invisible = True diff --git a/aleksis/core/util/dav_handler/contact.py b/aleksis/core/util/dav_handler/contact.py index f602d7d0fcdd7f03e5eed0ba0ced1de3e187f01d..f6f7d84e12ef960a60a4436692aaca4e0e2cb623 100644 --- a/aleksis/core/util/dav_handler/contact.py +++ b/aleksis/core/util/dav_handler/contact.py @@ -94,6 +94,6 @@ class AddressbookMultiget(QueryBase, ElementHandler): self.request.objects = [] def post_handle(self): - for child in self.children.values(): + for child in self.children: if child.name == DAVHref.name: child.invisible = True