diff --git a/ChangeLog b/ChangeLog index d41ba8ee..5924f575 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ -2023-02-05 Andrew Ruthven +2023-02-05 Andrew Ruthven * Fix is-defined and is-not-defined prop-filters + * A time-range prop-filter should only return events if they are + either in the time-range or have a recurrence in it. 2022-02-07 Andrew Ruthven * Fix Reccurrence Rules using BYHOUR, BYMINUTE and BYSECOND. diff --git a/inc/caldav-REPORT-calquery.php b/inc/caldav-REPORT-calquery.php index ebb18be7..c0ec60a9 100644 --- a/inc/caldav-REPORT-calquery.php +++ b/inc/caldav-REPORT-calquery.php @@ -76,6 +76,7 @@ function SqlFilterFragment( $filter, $components, $property = null, $parameter = global $need_post_filter, $range_filter, $target_collection, $parameter_match_num; $sql = ""; $params = array(); + global $expand_range_start, $expand_range_end, $expand_as_floating; if ( !is_array($filter) ) { dbg_error_log( "calquery", "Filter is of type '%s', but should be an array of XML Tags.", gettype($filter) ); } @@ -182,12 +183,48 @@ function SqlFilterFragment( $filter, $components, $property = null, $parameter = $start = $v->GetAttribute("start"); $finish = $v->GetAttribute("end"); - if ( isset($start) ) + if ( isset($start) ) { $params[':time_range_start'] = $start; + $time_range_start = new RepeatRuleDateTime($start); + } else { + # RFC 4791 Section 9.9 says that if start isn't set, then -infinity + # should be used. We can't specify that in PHP, and + # expand_event_instances has '-6 weeks' as the default. + # That's a bit short, go for one year prior to end, if defined, + # otherwise 1 year prior to now now. + if ( isset($finish) ) { + $time_range_start = new RepeatRuleDateTime($finish); + } else { + $time_range_start = new RepeatRuleDateTime; + } + $time_range_start->modify('-365 days'); - if ( isset($finish) ) + $params[':time_range_start'] = $time_range_start->UTC(); + } + + if (! isset($expand_range_start) || $time_range_start > $expand_range_start ) { + # We overload the expand_range_start, and we may need to make it more restrictive. + $expand_range_start = $time_range_start; + } + + if ( isset($finish) ) { $params[':time_range_end'] = $finish; + $time_range_end = new RepeatRuleDateTime($finish); + } else { + # RFC 4791 Section 9.9 says that if end isn't set, then +infinity + # should be used. We can't specify that in PHP, and + # expand_event_instances has '+ 6 weeks' as the default. That's a + # bit short, go for two years from the start. + $time_range_end = clone($time_range_start); + $time_range_end->modify('+730 days'); + $params[':time_range_end'] = $time_range_end->UTC(); + } + + if (! isset($expand_range_end) || $time_range_end < $expand_range_end ) { + # We overload the expand_range_end, and we may need to make it more restrictive. + $expand_range_end = $time_range_end; + } $legacy_start_cond = "($start_column IS NULL AND $finish_column > :time_range_start) OR $start_column > :time_range_start"; $legacy_end_cond = "$finish_column < :time_range_end"; @@ -412,7 +449,7 @@ if ( $qry->Exec("calquery",__LINE__,__FILE__) && $qry->rows() > 0 ) { if ( $bound_from != $target_collection->dav_name() ) { $dav_object->dav_name = str_replace( $bound_from, $target_collection->dav_name(), $dav_object->dav_name); } - if ( $need_expansion ) { + if ( $need_expansion || isset($range_filter) ) { $vResource = new vComponent($dav_object->caldav_data); $expanded = getVCalendarRange($vResource, $dav_object->collection_tzid); if ( !$expanded->overlaps($range_filter) ) continue; @@ -420,7 +457,13 @@ if ( $qry->Exec("calquery",__LINE__,__FILE__) && $qry->rows() > 0 ) { $expanded = expand_event_instances($vResource, $expand_range_start, $expand_range_end, $expand_as_floating , $dav_object->collection_tzid); if ( $expanded->ComponentCount() == 0 ) continue; - if ( $need_expansion ) $dav_object->caldav_data = $expanded->Render(); + + # We only keep the expanded instaneces if need_expansion is set, + # RFC4791 Section 7.4. Otherwise we should return the original + # caldav_data. + if ( $need_expansion ) { + $dav_object->caldav_data = $expanded->Render(); + } } else if ( isset($range_filter) ) { $vResource = new vComponent($dav_object->caldav_data); diff --git a/inc/caldav-REPORT.php b/inc/caldav-REPORT.php index f685f13f..67bda5e6 100644 --- a/inc/caldav-REPORT.php +++ b/inc/caldav-REPORT.php @@ -84,12 +84,13 @@ switch( $xmltree->GetNSTag() ) { */ function check_for_expansion( $calendar_data_node ) { global $need_expansion, $expand_range_start, $expand_range_end, $expand_as_floating; + $expand_as_floating = false; $expansion = $calendar_data_node->GetElements('urn:ietf:params:xml:ns:caldav:expand'); if ( isset($expansion[0]) ) { $need_expansion = true; $expand_range_start = $expansion[0]->GetAttribute('start'); - $expand_range_end = $expansion[0]->GetAttribute('end'); + $expand_range_end = $expansion[0]->GetAttribute('end'); $expand_as_floating = $expansion[0]->GetAttribute('floating'); if ( isset($expand_range_start) ) $expand_range_start = new RepeatRuleDateTime($expand_range_start); if ( isset($expand_range_end) ) $expand_range_end = new RepeatRuleDateTime($expand_range_end); diff --git a/testing/tests/regression-suite/0236-Moz-REPORT.result b/testing/tests/regression-suite/0236-Moz-REPORT.result index 79d2fea3..4c07a48b 100644 --- a/testing/tests/regression-suite/0236-Moz-REPORT.result +++ b/testing/tests/regression-suite/0236-Moz-REPORT.result @@ -2,62 +2,12 @@ HTTP/1.1 207 Multi-Status Date: Dow, 01 Jan 2000 00:00:00 GMT DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy -ETag: "ab07e565993a377f23fc062109bbf013" -Content-Length: 2857 +ETag: "882eeadb4b2e998ed4358acda515e963" +Content-Length: 1421 Content-Type: text/xml; charset="utf-8" - - /caldav.php/user1/home/2178279a-aec2-471f-832d-1f6df6203f2f.ics - - - "509b0f0d8a3363379f9f5727f5dd74a0" - BEGIN:VCALENDAR -PRODID:-//Mozilla Calendar//NONSGML Sunbird//EN -VERSION:2.0 -BEGIN:VTODO -CREATED:20070805T200215Z -LAST-MODIFIED:20070805T201531Z -DTSTAMP:20070805T200215Z -UID:2178279a-aec2-471f-832d-1f6df6203f2f -SUMMARY:Incomplete\, uncancelled -X-MOZ-LOCATIONPATH:2178279a-aec2-471f-832d-1f6df6203f2f.ics -DESCRIPTION:This task is incomplete and has not been cancelled (has no - status at all) -END:VTODO -END:VCALENDAR - - - HTTP/1.1 200 OK - - - - /caldav.php/user1/home/917b9e47-b748-4550-a566-657fbe672447.ics - - - "cb3d9dc3e8c157f53eba3ea0e1e0f146" - BEGIN:VCALENDAR -PRODID:-//Mozilla Calendar//NONSGML Sunbird//EN -VERSION:2.0 -BEGIN:VTODO -CREATED:20070805T201557Z -LAST-MODIFIED:20070805T201643Z -DTSTAMP:20070805T201557Z -UID:917b9e47-b748-4550-a566-657fbe672447 -SUMMARY:50% Complete\, uncancelled -STATUS:IN-PROCESS -PERCENT-COMPLETE:50 -X-MOZ-LOCATIONPATH:917b9e47-b748-4550-a566-657fbe672447.ics -DESCRIPTION:This task is in progress (50% complete) and has not been - cancelled. -END:VTODO -END:VCALENDAR - - - HTTP/1.1 200 OK - - /caldav.php/user1/home/e6eb5bc9-f7f9-4a0a-94e8-8e90eefc7d08.ics diff --git a/testing/tests/regression-suite/0555-iPhone-REPORT.result b/testing/tests/regression-suite/0555-iPhone-REPORT.result index e282bf10..c9942ddf 100644 --- a/testing/tests/regression-suite/0555-iPhone-REPORT.result +++ b/testing/tests/regression-suite/0555-iPhone-REPORT.result @@ -2,8 +2,8 @@ HTTP/1.1 207 Multi-Status Date: Dow, 01 Jan 2000 00:00:00 GMT DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy -ETag: "64bfdf4e95a5799a86f1c79e0f3faf1d" -Content-Length: 1369 +ETag: "571aa22469ee7442c32ba35664da10de" +Content-Length: 880 Content-Type: text/xml; charset="utf-8" @@ -38,24 +38,4 @@ Content-Type: text/xml; charset="utf-8" HTTP/1.1 200 OK - - /caldav.php/user1/home/0544-gzip-PUT.ics - - - "6ddd18264a9d40c1c9d37a005eeb7e4f" - - - HTTP/1.1 200 OK - - - - /caldav.php/user1/home/0545-deflate-PUT.ics - - - "4a3aa58a3e11487e87d87024465d4182" - - - HTTP/1.1 200 OK - - diff --git a/testing/tests/regression-suite/2520-date-range-filter.result b/testing/tests/regression-suite/2520-date-range-filter.result new file mode 100644 index 00000000..a9bee7e1 --- /dev/null +++ b/testing/tests/regression-suite/2520-date-range-filter.result @@ -0,0 +1,10 @@ +HTTP/1.1 207 Multi-Status +Date: Dow, 01 Jan 2000 00:00:00 GMT +DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule +DAV: extended-mkcol, bind, addressbook, calendar-auto-schedule, calendar-proxy +ETag: "07474790757c5e1b526ce4901889d6d3" +Content-Length: 68 +Content-Type: text/xml; charset="utf-8" + + + diff --git a/testing/tests/regression-suite/2520-date-range-filter.test b/testing/tests/regression-suite/2520-date-range-filter.test new file mode 100644 index 00000000..0bdc9498 --- /dev/null +++ b/testing/tests/regression-suite/2520-date-range-filter.test @@ -0,0 +1,34 @@ +# +# data-range fileter +# +# Regression test for https://gitlab.com/davical-project/davical/-/issues/280 +# +# Should *not* return /user1/events/hand-crafted-vevent.ics +# +TYPE=REPORT +URL=http://regression.host/caldav.php/user1/events/ +HEADER=Content-Type: text/xml; charset="UTF-8" +HEADER=Depth: 0 +HEAD + + +BEGINDATA + + + + + + + + + + + PERSONAL + + + + + +ENDDATA + +