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

honor TRIGGER of VALARM for timerange filtering

This commit is contained in:
Peter Bieringer 2025-05-15 21:35:00 +02:00
parent 3ea22a7ea4
commit f56416b2fb

View file

@ -121,6 +121,7 @@ def comp_match(item: "item.Item", filter_: ET.Element, level: int = 0) -> bool:
logger.warning("Filtering %s is not supported", name)
return True
# Point #3 and #4 of rfc4791-9.7.1
trigger = None
if level == 0:
components = [item.vobject_item]
elif level == 1:
@ -128,15 +129,18 @@ def comp_match(item: "item.Item", filter_: ET.Element, level: int = 0) -> bool:
elif level == 2:
components = list(getattr(item.vobject_item, "%s_list" % tag.lower()))
for comp in components:
if not hasattr(comp, name.lower()):
subcomp = getattr(comp, name.lower(), None)
if not subcomp:
return False
if hasattr(subcomp, "trigger"):
trigger = subcomp.trigger.value
for child in filter_:
if child.tag == xmlutils.make_clark("C:prop-filter"):
if not any(prop_match(comp, child, "C")
for comp in components):
return False
elif child.tag == xmlutils.make_clark("C:time-range"):
if not time_range_match(item.vobject_item, filter_[0], tag):
if not time_range_match(item.vobject_item, filter_[0], tag, trigger):
return False
elif child.tag == xmlutils.make_clark("C:comp-filter"):
if not comp_match(item, child, level=level + 1):
@ -166,7 +170,7 @@ def prop_match(vobject_item: vobject.base.Component,
# Point #3 and #4 of rfc4791-9.7.2
for child in filter_:
if ns == "C" and child.tag == xmlutils.make_clark("C:time-range"):
if not time_range_match(vobject_item, child, name):
if not time_range_match(vobject_item, child, name, None):
return False
elif child.tag == xmlutils.make_clark("%s:text-match" % ns):
if not text_match(vobject_item, child, name, ns):
@ -180,9 +184,10 @@ def prop_match(vobject_item: vobject.base.Component,
def time_range_match(vobject_item: vobject.base.Component,
filter_: ET.Element, child_name: str) -> bool:
filter_: ET.Element, child_name: str, trigger: datetime | None) -> bool:
"""Check whether the component/property ``child_name`` of
``vobject_item`` matches the time-range ``filter_``."""
# supporting since 3.5.4 now optional trigger (either absolute or relative offset)
if not filter_.get("start") and not filter_.get("end"):
return False
@ -193,6 +198,25 @@ def time_range_match(vobject_item: vobject.base.Component,
def range_fn(range_start: datetime, range_end: datetime,
is_recurrence: bool) -> bool:
nonlocal matched
if trigger:
# if trigger is given, only check range_start
if isinstance(trigger, timedelta):
# trigger is a offset, apply to range_start
if start < range_start + trigger and range_start + trigger < end:
matched = True
return True
else:
return False
elif isinstance(trigger, datetime):
# trigger is absolute, use instead of range_start
if start < trigger and trigger < end:
matched = True
return True
else:
return False
else:
logger.warning("item/filter/time_range_match/range_fn: unsupported data format of provided trigger=%r", trigger)
return True
if start < range_end and range_start < end:
matched = True
return True