static void e_cal_util_remove_instances_ex (icalcomponent *icalcomp, struct icaltimetype rid, ECalObjModType mod, gboolean keep_rid, gboolean can_add_exrule) { icalproperty *prop; struct icaltimetype itt, recur; struct icalrecurrencetype rule; icalrecur_iterator *iter; GSList *remove_props = NULL, *rrules = NULL, *link; g_return_if_fail (icalcomp != NULL); g_return_if_fail (mod != E_CAL_OBJ_MOD_ALL); /* First remove RDATEs and EXDATEs in the indicated range. */ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RDATE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_RDATE_PROPERTY)) { struct icaldatetimeperiodtype period; period = icalproperty_get_rdate (prop); if (time_matches_rid (period.time, rid, mod) && (!keep_rid || icaltime_compare (period.time, rid) != 0)) remove_props = g_slist_prepend (remove_props, prop); } for (prop = icalcomponent_get_first_property (icalcomp, ICAL_EXDATE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_EXDATE_PROPERTY)) { itt = icalproperty_get_exdate (prop); if (time_matches_rid (itt, rid, mod) && (!keep_rid || icaltime_compare (itt, rid) != 0)) remove_props = g_slist_prepend (remove_props, prop); } for (link = remove_props; link; link = g_slist_next (link)) { prop = link->data; icalcomponent_remove_property (icalcomp, prop); } g_slist_free (remove_props); remove_props = NULL; /* If we're only removing one instance, just add an EXDATE. */ if (mod == E_CAL_OBJ_MOD_THIS) { prop = icalproperty_new_exdate (rid); icalcomponent_add_property (icalcomp, prop); return; } /* Otherwise, iterate through RRULEs */ /* FIXME: this may generate duplicate EXRULEs */ for (prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY); prop; prop = icalcomponent_get_next_property (icalcomp, ICAL_RRULE_PROPERTY)) { rrules = g_slist_prepend (rrules, prop); } for (link = rrules; link; link = g_slist_next (link)) { prop = link->data; rule = icalproperty_get_rrule (prop); iter = icalrecur_iterator_new (rule, rid); recur = icalrecur_iterator_next (iter); if (mod & E_CAL_OBJ_MOD_THIS_AND_FUTURE) { /* Truncate the rule at rid. */ if (!icaltime_is_null_time (recur)) { /* Use count if it was used */ if (rule.count > 0) { gint occurrences_count = 0; icalrecur_iterator *count_iter; struct icaltimetype count_recur; count_iter = icalrecur_iterator_new (rule, icalcomponent_get_dtstart (icalcomp)); while (count_recur = icalrecur_iterator_next (count_iter), !icaltime_is_null_time (count_recur) && occurrences_count < rule.count) { if (icaltime_compare (count_recur, rid) >= 0) break; occurrences_count++; } icalrecur_iterator_free (count_iter); if (keep_rid && icaltime_compare (count_recur, rid) == 0) occurrences_count++; /* The caller should make sure that the remove will keep at least one instance */ g_warn_if_fail (occurrences_count > 0); rule.count = occurrences_count; } else { if (keep_rid && icaltime_compare (recur, rid) == 0) rule.until = icaltime_add (rid, icalcomponent_get_duration (icalcomp)); else rule.until = rid; icaltime_adjust (&rule.until, 0, 0, 0, -1); } icalproperty_set_rrule (prop, rule); icalproperty_remove_parameter_by_name (prop, "X-EVOLUTION-ENDDATE"); } } else { /* (If recur == rid, skip to the next occurrence) */ if (!keep_rid && icaltime_compare (recur, rid) == 0) recur = icalrecur_iterator_next (iter); /* If there is a recurrence after rid, add * an EXRULE to block instances up to rid. * Otherwise, just remove the RRULE. */ if (!icaltime_is_null_time (recur)) { if (can_add_exrule) { rule.count = 0; /* iCalendar says we should just use rid * here, but Outlook/Exchange handle * UNTIL incorrectly. */ if (keep_rid && icaltime_compare (recur, rid) == 0) { struct icaldurationtype duration = icalcomponent_get_duration (icalcomp); duration.is_neg = !duration.is_neg; rule.until = icaltime_add (rid, duration); } else rule.until = icaltime_add (rid, icalcomponent_get_duration (icalcomp)); prop = icalproperty_new_exrule (rule); icalcomponent_add_property (icalcomp, prop); } } else { remove_props = g_slist_prepend (remove_props, prop); } } icalrecur_iterator_free (iter); } for (link = remove_props; link; link = g_slist_next (link)) { prop = link->data; icalcomponent_remove_property (icalcomp, prop); } g_slist_free (remove_props); g_slist_free (rrules); }
void ical_property_EXDATE(struct exchange2ical *exchange2ical) { uint32_t i; uint32_t j; uint8_t modified; struct icaltimetype icaltime; struct icaltimetype dttime; icalproperty *prop; struct RecurrencePattern *pat = exchange2ical->RecurrencePattern; /* Sanity check */ if (exchange2ical->Recurring && (*exchange2ical->Recurring == 0x0)) return; if (!pat) return; if (!pat->DeletedInstanceCount) return; for (i = 0; i < pat->DeletedInstanceCount; i++) { modified=0; if(pat->ModifiedInstanceDates && pat->ModifiedInstanceCount){ for(j=0; j < pat->ModifiedInstanceCount; j++){ if(pat->ModifiedInstanceDates[j]==pat->DeletedInstanceDates[i]){ modified=1; break; } } } /* If this is an all-day appointment */ if (!modified && exchange2ical->apptSubType && (*exchange2ical->apptSubType == 0x1)) { struct tm tm; tm = get_tm_from_minutes_UTC(pat->DeletedInstanceDates[i]); icaltime= get_icaldate_from_tm(&tm); prop = icalproperty_new_exdate(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); } else if (!modified){ /* number of minutes between midnight of the specified * day and midnight, January 1, 1601 */ struct tm tm; tm = get_tm_from_minutes_UTC(pat->DeletedInstanceDates[i]); icaltime= get_icaltimetype_from_tm(&tm); if (exchange2ical->TimeZoneDesc) { /*Get time from dtstart*/ if (exchange2ical->apptEndWhole){ dttime = get_icaltime_from_FILETIME(exchange2ical->apptStartWhole); icaltime.hour = dttime.hour; icaltime.minute = dttime.minute; } prop = icalproperty_new_exdate(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); icalparameter *tzid = icalparameter_new_tzid(exchange2ical->TimeZoneDesc); icalproperty_add_parameter(prop, tzid); } else { /*Get time from dtstart*/ icaltime.is_utc = 1; if (exchange2ical->apptEndWhole){ dttime = get_icaltime_from_FILETIME_UTC(exchange2ical->apptStartWhole); icaltime.hour = dttime.hour; icaltime.minute = dttime.minute; } prop = icalproperty_new_exdate(icaltime); icalcomponent_add_property(exchange2ical->vevent, prop); } } } }