Ver código fonte

Merge pull request #1981 from metallerok/overridden_recurrence_validation

(#1966) overridden recurrence validation
Peter Bieringer 1 semana atrás
pai
commit
33a6791fb5

+ 17 - 0
radicale/app/report.py

@@ -641,6 +641,23 @@ def _split_overridden_vevents(
             vevent_recurrence = vevent
 
     if vevent_recurrence:
+        # RFC 5545 3.8.4.4: RECURRENCE-ID MUST have the same value type as DTSTART
+        # in the recurring component.
+        base_dtstart = vevent_recurrence.dtstart.value
+        expected_type = datetime.date
+        if isinstance(base_dtstart, datetime.datetime):
+            expected_type = datetime.datetime
+
+        for ov in vevents_overridden:
+            rid = ov.recurrence_id.value
+            if not isinstance(rid, expected_type):
+                raise ValueError(
+                    f"component with UID {vevent_recurrence.uid} has "
+                    f"incompatible RECURRENCE-ID value type: base DTSTART is "
+                    f"{type(base_dtstart).__name__}, but override RECURRENCE-ID is "
+                    f"{type(rid).__name__} ({ov.recurrence_id.value!r})"
+                )
+
         return (
             vevent_recurrence, sorted(
                 vevents_overridden,

+ 20 - 0
radicale/tests/static/event_mixed_recurrence_id_dt_type.ics

@@ -0,0 +1,20 @@
+BEGIN:VCALENDAR
+VERSION:2.0
+
+BEGIN:VEVENT
+DTSTART:20060102T120000Z
+DURATION:PT1H
+RRULE:FREQ=DAILY;COUNT=3
+SUMMARY:Recurring event
+UID:event_mixed_recurrence_id_dt_type
+END:VEVENT
+
+BEGIN:VEVENT
+DTSTART:20060103T140000Z
+DURATION:PT1H
+RECURRENCE-ID;VALUE=DATE:20060103
+SUMMARY:Override with wrong type
+UID:event_mixed_recurrence_id_dt_type
+END:VEVENT
+
+END:VCALENDAR

+ 40 - 0
radicale/tests/test_expand.py

@@ -698,3 +698,43 @@ permissions: RrWw""")
         status, responses = self.report("/test", request)
         assert status == 207
         assert len(responses) == 0
+
+    def test_report_with_incompatible_recurrence_id_dt_types(self, caplog) -> None:
+        """Test report with incompatible RECURRENCE-ID value types (RFC 5545 3.8.4.4)"""
+
+        import logging
+        caplog.set_level(logging.WARNING)
+
+        event_id = "event_mixed_recurrence_id_dt_type"
+        start = "20060103T000000Z"
+        end = "20060105T000000Z"
+
+        self.put("/calendar.ics/", get_file_content(f"{event_id}.ics"))
+
+        request = f"""<?xml version="1.0" encoding="utf-8" ?>
+        <C:calendar-query xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
+            <D:prop>
+                <C:calendar-data>
+                    <C:expand start="{start}" end="{end}"/>
+                </C:calendar-data>
+            </D:prop>
+            <C:filter>
+                <C:comp-filter name="VCALENDAR">
+                    <C:comp-filter name="VEVENT">
+                        <C:time-range start="{start}" end="{end}"/>
+                    </C:comp-filter>
+                </C:comp-filter>
+            </C:filter>
+        </C:calendar-query>
+        """
+
+        status, _, _ = self.request("REPORT", "/calendar.ics/", request)
+
+        assert status == 400
+
+        logs = caplog.messages
+        error_logs = [log for log in logs if "incompatible RECURRENCE-ID value type" in log]
+        assert len(error_logs) > 0
+        assert event_id in error_logs[0]
+        assert "base DTSTART is datetime" in error_logs[0]
+        assert "override RECURRENCE-ID is date" in error_logs[0]