[evolution-data-server] Bug 789132 - Different TZID of RECURRENCE-ID fails to match instances



commit 78fc16455dd207a4d21c5992f01ed04656607033
Author: Milan Crha <mcrha redhat com>
Date:   Thu Oct 26 19:29:46 2017 +0200

    Bug 789132 - Different TZID of RECURRENCE-ID fails to match instances

 src/calendar/libecal/e-cal-client.c    |   98 +++++++++++++++++++-------------
 src/calendar/libecal/e-cal-component.c |    2 +
 2 files changed, 61 insertions(+), 39 deletions(-)
---
diff --git a/src/calendar/libecal/e-cal-client.c b/src/calendar/libecal/e-cal-client.c
index 9b41bf1..a4143ec 100644
--- a/src/calendar/libecal/e-cal-client.c
+++ b/src/calendar/libecal/e-cal-client.c
@@ -2456,9 +2456,35 @@ compare_comp_instance (gconstpointer a,
        return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
 }
 
+static time_t
+convert_to_tt_with_zone (const ECalComponentDateTime *dt,
+                        ECalRecurResolveTimezoneFn tz_cb,
+                        gpointer tz_cb_data,
+                        icaltimezone *default_timezone)
+{
+       icaltimezone *zone = default_timezone;
+
+       if (!dt || !dt->value)
+               return (time_t) 0;
+
+       if (icaltime_is_utc (*dt->value)) {
+               zone = icaltimezone_get_utc_timezone ();
+       } else if (tz_cb && !dt->value->is_date && dt->tzid) {
+               zone = (*tz_cb) (dt->tzid, tz_cb_data);
+
+               if (!zone)
+                       zone = default_timezone;
+       }
+
+       return icaltime_as_timet_with_zone (*dt->value, zone);
+}
+
 static GSList *
 process_detached_instances (GSList *instances,
-                            GSList *detached_instances)
+                           GSList *detached_instances,
+                           ECalRecurResolveTimezoneFn tz_cb,
+                           gpointer tz_cb_data,
+                           icaltimezone *default_timezone)
 {
        struct comp_instance *ci, *cid;
        GSList *dl, *unprocessed_instances = NULL;
@@ -2468,6 +2494,7 @@ process_detached_instances (GSList *instances,
                const gchar *uid;
                gboolean processed;
                ECalComponentRange recur_id, instance_recur_id;
+               time_t d_rid, i_rid;
 
                processed = FALSE;
                recur_id.type = E_CAL_COMPONENT_RANGE_SINGLE;
@@ -2477,6 +2504,11 @@ process_detached_instances (GSList *instances,
                e_cal_component_get_uid (cid->comp, &uid);
                e_cal_component_get_recurid (cid->comp, &recur_id);
 
+               if (!recur_id.datetime.value)
+                       continue;
+
+               d_rid = convert_to_tt_with_zone (&recur_id.datetime, tz_cb, tz_cb_data, default_timezone);
+
                /* search for coincident instances already expanded */
                for (il = instances; il != NULL; il = il->next) {
                        const gchar *instance_uid;
@@ -2484,14 +2516,25 @@ process_detached_instances (GSList *instances,
 
                        ci = il->data;
                        e_cal_component_get_uid (ci->comp, &instance_uid);
-                       e_cal_component_get_recurid (ci->comp, &instance_recur_id);
+
                        if (strcmp (uid, instance_uid) == 0) {
-                               gchar *i_rid = NULL, *d_rid = NULL;
+                               e_cal_component_get_recurid (ci->comp, &instance_recur_id);
+
+                               if (!instance_recur_id.datetime.value) {
+                                       /*
+                                        * Prevent obvious segfault by ignoring missing
+                                        * recurrency ids. Real problem might be elsewhere,
+                                        * but anything is better than crashing...
+                                        */
+                                       g_warning ("UID %s: instance RECURRENCE-ID and detached instance 
RECURRENCE-ID cannot compare", uid);
+
+                                       e_cal_component_free_range (&instance_recur_id);
+                                       continue;
+                               }
 
-                               i_rid = e_cal_component_get_recurid_as_string (ci->comp);
-                               d_rid = e_cal_component_get_recurid_as_string (cid->comp);
+                               i_rid = convert_to_tt_with_zone (&instance_recur_id.datetime, tz_cb, 
tz_cb_data, default_timezone);
 
-                               if (i_rid && d_rid && strcmp (i_rid, d_rid) == 0) {
+                               if (recur_id.type == E_CAL_COMPONENT_RANGE_SINGLE && i_rid == d_rid) {
                                        g_object_unref (ci->comp);
                                        ci->comp = g_object_ref (cid->comp);
                                        ci->start = cid->start;
@@ -2499,29 +2542,7 @@ process_detached_instances (GSList *instances,
 
                                        processed = TRUE;
                                } else {
-                                       if (!instance_recur_id.datetime.value ||
-                                           !recur_id.datetime.value) {
-                                               /*
-                                                * Prevent obvious segfault by ignoring missing
-                                                * recurrency ids. Real problem might be elsewhere,
-                                                * but anything is better than crashing...
-                                                */
-                                               g_log (
-                                                       G_LOG_DOMAIN,
-                                                       G_LOG_LEVEL_CRITICAL,
-                                                       "UID %s: instance RECURRENCE-ID %s + detached 
instance RECURRENCE-ID %s: cannot compare",
-                                                       uid,
-                                                       i_rid,
-                                                       d_rid);
-
-                                               e_cal_component_free_datetime (&instance_recur_id.datetime);
-                                               g_free (i_rid);
-                                               g_free (d_rid);
-                                               continue;
-                                       }
-                                       cmp = icaltime_compare (
-                                               *instance_recur_id.datetime.value,
-                                               *recur_id.datetime.value);
+                                       cmp = i_rid == d_rid ? 0 : i_rid < d_rid ? -1 : 1;
                                        if ((recur_id.type == E_CAL_COMPONENT_RANGE_THISPRIOR && cmp <= 0) ||
                                                (recur_id.type == E_CAL_COMPONENT_RANGE_THISFUTURE && cmp >= 
0)) {
                                                ECalComponent *comp;
@@ -2537,10 +2558,8 @@ process_detached_instances (GSList *instances,
                                                ci->comp = comp;
                                        }
                                }
-                               g_free (i_rid);
-                               g_free (d_rid);
                        }
-                       e_cal_component_free_datetime (&instance_recur_id.datetime);
+                       e_cal_component_free_range (&instance_recur_id);
                }
 
                e_cal_component_free_datetime (&recur_id.datetime);
@@ -2577,19 +2596,19 @@ generate_instances (ECalClient *client,
        GSList *instances, *detached_instances = NULL;
        GSList *l;
        ECalClientPrivate *priv;
+       icaltimezone *default_zone;
 
        priv = client->priv;
 
        instances = NULL;
 
+       if (priv->default_zone)
+               default_zone = priv->default_zone;
+       else
+               default_zone = icaltimezone_get_utc_timezone ();
+
        for (l = objects; l && !g_cancellable_is_cancelled (cancellable); l = l->next) {
                ECalComponent *comp;
-               icaltimezone *default_zone;
-
-               if (priv->default_zone)
-                       default_zone = priv->default_zone;
-               else
-                       default_zone = icaltimezone_get_utc_timezone ();
 
                comp = l->data;
                if (e_cal_component_is_instance (comp)) {
@@ -2709,7 +2728,8 @@ generate_instances (ECalClient *client,
 
        if (!g_cancellable_is_cancelled (cancellable)) {
                instances = g_slist_sort (instances, compare_comp_instance);
-               instances = process_detached_instances (instances, detached_instances);
+               instances = process_detached_instances (instances, detached_instances,
+                       e_cal_client_resolve_tzid_cb, client, default_zone);
        }
 
        for (l = instances; l && !g_cancellable_is_cancelled (cancellable); l = l->next) {
diff --git a/src/calendar/libecal/e-cal-component.c b/src/calendar/libecal/e-cal-component.c
index 08f1ebd..d96a5fb 100644
--- a/src/calendar/libecal/e-cal-component.c
+++ b/src/calendar/libecal/e-cal-component.c
@@ -3816,6 +3816,8 @@ e_cal_component_get_recurid (ECalComponent *comp,
        priv = comp->priv;
        g_return_if_fail (priv->icalcomp != NULL);
 
+       recur_id->type = E_CAL_COMPONENT_RANGE_SINGLE;
+
        get_datetime (
                &priv->recur_id.recur_time,
                icalproperty_get_recurrenceid,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]