If time-range is set, only return matching events.

Closes #280
This commit is contained in:
Andrew Ruthven 2023-02-06 19:53:44 +13:00 committed by Florian Schlichting
parent 4a2db83b7c
commit b40c96debb
7 changed files with 100 additions and 80 deletions

View File

@ -1,5 +1,7 @@
2023-02-05 Andrew Ruthven <Andrew Ruthven>
2023-02-05 Andrew Ruthven <andrew@etc.gen.nz>
* 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 <andrew@etc.gen.nz>
* Fix Reccurrence Rules using BYHOUR, BYMINUTE and BYSECOND.

View File

@ -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);

View File

@ -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);

View File

@ -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"
<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
<response>
<href>/caldav.php/user1/home/2178279a-aec2-471f-832d-1f6df6203f2f.ics</href>
<propstat>
<prop>
<getetag>"509b0f0d8a3363379f9f5727f5dd74a0"</getetag>
<C:calendar-data>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
</C:calendar-data>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
<response>
<href>/caldav.php/user1/home/917b9e47-b748-4550-a566-657fbe672447.ics</href>
<propstat>
<prop>
<getetag>"cb3d9dc3e8c157f53eba3ea0e1e0f146"</getetag>
<C:calendar-data>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
</C:calendar-data>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
<response>
<href>/caldav.php/user1/home/e6eb5bc9-f7f9-4a0a-94e8-8e90eefc7d08.ics</href>
<propstat>

View File

@ -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"
<?xml version="1.0" encoding="utf-8" ?>
@ -38,24 +38,4 @@ Content-Type: text/xml; charset="utf-8"
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
<response>
<href>/caldav.php/user1/home/0544-gzip-PUT.ics</href>
<propstat>
<prop>
<getetag>"6ddd18264a9d40c1c9d37a005eeb7e4f"</getetag>
<resourcetype/>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
<response>
<href>/caldav.php/user1/home/0545-deflate-PUT.ics</href>
<propstat>
<prop>
<getetag>"4a3aa58a3e11487e87d87024465d4182"</getetag>
<resourcetype/>
</prop>
<status>HTTP/1.1 200 OK</status>
</propstat>
</response>
</multistatus>

View File

@ -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"
<?xml version="1.0" encoding="utf-8" ?>
<multistatus xmlns="DAV:"/>

View File

@ -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
<?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/>
</D:prop>
<C:filter>
<C:comp-filter name="VCALENDAR">
<C:comp-filter name="VEVENT">
<C:time-range start="20060713T110000Z" end="20060715T110000Z"/>
<C:prop-filter name="CATEGORIES">
<C:text-match collation="i;octet">PERSONAL</C:text-match>
</C:prop-filter>
</C:comp-filter>
</C:comp-filter>
</C:filter>
</C:calendar-query>
ENDDATA