Merge pull request #1883 from pbiering/fix-1880
Fix for #1880 and finally for #1812
This commit is contained in:
@@ -156,6 +156,7 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
|
|||||||
Read rfc3253-3.6 for info.
|
Read rfc3253-3.6 for info.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
logger.debug("TRACE/REPORT/xml_report: base_prefix=%r path=%r", base_prefix, path)
|
||||||
multistatus = ET.Element(xmlutils.make_clark("D:multistatus"))
|
multistatus = ET.Element(xmlutils.make_clark("D:multistatus"))
|
||||||
if xml_request is None:
|
if xml_request is None:
|
||||||
return client.MULTI_STATUS, multistatus
|
return client.MULTI_STATUS, multistatus
|
||||||
@@ -239,6 +240,7 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
|
|||||||
filter_copy = copy.deepcopy(filter_)
|
filter_copy = copy.deepcopy(filter_)
|
||||||
|
|
||||||
if expand is not None:
|
if expand is not None:
|
||||||
|
logger.debug("TRACE/REPORT/xml_report: expand")
|
||||||
for comp_filter in filter_copy.findall(".//" + xmlutils.make_clark("C:comp-filter")):
|
for comp_filter in filter_copy.findall(".//" + xmlutils.make_clark("C:comp-filter")):
|
||||||
if comp_filter.get("name", "").upper() == "VCALENDAR":
|
if comp_filter.get("name", "").upper() == "VCALENDAR":
|
||||||
continue
|
continue
|
||||||
@@ -275,21 +277,15 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
|
|||||||
|
|
||||||
found_props = []
|
found_props = []
|
||||||
not_found_props = []
|
not_found_props = []
|
||||||
item_etag: str = ""
|
|
||||||
|
|
||||||
for prop in props:
|
for prop in props:
|
||||||
element = ET.Element(prop.tag)
|
element = ET.Element(prop.tag)
|
||||||
if prop.tag == xmlutils.make_clark("D:getetag"):
|
if prop.tag == xmlutils.make_clark("D:getcontenttype"):
|
||||||
if expand is not None:
|
|
||||||
item_etag = item.etag
|
|
||||||
else:
|
|
||||||
element.text = item.etag
|
|
||||||
found_props.append(element)
|
|
||||||
elif prop.tag == xmlutils.make_clark("D:getcontenttype"):
|
|
||||||
element.text = xmlutils.get_content_type(item, encoding)
|
element.text = xmlutils.get_content_type(item, encoding)
|
||||||
found_props.append(element)
|
found_props.append(element)
|
||||||
elif prop.tag in (
|
elif prop.tag in (
|
||||||
xmlutils.make_clark("C:calendar-data"),
|
xmlutils.make_clark("C:calendar-data"),
|
||||||
|
xmlutils.make_clark("D:getetag"),
|
||||||
xmlutils.make_clark("CR:address-data")):
|
xmlutils.make_clark("CR:address-data")):
|
||||||
element.text = item.serialize()
|
element.text = item.serialize()
|
||||||
|
|
||||||
@@ -326,11 +322,24 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
n_vevents += n_vev
|
n_vevents += n_vev
|
||||||
found_props.append(expanded_element)
|
if prop.tag == xmlutils.make_clark("D:getetag"):
|
||||||
|
if n_vev > 0:
|
||||||
|
logger.debug("TRACE/REPORT/xml_report: getetag/expanded element")
|
||||||
|
element.text = item.etag
|
||||||
|
found_props.append(element)
|
||||||
|
else:
|
||||||
|
logger.debug("TRACE/REPORT/xml_report: getetag/no expanded element")
|
||||||
|
else:
|
||||||
|
logger.debug("TRACE/REPORT/xml_report: default")
|
||||||
|
found_props.append(expanded_element)
|
||||||
else:
|
else:
|
||||||
found_props.append(element)
|
if prop.tag == xmlutils.make_clark("D:getetag"):
|
||||||
if hasattr(item.vobject_item, "vevent_list"):
|
element.text = item.etag
|
||||||
n_vevents += len(item.vobject_item.vevent_list)
|
found_props.append(element)
|
||||||
|
else:
|
||||||
|
found_props.append(element)
|
||||||
|
if hasattr(item.vobject_item, "vevent_list"):
|
||||||
|
n_vevents += len(item.vobject_item.vevent_list)
|
||||||
# Avoid DoS with too many events
|
# Avoid DoS with too many events
|
||||||
if max_occurrence and n_vevents > max_occurrence:
|
if max_occurrence and n_vevents > max_occurrence:
|
||||||
raise ValueError("REPORT occurrences limit of {} hit"
|
raise ValueError("REPORT occurrences limit of {} hit"
|
||||||
@@ -345,7 +354,7 @@ def xml_report(base_prefix: str, path: str, xml_request: Optional[ET.Element],
|
|||||||
if found_props or not_found_props:
|
if found_props or not_found_props:
|
||||||
multistatus.append(xml_item_response(
|
multistatus.append(xml_item_response(
|
||||||
base_prefix, uri, found_props=found_props,
|
base_prefix, uri, found_props=found_props,
|
||||||
not_found_props=not_found_props, found_item=True, item_etag=item_etag))
|
not_found_props=not_found_props, found_item=True))
|
||||||
|
|
||||||
return client.MULTI_STATUS, multistatus
|
return client.MULTI_STATUS, multistatus
|
||||||
|
|
||||||
@@ -664,7 +673,7 @@ def _find_overridden(
|
|||||||
def xml_item_response(base_prefix: str, href: str,
|
def xml_item_response(base_prefix: str, href: str,
|
||||||
found_props: Sequence[ET.Element] = (),
|
found_props: Sequence[ET.Element] = (),
|
||||||
not_found_props: Sequence[ET.Element] = (),
|
not_found_props: Sequence[ET.Element] = (),
|
||||||
found_item: bool = True, item_etag: str = "") -> ET.Element:
|
found_item: bool = True) -> ET.Element:
|
||||||
response = ET.Element(xmlutils.make_clark("D:response"))
|
response = ET.Element(xmlutils.make_clark("D:response"))
|
||||||
|
|
||||||
href_element = ET.Element(xmlutils.make_clark("D:href"))
|
href_element = ET.Element(xmlutils.make_clark("D:href"))
|
||||||
@@ -678,10 +687,6 @@ def xml_item_response(base_prefix: str, href: str,
|
|||||||
status = ET.Element(xmlutils.make_clark("D:status"))
|
status = ET.Element(xmlutils.make_clark("D:status"))
|
||||||
status.text = xmlutils.make_response(code)
|
status.text = xmlutils.make_response(code)
|
||||||
prop_element = ET.Element(xmlutils.make_clark("D:prop"))
|
prop_element = ET.Element(xmlutils.make_clark("D:prop"))
|
||||||
if (item_etag != "") and (code == 200):
|
|
||||||
prop_etag = ET.Element(xmlutils.make_clark("D:getetag"))
|
|
||||||
prop_etag.text = item_etag
|
|
||||||
prop_element.append(prop_etag)
|
|
||||||
for prop in props:
|
for prop in props:
|
||||||
prop_element.append(prop)
|
prop_element.append(prop)
|
||||||
propstat.append(prop_element)
|
propstat.append(prop_element)
|
||||||
@@ -735,6 +740,7 @@ def retrieve_items(
|
|||||||
else:
|
else:
|
||||||
yield item, False
|
yield item, False
|
||||||
if collection_requested:
|
if collection_requested:
|
||||||
|
logger.debug("TRACE/REPORT/retrieve_items: get_filtered")
|
||||||
yield from collection.get_filtered(filters)
|
yield from collection.get_filtered(filters)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
30
radicale/tests/static/event_issue1812_getetag.ics
Normal file
30
radicale/tests/static/event_issue1812_getetag.ics
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
BEGIN:VCALENDAR
|
||||||
|
VERSION:2.0
|
||||||
|
PRODID:-//algoo.fr//NONSGML Open Calendar v0.9//EN
|
||||||
|
BEGIN:VTIMEZONE
|
||||||
|
TZID:Europe/Paris
|
||||||
|
LAST-MODIFIED:20250523T094234Z
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19701025T030000Z
|
||||||
|
RRULE:BYDAY=-1SU;BYMONTH=10;FREQ=YEARLY
|
||||||
|
TZNAME:CET
|
||||||
|
TZOFFSETFROM:+0200
|
||||||
|
TZOFFSETTO:+0100
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19700329T020000Z
|
||||||
|
RRULE:BYDAY=-1SU;BYMONTH=3;FREQ=YEARLY
|
||||||
|
TZNAME:CEST
|
||||||
|
TZOFFSETFROM:+0100
|
||||||
|
TZOFFSETTO:+0200
|
||||||
|
END:DAYLIGHT
|
||||||
|
END:VTIMEZONE
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:070a3478-4411-4364-844d-26f3542fc364
|
||||||
|
DTSTART;TZID=Europe/Paris;VALUE=DATE:20250716
|
||||||
|
DTEND;TZID=Europe/Paris;VALUE=DATE:20250717
|
||||||
|
DTSTAMP;VALUE=DATE-TIME:20250723T080354Z
|
||||||
|
SEQUENCE:1
|
||||||
|
SUMMARY:Filtered event
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
||||||
29
radicale/tests/static/event_issue1880_1.ics
Normal file
29
radicale/tests/static/event_issue1880_1.ics
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
BEGIN:VCALENDAR
|
||||||
|
VERSION:2.0
|
||||||
|
PRODID:-//algoo.fr//NONSGML Open Calendar v0.9//EN
|
||||||
|
BEGIN:VTIMEZONE
|
||||||
|
TZID:Europe/Paris
|
||||||
|
LAST-MODIFIED:20250523T094234Z
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19701025T030000Z
|
||||||
|
RRULE:BYDAY=-1SU;BYMONTH=10;FREQ=YEARLY
|
||||||
|
TZNAME:CET
|
||||||
|
TZOFFSETFROM:+0200
|
||||||
|
TZOFFSETTO:+0100
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19700329T020000Z
|
||||||
|
RRULE:BYDAY=-1SU;BYMONTH=3;FREQ=YEARLY
|
||||||
|
TZNAME:CEST
|
||||||
|
TZOFFSETFROM:+0100
|
||||||
|
TZOFFSETTO:+0200
|
||||||
|
END:DAYLIGHT
|
||||||
|
END:VTIMEZONE
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:f5b69821-addc-4010-9ab8-891df1c33c01
|
||||||
|
DTSTART;TZID=Europe/Paris;VALUE=DATE-TIME:20250925T093000
|
||||||
|
DTEND;TZID=Europe/Paris;VALUE=DATE-TIME:20250925T140000
|
||||||
|
DTSTAMP:20250923T114003Z
|
||||||
|
SUMMARY:event from opencalendar
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
||||||
396
radicale/tests/static/event_issue1880_2.ics
Normal file
396
radicale/tests/static/event_issue1880_2.ics
Normal file
@@ -0,0 +1,396 @@
|
|||||||
|
BEGIN:VCALENDAR
|
||||||
|
VERSION:2.0
|
||||||
|
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
|
||||||
|
BEGIN:VTIMEZONE
|
||||||
|
TZID:Europe/Paris
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19110311T000000
|
||||||
|
RDATE:19110311T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+000921
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19161002T000000
|
||||||
|
RDATE:19161002T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19171008T000000
|
||||||
|
RDATE:19171008T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19181007T000000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1MO;UNTIL=19191006T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19201024T000000
|
||||||
|
RDATE:19201024T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19211026T000000
|
||||||
|
RDATE:19211026T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19221008T000000
|
||||||
|
RDATE:19221008T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19231007T000000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU;UNTIL=19321002T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19331008T000000
|
||||||
|
RDATE:19331008T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19341007T000000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU;UNTIL=19381002T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19391119T000000
|
||||||
|
RDATE:19391119T000000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+000000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19421102T030000
|
||||||
|
RDATE:19421102T030000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19431004T030000
|
||||||
|
RDATE:19431004T030000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19450916T030000
|
||||||
|
RDATE:19450916T030000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19760926T010000
|
||||||
|
RDATE:19760926T010000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19770925T030000
|
||||||
|
RDATE:19770925T030000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19781001T030000
|
||||||
|
RDATE:19781001T030000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19790930T030000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU;UNTIL=19950924T030000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19961027T030000
|
||||||
|
RDATE:19961027T030000
|
||||||
|
TZNAME:Europe/Paris(STD)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:STANDARD
|
||||||
|
DTSTART:19971026T030000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
||||||
|
TZNAME:(STD)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:STANDARD
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19160614T230000
|
||||||
|
RDATE:19160614T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19170324T230000
|
||||||
|
RDATE:19170324T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19180309T230000
|
||||||
|
RDATE:19180309T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19190301T230000
|
||||||
|
RDATE:19190301T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19200214T230000
|
||||||
|
RDATE:19200214T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19210314T230000
|
||||||
|
RDATE:19210314T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19220325T230000
|
||||||
|
RDATE:19220325T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19230526T230000
|
||||||
|
RDATE:19230526T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19240329T230000
|
||||||
|
RDATE:19240329T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19250404T230000
|
||||||
|
RDATE:19250404T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19260417T230000
|
||||||
|
RDATE:19260417T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19270409T230000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=2SA;UNTIL=19280414T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19290420T230000
|
||||||
|
RDATE:19290420T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19300412T230000
|
||||||
|
RDATE:19300412T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19310418T230000
|
||||||
|
RDATE:19310418T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19320402T230000
|
||||||
|
RDATE:19320402T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19330325T230000
|
||||||
|
RDATE:19330325T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19340407T230000
|
||||||
|
RDATE:19340407T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19350330T230000
|
||||||
|
RDATE:19350330T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19360418T230000
|
||||||
|
RDATE:19360418T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19370403T230000
|
||||||
|
RDATE:19370403T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19380326T230000
|
||||||
|
RDATE:19380326T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19390415T230000
|
||||||
|
RDATE:19390415T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19400225T020000
|
||||||
|
RDATE:19400225T020000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+000000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19400614T230000
|
||||||
|
RDATE:19400614T230000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+020000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19430329T020000
|
||||||
|
RDATE:19430329T020000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+020000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19440403T020000
|
||||||
|
RDATE:19440403T020000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+020000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19440825T000000
|
||||||
|
RDATE:19440825T000000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+020000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19441008T010000
|
||||||
|
RDATE:19441008T010000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+020000
|
||||||
|
TZOFFSETTO:+010000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19450402T020000
|
||||||
|
RDATE:19450402T020000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+020000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19760328T010000
|
||||||
|
RDATE:19760328T010000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+020000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19770403T020000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU;UNTIL=19800406T020000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+020000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19810329T020000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU;UNTIL=19960331T020000
|
||||||
|
TZNAME:Europe/Paris(DST)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+020000
|
||||||
|
END:DAYLIGHT
|
||||||
|
BEGIN:DAYLIGHT
|
||||||
|
DTSTART:19970330T020000
|
||||||
|
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
||||||
|
TZNAME:(DST)
|
||||||
|
TZOFFSETFROM:+010000
|
||||||
|
TZOFFSETTO:+020000
|
||||||
|
END:DAYLIGHT
|
||||||
|
X-TZINFO:Europe/Paris[2024a]
|
||||||
|
END:VTIMEZONE
|
||||||
|
BEGIN:VEVENT
|
||||||
|
UID:50c08af4-295c-4bea-9ea4-7402b8e82143
|
||||||
|
DTSTART;TZID=Europe/Paris:20250924T133000
|
||||||
|
DTEND;TZID=Europe/Paris:20250924T143000
|
||||||
|
CREATED:20250923T113902Z
|
||||||
|
DTSTAMP:20250923T113912Z
|
||||||
|
LAST-MODIFIED:20250923T113912Z
|
||||||
|
SUMMARY:event from thunderbird
|
||||||
|
TRANSP:OPAQUE
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
||||||
@@ -512,3 +512,188 @@ permissions: RrWw""")
|
|||||||
status, event2_calendar_data = responses["/test/event2.ics"]["C:calendar-data"]
|
status, event2_calendar_data = responses["/test/event2.ics"]["C:calendar-data"]
|
||||||
assert event2_calendar_data.text
|
assert event2_calendar_data.text
|
||||||
assert "UID:c6be8b2c-3d72-453c-b698-4f25cdf1569e" in event2_calendar_data.text
|
assert "UID:c6be8b2c-3d72-453c-b698-4f25cdf1569e" in event2_calendar_data.text
|
||||||
|
|
||||||
|
def test_report_getetag_expand_filter(self) -> None:
|
||||||
|
"""Test getetag with time-range filter and expand (example from #1880)."""
|
||||||
|
self.mkcalendar("/test/")
|
||||||
|
self.put("/test/event_issue1880_1.ics", get_file_content("event_issue1880_1.ics"))
|
||||||
|
self.put("/test/event_issue1880_2.ics", get_file_content("event_issue1880_2.ics"))
|
||||||
|
|
||||||
|
request = """
|
||||||
|
<C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||||
|
<D:prop>
|
||||||
|
<D:getetag>
|
||||||
|
<C:expand start="20250921T220000Z" end="20250928T220000Z"/>
|
||||||
|
</D:getetag>
|
||||||
|
</D:prop>
|
||||||
|
<C:filter>
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20250921T220000Z" end="20250928T220000Z"/>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:filter>
|
||||||
|
</C:calendar-query>
|
||||||
|
"""
|
||||||
|
status, responses = self.report("/test", request)
|
||||||
|
assert status == 207
|
||||||
|
assert len(responses) == 2
|
||||||
|
assert isinstance(responses["/test/event_issue1880_1.ics"], dict)
|
||||||
|
assert isinstance(responses["/test/event_issue1880_2.ics"], dict)
|
||||||
|
assert "D:getetag" in responses["/test/event_issue1880_1.ics"]
|
||||||
|
assert "D:getetag" in responses["/test/event_issue1880_2.ics"]
|
||||||
|
|
||||||
|
def test_report_getetag_expand_filter_positive1(self) -> None:
|
||||||
|
"""Test getetag with time-range filter and expand (not applicable), should return as matching filter range (example from #1812)."""
|
||||||
|
self.mkcalendar("/test/")
|
||||||
|
self.put("/test/event_issue1812_getetag.ics", get_file_content("event_issue1812_getetag.ics"))
|
||||||
|
|
||||||
|
request = """
|
||||||
|
<C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||||
|
<D:prop>
|
||||||
|
<D:getetag>
|
||||||
|
<C:expand start="20250706T220000Z" end="20250713T220000Z" />
|
||||||
|
</D:getetag>
|
||||||
|
</D:prop>
|
||||||
|
<C:filter>
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20250716T220000Z" end="20250717T220000Z" />
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:filter>
|
||||||
|
</C:calendar-query>
|
||||||
|
"""
|
||||||
|
status, responses = self.report("/test", request)
|
||||||
|
assert status == 207
|
||||||
|
assert len(responses) == 1
|
||||||
|
assert isinstance(responses["/test/event_issue1812_getetag.ics"], dict)
|
||||||
|
assert "D:getetag" in responses["/test/event_issue1812_getetag.ics"]
|
||||||
|
|
||||||
|
def test_report_getetag_expand_filter_positive2(self) -> None:
|
||||||
|
"""Test getetag with time-range filter and expand, should return as matching filter range (example from #1812)."""
|
||||||
|
self.mkcalendar("/test/")
|
||||||
|
self.put("/test/event_issue1812.ics", get_file_content("event_issue1812.ics"))
|
||||||
|
|
||||||
|
request = """
|
||||||
|
<C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||||
|
<D:prop>
|
||||||
|
<D:getetag>
|
||||||
|
<C:expand start="20250706T220000Z" end="20250730T220000Z" />
|
||||||
|
</D:getetag>
|
||||||
|
</D:prop>
|
||||||
|
<C:filter>
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20250716T220000Z" end="20250723T220000Z" />
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:filter>
|
||||||
|
</C:calendar-query>
|
||||||
|
"""
|
||||||
|
status, responses = self.report("/test", request)
|
||||||
|
assert status == 207
|
||||||
|
assert len(responses) == 1
|
||||||
|
assert isinstance(responses["/test/event_issue1812.ics"], dict)
|
||||||
|
assert "D:getetag" in responses["/test/event_issue1812.ics"]
|
||||||
|
|
||||||
|
def test_report_getetag_expand_filter_negative1(self) -> None:
|
||||||
|
"""Test getetag with time-range filter and expand, should not return anything (example from #1812)."""
|
||||||
|
self.mkcalendar("/test/")
|
||||||
|
self.put("/test/event_issue1812_getetag.ics", get_file_content("event_issue1812_getetag.ics"))
|
||||||
|
|
||||||
|
request = """
|
||||||
|
<C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||||
|
<D:prop>
|
||||||
|
<D:getetag>
|
||||||
|
<C:expand start="20250706T220000Z" end="20250713T220000Z" />
|
||||||
|
</D:getetag>
|
||||||
|
</D:prop>
|
||||||
|
<C:filter>
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20250706T220000Z" end="20250713T220000Z" />
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:filter>
|
||||||
|
</C:calendar-query>
|
||||||
|
"""
|
||||||
|
status, responses = self.report("/test", request)
|
||||||
|
assert status == 207
|
||||||
|
assert len(responses) == 0
|
||||||
|
|
||||||
|
def test_report_getetag_expand_filter_negative2(self) -> None:
|
||||||
|
"""Test getetag with time-range filter and expand, should not return anything (example from #1812)."""
|
||||||
|
self.mkcalendar("/test/")
|
||||||
|
self.put("/test/event_issue1812_getetag.ics", get_file_content("event_issue1812_getetag.ics"))
|
||||||
|
|
||||||
|
request = """
|
||||||
|
<C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||||
|
<D:prop>
|
||||||
|
<D:getetag />
|
||||||
|
<C:calendar-data>
|
||||||
|
<C:expand start="20240706T220000Z" end="20240713T220000Z" />
|
||||||
|
</C:calendar-data>
|
||||||
|
</D:prop>
|
||||||
|
<C:filter>
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20250706T220000Z" end="20250713T220000Z" />
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:filter>
|
||||||
|
</C:calendar-query>
|
||||||
|
"""
|
||||||
|
status, responses = self.report("/test", request)
|
||||||
|
assert status == 207
|
||||||
|
assert len(responses) == 0
|
||||||
|
|
||||||
|
def test_report_getetag_expand_filter_negative3(self) -> None:
|
||||||
|
"""Test getetag with time-range filter and expand, should not return anything (example from #1812)."""
|
||||||
|
self.mkcalendar("/test/")
|
||||||
|
self.put("/test/event_issue1812_getetag.ics", get_file_content("event_issue1812_getetag.ics"))
|
||||||
|
|
||||||
|
request = """
|
||||||
|
<C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||||
|
<D:prop>
|
||||||
|
<C:calendar-data>
|
||||||
|
<C:expand start="20240706T220000Z" end="20240713T220000Z" />
|
||||||
|
</C:calendar-data>
|
||||||
|
</D:prop>
|
||||||
|
<C:filter>
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20250706T220000Z" end="20250713T220000Z" />
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:filter>
|
||||||
|
</C:calendar-query>
|
||||||
|
"""
|
||||||
|
status, responses = self.report("/test", request)
|
||||||
|
assert status == 207
|
||||||
|
assert len(responses) == 0
|
||||||
|
|
||||||
|
def test_report_getetag_expand_filter_negative4(self) -> None:
|
||||||
|
"""Test getetag with time-range filter and expand, nothing returned as filter is not matching (example from #1812)."""
|
||||||
|
self.mkcalendar("/test/")
|
||||||
|
self.put("/test/event_issue1812.ics", get_file_content("event_issue1812.ics"))
|
||||||
|
|
||||||
|
request = """
|
||||||
|
<C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
|
||||||
|
<D:prop>
|
||||||
|
<D:getetag>
|
||||||
|
<C:expand start="20250706T220000Z" end="20250730T220000Z" />
|
||||||
|
</D:getetag>
|
||||||
|
</D:prop>
|
||||||
|
<C:filter>
|
||||||
|
<C:comp-filter name="VCALENDAR">
|
||||||
|
<C:comp-filter name="VEVENT">
|
||||||
|
<C:time-range start="20240716T220000Z" end="20240723T220000Z" />
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:comp-filter>
|
||||||
|
</C:filter>
|
||||||
|
</C:calendar-query>
|
||||||
|
"""
|
||||||
|
status, responses = self.report("/test", request)
|
||||||
|
assert status == 207
|
||||||
|
assert len(responses) == 0
|
||||||
|
|||||||
Reference in New Issue
Block a user