X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fmodules%2Fcalendar%2Fserv_calendar.c;h=f8dcdf930d317d1bfc9a7a68ecbb38cc5de768e4;hb=aeeb8d6fecd8ef9a1d401810313281582460bc65;hp=acff28e7a2b12a1eadbc72b4581d18abff6079c8;hpb=ac946e14e17e211d692ea8cff05a662edd6c0b42;p=citadel.git diff --git a/citadel/modules/calendar/serv_calendar.c b/citadel/modules/calendar/serv_calendar.c index acff28e7a..f8dcdf930 100644 --- a/citadel/modules/calendar/serv_calendar.c +++ b/citadel/modules/calendar/serv_calendar.c @@ -1224,31 +1224,28 @@ void ical_conflicts(long msgnum, char *partnum) { * Look for busy time in a VEVENT and add it to the supplied VFREEBUSY. * * fb The VFREEBUSY component to which we are appending - * top_level_cal The top-level VCALENDAR component which contains VEVENT to be added - * cal Initially set to the same as top_level_cal by the caller, but then we recurse + * top_level_cal The top-level VCALENDAR component which contains a VEVENT to be added */ -void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal, icalcomponent *cal) { +void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal) { + icalcomponent *cal; icalproperty *p; icalvalue *v; struct icalperiodtype this_event_period = icalperiodtype_null_period(); + icaltimetype dtstart = icaltime_null_time(); + icaltimetype dtend = icaltime_null_time(); - if (!top_level_cal) return; - if (!cal) return; + /* recur variables */ + icalproperty *rrule = NULL; + struct icalrecurrencetype recur; + icalrecur_iterator *ritr = NULL; + struct icaldurationtype dur; + int num_recur = 0; - /* Convert all time zones to UTC (FIXME this won't work with recurring events) */ - if (icalcomponent_isa(cal) == ICAL_VCALENDAR_COMPONENT) { - ical_dezonify(cal); - } + if (!top_level_cal) return; - /* Now boil it down to the VEVENT only (FIXME this won't work with recurring events) */ - if (icalcomponent_isa(cal) != ICAL_VEVENT_COMPONENT) { - ical_add_to_freebusy(fb, top_level_cal, - icalcomponent_get_first_component( - cal, ICAL_VEVENT_COMPONENT - ) - ); - return; - } + /* Find the VEVENT component containing an event */ + cal = icalcomponent_get_first_component(top_level_cal, ICAL_VEVENT_COMPONENT); + if (!cal) return; /* If this event is not opaque, the user isn't publishing it as * busy time, so don't bother doing anything else. @@ -1263,45 +1260,100 @@ void ical_add_to_freebusy(icalcomponent *fb, icalcomponent *top_level_cal, icalc } } - /* Convert the DTSTART and DTEND properties to an icalperiod. */ + /* + * Now begin calculating the event start and end times. + */ p = icalcomponent_get_first_property(cal, ICAL_DTSTART_PROPERTY); - if (p != NULL) { - this_event_period.start = icalproperty_get_dtstart(p); - } + if (!p) return; + dtstart = icalproperty_get_dtstart(p); - p = icalcomponent_get_first_property(cal, ICAL_DTEND_PROPERTY); - if (p != NULL) { - this_event_period.end = icalproperty_get_dtstart(p); - } - - /* Now add it. */ - icalcomponent_add_property(fb, icalproperty_new_freebusy(this_event_period)); - - /* Make sure the DTSTART property of the freebusy *list* is set to - * the DTSTART property of the *earliest event*. - */ - p = icalcomponent_get_first_property(fb, ICAL_DTSTART_PROPERTY); - if (p == NULL) { - icalcomponent_set_dtstart(fb, icalcomponent_get_dtstart(cal)); + if (icaltime_is_utc(dtstart)) { + dtstart.zone = icaltimezone_get_utc_timezone(); } else { - if (icaltime_compare(icalcomponent_get_dtstart(cal), icalcomponent_get_dtstart(fb)) < 0) { - icalcomponent_set_dtstart(fb, icalcomponent_get_dtstart(cal)); + dtstart.zone = icalcomponent_get_timezone(top_level_cal, + icalparameter_get_tzid( + icalproperty_get_first_parameter(p, ICAL_TZID_PARAMETER) + ) + ); + if (!dtstart.zone) { + dtstart.zone = get_default_icaltimezone(); } } - /* Make sure the DTEND property of the freebusy *list* is set to - * the DTEND property of the *latest event*. - */ - p = icalcomponent_get_first_property(fb, ICAL_DTEND_PROPERTY); - if (p == NULL) { - icalcomponent_set_dtend(fb, icalcomponent_get_dtend(cal)); + dtend = icalcomponent_get_dtend(cal); + if (!icaltime_is_null_time(dtend)) { + dur = icaltime_subtract(dtend, dtstart); } - else { - if (icaltime_compare(icalcomponent_get_dtend(cal), icalcomponent_get_dtend(fb)) > 0) { - icalcomponent_set_dtend(fb, icalcomponent_get_dtend(cal)); - } + + /* Is a recurrence specified? If so, get ready to process it... */ + rrule = ical_ctdl_get_subprop(cal, ICAL_RRULE_PROPERTY); + if (rrule) { + recur = icalproperty_get_rrule(rrule); + ritr = icalrecur_iterator_new(recur, dtstart); } + + do { + /* Convert the DTSTART and DTEND properties to an icalperiod. */ + this_event_period.start = dtstart; + + if (!icaltime_is_null_time(dtend)) { + this_event_period.end = dtend; + } + + /* Convert the timestamps to UTC. It's ok to do this because we've already expanded + * recurrences and this data is never going to get used again. + */ + this_event_period.start = icaltime_convert_to_zone( + this_event_period.start, + icaltimezone_get_utc_timezone() + ); + this_event_period.end = icaltime_convert_to_zone( + this_event_period.end, + icaltimezone_get_utc_timezone() + ); + + /* Now add it. */ + icalcomponent_add_property(fb, icalproperty_new_freebusy(this_event_period)); + + /* Make sure the DTSTART property of the freebusy *list* is set to + * the DTSTART property of the *earliest event*. + */ + p = icalcomponent_get_first_property(fb, ICAL_DTSTART_PROPERTY); + if (p == NULL) { + icalcomponent_set_dtstart(fb, this_event_period.start); + } + else { + if (icaltime_compare(this_event_period.start, icalcomponent_get_dtstart(fb)) < 0) { + icalcomponent_set_dtstart(fb, this_event_period.start); + } + } + + /* Make sure the DTEND property of the freebusy *list* is set to + * the DTEND property of the *latest event*. + */ + p = icalcomponent_get_first_property(fb, ICAL_DTEND_PROPERTY); + if (p == NULL) { + icalcomponent_set_dtend(fb, this_event_period.end); + } + else { + if (icaltime_compare(this_event_period.end, icalcomponent_get_dtend(fb)) > 0) { + icalcomponent_set_dtend(fb, this_event_period.end); + } + } + + if (rrule) { + dtstart = icalrecur_iterator_next(ritr); + if (!icaltime_is_null_time(dtend)) { + dtend = icaltime_add(dtstart, dur); + dtend.zone = dtstart.zone; + dtend.is_utc = dtstart.is_utc; + } + ++num_recur; + } + + } while ( (rrule) && (!icaltime_is_null_time(dtstart)) && (num_recur < MAX_RECUR) ) ; + icalrecur_iterator_free(ritr); } @@ -1335,9 +1387,7 @@ void ical_freebusy_backend(long msgnum, void *data) { CtdlFreeMessage(msg); if (ird.cal) { - CtdlLogPrintf(CTDL_DEBUG, "Adding event from msg #%ld...\n", msgnum); - ical_add_to_freebusy(fb, ird.cal, ird.cal); /* Add VEVENT times to VFREEBUSY */ - CtdlLogPrintf(CTDL_DEBUG, "...done.\n"); + ical_add_to_freebusy(fb, ird.cal); /* Add VEVENT times to VFREEBUSY */ icalcomponent_free(ird.cal); } } @@ -1495,7 +1545,7 @@ void ical_freebusy(char *who) { serialized_request = icalcomponent_as_ical_string_r(encaps); icalcomponent_free(encaps); /* Don't need this anymore. */ - cprintf("%d Here is the free/busy data:\n", LISTING_FOLLOWS); + cprintf("%d Free/busy for %s\n", LISTING_FOLLOWS, usbuf.fullname); if (serialized_request != NULL) { client_write(serialized_request, strlen(serialized_request)); free(serialized_request); @@ -1600,7 +1650,7 @@ void ical_getics(void) encaps = icalcomponent_new_vcalendar(); if (encaps == NULL) { - CtdlLogPrintf(CTDL_DEBUG, "ERROR: could not allocate component!\n"); + CtdlLogPrintf(CTDL_ALERT, "ERROR: could not allocate component!\n"); cprintf("%d Could not allocate memory\n", ERROR+INTERNAL_ERROR); return; } @@ -1678,7 +1728,7 @@ void ical_putics(void) } cprintf("%d Transmit data now\n", SEND_LISTING); - calstream = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0); + calstream = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0, 0); if (calstream == NULL) { return; } @@ -1999,7 +2049,7 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) /* Encapsulate the VEVENT component into a complete VCALENDAR */ encaps = icalcomponent_new_vcalendar(); if (encaps == NULL) { - CtdlLogPrintf(CTDL_DEBUG, "ERROR: could not allocate component!\n"); + CtdlLogPrintf(CTDL_ALERT, "ERROR: could not allocate component!\n"); icalcomponent_free(the_request); return; } @@ -2033,9 +2083,6 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) || (icalproperty_isa(p) == ICAL_RECURRENCEID_PROPERTY) ) { t = icalproperty_get_dtstart(p); // it's safe to use dtstart for all of them - CtdlLogPrintf(CTDL_DEBUG, "Found an icaltimetype: %s\n", - icaltime_as_ical_string(t) - ); /* First see if there's a timezone attached to the data structure itself */ if (icaltime_is_utc(t)) { @@ -2044,7 +2091,6 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) else { z = icaltime_get_timezone(t); } - if (z) CtdlLogPrintf(CTDL_DEBUG, "Timezone is present in data structure\n"); /* If not, try to determine the tzid from the parameter using attached zones */ if (!z) { @@ -2053,7 +2099,6 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) icalproperty_get_first_parameter(p, ICAL_TZID_PARAMETER) ) ); - if (z) CtdlLogPrintf(CTDL_DEBUG, "Timezone was found in attached zones\n"); } /* Still no good? Try our internal database */ @@ -2063,21 +2108,20 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) icalproperty_get_first_parameter(p, ICAL_TZID_PARAMETER) ) ); - if (z) CtdlLogPrintf(CTDL_DEBUG, "Timezone was found in internal db\n"); } if (z) { - CtdlLogPrintf(CTDL_DEBUG, "Have valid timezone, need to attach it.\n"); + /* We have a valid timezone. Good. Now we need to attach it. */ zone_already_attached = 0; for (i=0; i<5; ++i) { if (z == attached_zones[i]) { + /* We've already got this one, no need to attach another. */ ++zone_already_attached; - CtdlLogPrintf(CTDL_DEBUG, "zone already attached!!\n"); } } if ((!zone_already_attached) && (num_zones_attached < 5)) { - CtdlLogPrintf(CTDL_DEBUG, "attach zone %d\n", num_zones_attached); + /* This is a new one, so attach it. */ attached_zones[num_zones_attached++] = z; } @@ -2106,8 +2150,6 @@ void ical_send_out_invitations(icalcomponent *top_level_cal, icalcomponent *cal) icalcomponent_free(encaps); /* Don't need this anymore. */ if (serialized_request == NULL) return; - CtdlLogPrintf(CTDL_DEBUG, "SENDING INVITATIONS:\n%s\n", serialized_request); - reqsize = strlen(serialized_request) + SIZ; request_message_text = malloc(reqsize); if (request_message_text != NULL) {