X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;ds=sidebyside;f=webcit-ng%2Fserver%2Fcaldav_reports.c;fp=webcit-ng%2Fserver%2Fcaldav_reports.c;h=8930bfb328b325d626323b586498c67aef3eeab1;hb=3369975ea949c33c3eeb4a4668d5af402cb8781a;hp=374d50ee5f754842dadd2fadce83e81e40641a8b;hpb=0b83ae50f5442c82dc8fb11ad3322d90383e34d5;p=citadel.git diff --git a/webcit-ng/server/caldav_reports.c b/webcit-ng/server/caldav_reports.c index 374d50ee5..8930bfb32 100644 --- a/webcit-ng/server/caldav_reports.c +++ b/webcit-ng/server/caldav_reports.c @@ -260,33 +260,60 @@ void caldav_report_one_item(struct http_transaction *h, struct ctdlsession *c, S // Compare function for "time-range" tests (RFC4791 section 9.9) // Returns nonzero if the supplied icalcomponent occurs within the specified time range +// +// IMPLEMENTATION NOTE: +// ical_ctdl_is_overlap() works because icaltime_compare() is really smart. +// It looks at the time zone of the dtstart/dtend and can apparently go back up the icalcomponent +// hierarchy to find its time zone data. I tested this by creating an event with a fictional +// time zone and it did the right thing. It even showed the fictional name to me. This saves us +// from having to convert everything to UTC before comparing. Nice! +// int caldav_time_range_filter_matches(icalcomponent *cal, char *start_str, char *end_str) { + struct icaltimetype dtstart = icalcomponent_get_dtstart(cal); + struct icaltimetype dtend = icalcomponent_get_dtend(cal); - // syslog(LOG_DEBUG, "caldav_time_range_filter_matches() comparing:\n\033[35m%s\033[0m", icalcomponent_as_ical_string(cal)); + struct icaltimetype search_start = icaltime_from_string(start_str); + syslog(LOG_DEBUG, " search start: \033[36m%-16s\033[0m (%s)", icaltime_as_ical_string_r(search_start), icaltime_get_tzid(search_start)); - // NOTE TO ME: - // Recurrence info is available at this level. We can handle it here. + struct icaltimetype search_end = icaltime_from_string(end_str); + syslog(LOG_DEBUG, " search end: \033[36m%-16s\033[0m (%s)", icaltime_as_ical_string_r(search_end), icaltime_get_tzid(search_end)); - // IMPLEMENTATION NOTE: - // ical_ctdl_is_overlap() works because icaltime_compare() is really smart. - // It looks at the time zone of the dtstart/dtend and can apparently go back up the icalcomponent - // hierarchy to find its time zone data. I tested this by creating an event with a fictional - // time zone and it did the right thing. It even showed the fictional name to me. This saves us - // from having to convert everything to UTC before comparing. Nice! + // If it is a recurring event, RRULE is available at this level. We can handle it here. - icaltimetype dts = icalcomponent_get_dtstart(cal); - syslog(LOG_DEBUG, "component start: \033[36m%-16s\033[0m (%s)", icaltime_as_ical_string_r(dts), icaltime_get_tzid(dts)); - - icaltimetype dte = icalcomponent_get_dtend(cal); - syslog(LOG_DEBUG, "component end: \033[36m%-16s\033[0m (%s)", icaltime_as_ical_string_r(dte), icaltime_get_tzid(dte)); + icalproperty *rrule; + rrule = icalcomponent_get_first_property(cal, ICAL_RRULE_PROPERTY); + if (rrule) { + if (icaltime_is_null_time(dtend)) { + dtend = dtstart; + } + struct icaldurationtype dur = icaltime_subtract(dtend, dtstart); // recurrences need duration to find dtend + struct icalrecurrencetype recur = icalproperty_get_rrule(rrule); + + icalrecur_iterator *ritr = icalrecur_iterator_new(recur, dtstart); // iterate through recurrences + int rcount = 0; + syslog(LOG_DEBUG, "\033[7m RECURRENCE: \033[0m"); + while (dtstart = icalrecur_iterator_next(ritr), !icaltime_is_null_time(dtstart)) { + dtend = icaltime_add(dtstart, dur); + syslog(LOG_DEBUG, "recurrence %3d start: \033[36m%-16s\033[0m (%s)", rcount, icaltime_as_ical_string_r(dtstart), icaltime_get_tzid(dtstart)); + syslog(LOG_DEBUG, "recurrence %3d end: \033[36m%-16s\033[0m (%s)", rcount, icaltime_as_ical_string_r(dtend), icaltime_get_tzid(dtend)); + + // Does THIS recurrence match the query? + if (ical_ctdl_is_overlap(dtstart, dtend, search_start, search_end)) { + icalrecur_iterator_free(ritr); + return(1); + } - struct icaltimetype start = icaltime_from_string(start_str); - syslog(LOG_DEBUG, " search start: \033[36m%-16s\033[0m (%s)", icaltime_as_ical_string_r(start), icaltime_get_tzid(start)); + ++rcount; + } - struct icaltimetype end = icaltime_from_string(end_str); - syslog(LOG_DEBUG, " search end: \033[36m%-16s\033[0m (%s)", icaltime_as_ical_string_r(end), icaltime_get_tzid(end)); + icalrecur_iterator_free(ritr); + return(0); // compared all recurrences, no match was found for any of them + } - return(ical_ctdl_is_overlap(dts, dte, start, end)); // We have a convenience function for this. + // For non recurring events, do a simple time range compare. + syslog(LOG_DEBUG, "event start: \033[36m%-16s\033[0m (%s)", icaltime_as_ical_string_r(dtstart), icaltime_get_tzid(dtstart)); + syslog(LOG_DEBUG, "event end: \033[36m%-16s\033[0m (%s)", icaltime_as_ical_string_r(dtend), icaltime_get_tzid(dtend)); + return(ical_ctdl_is_overlap(dtstart, dtend, search_start, search_end)); // We have a convenience function for this. }