[evolution-ews] Calendar invites added with the wrong time zone



commit 06b9eff5dbd6f9259214cfc9a3a08de92b031d9a
Author: Milan Crha <mcrha redhat com>
Date:   Tue Sep 4 11:04:27 2018 +0200

    Calendar invites added with the wrong time zone
    
    When a non-libical timezone had been used in a meeting invitation
    component or in an iCalendar object being imported, it were not
    found in the local timezone cache, which caused reset of the timezone
    to UTC.
    
    Reported downstream at:
    https://bugzilla.redhat.com/show_bug.cgi?id=1624343

 src/calendar/e-cal-backend-ews-utils.c | 56 +++++++++++++++++++++++-----------
 src/calendar/e-cal-backend-ews-utils.h |  4 ++-
 src/calendar/e-cal-backend-ews.c       | 20 +++++++-----
 3 files changed, 54 insertions(+), 26 deletions(-)
---
diff --git a/src/calendar/e-cal-backend-ews-utils.c b/src/calendar/e-cal-backend-ews-utils.c
index 63a96d67..84fcc209 100644
--- a/src/calendar/e-cal-backend-ews-utils.c
+++ b/src/calendar/e-cal-backend-ews-utils.c
@@ -178,7 +178,8 @@ e_cal_backend_ews_tz_util_get_msdn_equivalent (const gchar *ical_tz_location)
 {
        const gchar *msdn_tz_location = NULL;
 
-       g_return_val_if_fail (ical_tz_location != NULL, NULL);
+       if (!ical_tz_location || !*ical_tz_location)
+               return NULL;
 
        g_rec_mutex_lock (&tz_mutex);
        if (ical_to_msdn == NULL) {
@@ -199,7 +200,8 @@ e_cal_backend_ews_tz_util_get_ical_equivalent (const gchar *msdn_tz_location)
 {
        const gchar *ical_tz_location = NULL;
 
-       g_return_val_if_fail (msdn_tz_location != NULL, NULL);
+       if (!msdn_tz_location || !*msdn_tz_location)
+               return NULL;
 
        g_rec_mutex_lock (&tz_mutex);
        if (msdn_to_ical == NULL) {
@@ -330,6 +332,7 @@ void
 ews_set_alarm (ESoapMessage *msg,
                ECalComponent *comp,
               ETimezoneCache *timezone_cache,
+              icalcomponent *vcalendar,
               gboolean with_due_by)
 {
        /* We know there would be only a single alarm in EWS calendar item */
@@ -351,7 +354,7 @@ ews_set_alarm (ESoapMessage *msg,
                        if (with_due_by) {
                                struct icaltimetype dtstart;
 
-                               dtstart = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, 
e_cal_component_get_icalcomponent (comp),
+                               dtstart = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, 
vcalendar, e_cal_component_get_icalcomponent (comp),
                                        ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
 
                                if (!icaltime_is_null_time (dtstart)) {
@@ -1121,16 +1124,16 @@ convert_vevent_calcomp_to_xml (ESoapMessage *msg,
        /* set alarms */
        has_alarms = e_cal_component_has_alarms (comp);
        if (has_alarms)
-               ews_set_alarm (msg, comp, convert_data->timezone_cache, FALSE);
+               ews_set_alarm (msg, comp, convert_data->timezone_cache, convert_data->vcalendar, FALSE);
        else
                e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");
 
        /* start time, end time and meeting time zone */
-       dtstart = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, 
ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+       dtstart = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, 
convert_data->vcalendar, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
        tzid_start = (icaltimezone *) (dtstart.zone ? dtstart.zone : convert_data->default_zone);
        ical_location_start = icaltimezone_get_location (tzid_start);
 
-       dtend = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, 
ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
+       dtend = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, 
convert_data->vcalendar, icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
        tzid_end = (icaltimezone *) (dtend.zone ? dtend.zone : convert_data->default_zone);
        ical_location_end = icaltimezone_get_location (tzid_end);
 
@@ -1290,7 +1293,7 @@ convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
 
        prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
        if (prop) {
-               dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, 
ICAL_DUE_PROPERTY, icalproperty_get_due);
+               dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, 
convert_data->vcalendar, icalcomp, ICAL_DUE_PROPERTY, icalproperty_get_due);
                e_ews_cal_utils_set_time (msg, "DueDate", &dt, TRUE);
        }
 
@@ -1305,7 +1308,7 @@ convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
 
        prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
        if (prop) {
-               dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, 
ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+               dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, 
convert_data->vcalendar, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
                e_ews_cal_utils_set_time (msg, "StartDate", &dt, TRUE);
        }
 
@@ -1328,7 +1331,7 @@ convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
                ECalComponent *comp = e_cal_component_new_from_icalcomponent (icalcomponent_new_clone 
(icalcomp));
 
                if (comp && e_cal_component_has_alarms (comp)) {
-                       ews_set_alarm (msg, comp, convert_data->timezone_cache, TRUE);
+                       ews_set_alarm (msg, comp, convert_data->timezone_cache, convert_data->vcalendar, 
TRUE);
                } else {
                        has_alarms = FALSE;
                }
@@ -1582,8 +1585,8 @@ convert_vevent_component_to_updatexml (ESoapMessage *msg,
 
        /* Update other properties allowed only for meeting organizers*/
        /*meeting dates*/
-       dtstart = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, 
ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
-       dtstart_old = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp_old, 
ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+       dtstart = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, 
convert_data->vcalendar, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+       dtstart_old = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, 
convert_data->vcalendar, icalcomp_old, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
        dt_start_changed = icaltime_compare (dtstart, dtstart_old) != 0;
        if (dtstart.zone != NULL) {
                tzid_start = (icaltimezone *) dtstart.zone;
@@ -1594,8 +1597,8 @@ convert_vevent_component_to_updatexml (ESoapMessage *msg,
                        dt_start_changed_timezone_name = TRUE;
        }
 
-       dtend = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, 
ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
-       dtend_old = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp_old, 
ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
+       dtend = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, 
convert_data->vcalendar, icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
+       dtend_old = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, 
convert_data->vcalendar, icalcomp_old, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
        dt_end_changed = icaltime_compare (dtend, dtend_old) != 0;
        if (dtend.zone != NULL) {
                tzid_end = (icaltimezone *) dtend.zone;
@@ -1818,7 +1821,7 @@ convert_vtodo_component_to_updatexml (ESoapMessage *msg,
 
        prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
        if (prop) {
-               dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, 
ICAL_DUE_PROPERTY, icalproperty_get_due);
+               dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, 
convert_data->vcalendar, icalcomp, ICAL_DUE_PROPERTY, icalproperty_get_due);
                e_ews_message_start_set_item_field (msg, "DueDate", "task", "Task");
                e_ews_cal_utils_set_time (msg, "DueDate", &dt, TRUE);
                e_ews_message_end_set_item_field (msg);
@@ -1848,7 +1851,7 @@ convert_vtodo_component_to_updatexml (ESoapMessage *msg,
 
        prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
        if (prop) {
-               dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, icalcomp, 
ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+               dt = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, 
convert_data->vcalendar, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
                e_ews_message_start_set_item_field (msg, "StartDate", "task", "Task");
                e_ews_cal_utils_set_time (msg, "StartDate", &dt, TRUE);
                e_ews_message_end_set_item_field (msg);
@@ -2090,6 +2093,7 @@ e_cal_backend_ews_prepare_accept_item_request (ESoapMessage *msg,
 
 struct icaltimetype
 e_cal_backend_ews_get_datetime_with_zone (ETimezoneCache *timezone_cache,
+                                         icalcomponent *vcalendar,
                                          icalcomponent *comp,
                                          icalproperty_kind prop_kind,
                                          struct icaltimetype (* get_func) (const icalproperty *prop))
@@ -2097,7 +2101,7 @@ e_cal_backend_ews_get_datetime_with_zone (ETimezoneCache *timezone_cache,
        struct icaltimetype dt = icaltime_null_time ();
        icalproperty *prop;
        icalparameter *param;
-       const gchar *tzid;
+       const gchar *tzid, *eqv_tzid;
 
        g_return_val_if_fail (E_IS_TIMEZONE_CACHE (timezone_cache), dt);
        g_return_val_if_fail (comp != NULL, dt);
@@ -2113,6 +2117,8 @@ e_cal_backend_ews_get_datetime_with_zone (ETimezoneCache *timezone_cache,
            icaltime_is_null_time (dt))
                return dt;
 
+       dt.zone = NULL;
+
        param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
        if (!param)
                return dt;
@@ -2121,7 +2127,23 @@ e_cal_backend_ews_get_datetime_with_zone (ETimezoneCache *timezone_cache,
        if (!tzid || !*tzid)
                return dt;
 
-       dt.zone = e_timezone_cache_get_timezone (timezone_cache, tzid);
+       eqv_tzid = e_cal_backend_ews_tz_util_get_ical_equivalent (tzid);
+
+       if (!eqv_tzid) {
+               /* Unlikely to work, but just in case */
+               eqv_tzid = e_cal_backend_ews_tz_util_get_msdn_equivalent (tzid);
+               if (eqv_tzid)
+                       eqv_tzid = e_cal_backend_ews_tz_util_get_ical_equivalent (eqv_tzid);
+       }
+
+       if (eqv_tzid)
+               dt.zone = e_timezone_cache_get_timezone (timezone_cache, eqv_tzid);
+
+       if (!dt.zone)
+               dt.zone = e_timezone_cache_get_timezone (timezone_cache, tzid);
+
+       if (!dt.zone)
+               dt.zone = vcalendar ? icalcomponent_get_timezone (vcalendar, tzid) : NULL;
 
        return dt;
 }
diff --git a/src/calendar/e-cal-backend-ews-utils.h b/src/calendar/e-cal-backend-ews-utils.h
index 04f1cba7..6501485f 100644
--- a/src/calendar/e-cal-backend-ews-utils.h
+++ b/src/calendar/e-cal-backend-ews-utils.h
@@ -47,6 +47,7 @@ typedef struct {
        ECalComponent *comp;
        ECalComponent *old_comp;
        icalcomponent *icalcomp;
+       icalcomponent *vcalendar; /* can be NULL, parent of icalcomp, where timezones can be eventually found 
*/
        gchar *item_id;
        gchar *change_key;
        EEwsItemChangeType change_type;
@@ -63,7 +64,7 @@ void ewscal_set_meeting_timezone (ESoapMessage *msg, icaltimezone *icaltz);
 void ewscal_set_reccurence (ESoapMessage *msg, icalproperty *rrule, icaltimetype *dtstart);
 void ewscal_set_reccurence_exceptions (ESoapMessage *msg, icalcomponent *comp);
 gchar *e_ews_extract_attachment_id_from_uri (const gchar *uri);
-void ews_set_alarm (ESoapMessage *msg, ECalComponent *comp, ETimezoneCache *timezone_cache, gboolean 
with_due_by);
+void ews_set_alarm (ESoapMessage *msg, ECalComponent *comp, ETimezoneCache *timezone_cache, icalcomponent 
*vcalendar, gboolean with_due_by);
 gint ews_get_alarm (ECalComponent *comp);
 void e_ews_clean_icalcomponent (icalcomponent *icalcomp);
 
@@ -82,6 +83,7 @@ guint e_cal_backend_ews_rid_to_index (icaltimezone *timezone, const gchar *rid,
 
 struct icaltimetype
                e_cal_backend_ews_get_datetime_with_zone        (ETimezoneCache *timezone_cache,
+                                                                icalcomponent *vcalendar,
                                                                 icalcomponent *comp,
                                                                 icalproperty_kind prop_kind,
                                                                 struct icaltimetype (* get_func) (const 
icalproperty *prop));
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index 24cf222b..5176e399 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -499,7 +499,7 @@ ecb_ews_item_to_component_sync (ECalBackendEws *cbews,
                                        icalcomponent *alarm_icalcomp;
                                        struct icaltimetype dtstart, due_by;
 
-                                       dtstart = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, 
icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+                                       dtstart = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, 
NULL, icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
                                        due_by = icaltime_from_timet_with_zone (reminder_due_by, 0, utc_zone);
 
                                        if (icaltime_is_null_time (dtstart)) {
@@ -638,7 +638,7 @@ ecb_ews_item_to_component_sync (ECalBackendEws *cbews,
                        if (start_zone != NULL) {
                                icalcomp = icalcomponent_get_first_component (vcomp, kind);
 
-                               dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, icalcomp, 
ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+                               dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, 
icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
                                dt = icaltime_convert_to_zone (dt, start_zone);
                                icalcomponent_set_dtstart (icalcomp, dt);
 
@@ -646,7 +646,7 @@ ecb_ews_item_to_component_sync (ECalBackendEws *cbews,
                                e_timezone_cache_add_timezone (timezone_cache, start_zone);
 
                                if (end_zone != NULL) {
-                                       dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, 
icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
+                                       dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, 
icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
                                        dt = icaltime_convert_to_zone (dt, end_zone);
                                        icalcomponent_set_dtend (icalcomp, dt);
 
@@ -714,11 +714,11 @@ ecb_ews_item_to_component_sync (ECalBackendEws *cbews,
                                zone = icaltimezone_get_builtin_timezone (tzid);
 
                        if (zone != NULL) {
-                               dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, icalcomp, 
ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+                               dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, 
icalcomp, ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
                                dt = icaltime_convert_to_zone (dt, zone);
                                icalcomponent_set_dtstart (icalcomp, dt);
 
-                               dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, icalcomp, 
ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
+                               dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, 
icalcomp, ICAL_DTEND_PROPERTY, icalproperty_get_dtend);
                                dt = icaltime_convert_to_zone (dt, zone);
                                icalcomponent_set_dtend (icalcomp, dt);
                        }
@@ -2989,7 +2989,7 @@ ecb_ews_send_cancellation_email_sync (ECalBackendEws *cbews,
        icalcomponent_add_property (vevent, icalproperty_new_status (ICAL_STATUS_CANCELLED));
        prop = icalcomponent_get_first_property (vevent, ICAL_METHOD_PROPERTY);
        if (prop != NULL) icalcomponent_remove_property (vevent, prop);
-       dt = e_cal_backend_ews_get_datetime_with_zone (E_TIMEZONE_CACHE (cbews), vevent, 
ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
+       dt = e_cal_backend_ews_get_datetime_with_zone (E_TIMEZONE_CACHE (cbews), NULL, vevent, 
ICAL_DTSTART_PROPERTY, icalproperty_get_dtstart);
        icaltz = (icaltimezone *)
                (dt.zone ? dt.zone : ecb_ews_get_timezone_from_ical_component (cbews, vevent));
        vtz = icaltimezone_get_component (icaltz);
@@ -3032,6 +3032,7 @@ ecb_ews_send_cancellation_email_sync (ECalBackendEws *cbews,
 
 static void
 ecb_ews_receive_objects_no_exchange_mail (ECalBackendEws *cbews,
+                                         icalcomponent *vcalendar,
                                          icalcomponent *subcomp,
                                          GSList **ids,
                                          GCancellable *cancellable,
@@ -3043,6 +3044,7 @@ ecb_ews_receive_objects_no_exchange_mail (ECalBackendEws *cbews,
        convert_data.connection = cbews->priv->cnc;
        convert_data.timezone_cache = E_TIMEZONE_CACHE (cbews);
        convert_data.icalcomp = subcomp;
+       convert_data.vcalendar = vcalendar;
        convert_data.default_zone = icaltimezone_get_utc_timezone ();
 
        fid = e_ews_folder_id_new (cbews->priv->folder_id, NULL, FALSE);
@@ -3287,6 +3289,7 @@ ecb_ews_get_item_accept_id (ECalComponent *comp,
 
 static gboolean
 ecb_ews_do_method_request_publish_reply (ECalBackendEws *cbews,
+                                        icalcomponent *vcalendar,
                                         ECalComponent *comp,
                                         icalcomponent *subcomp,
                                         const gchar *response_type,
@@ -3317,7 +3320,7 @@ ecb_ews_do_method_request_publish_reply (ECalBackendEws *cbews,
        while (pass < 2) {
                /*in case we do not have item id we will create item with mime content only*/
                if (!item_id || (response_type && g_ascii_strcasecmp (response_type, "NEEDS-ACTION") == 0)) {
-                       ecb_ews_receive_objects_no_exchange_mail (cbews, subcomp, &ids, cancellable, 
&local_error);
+                       ecb_ews_receive_objects_no_exchange_mail (cbews, vcalendar, subcomp, &ids, 
cancellable, &local_error);
                } else {
                        EwsCalendarConvertData convert_data = { 0 };
 
@@ -3426,6 +3429,7 @@ ecb_ews_do_method_request_publish_reply (ECalBackendEws *cbews,
                        }
 
                        convert_data.timezone_cache = E_TIMEZONE_CACHE (cbews);
+                       convert_data.vcalendar = vcalendar;
 
                        e_ews_connection_update_items_sync (
                                cbews->priv->cnc,
@@ -3511,7 +3515,7 @@ ecb_ews_receive_objects_sync (ECalBackendSync *sync_backend,
 
                        comp = e_cal_component_new_from_icalcomponent (icalcomponent_new_clone (subcomp));
 
-                       success = ecb_ews_do_method_request_publish_reply (cbews, comp, subcomp, 
response_type, user_email, rsvp_requested, cancellable, error);
+                       success = ecb_ews_do_method_request_publish_reply (cbews, icalcomp, comp, subcomp, 
response_type, user_email, rsvp_requested, cancellable, error);
 
                        do_refresh = TRUE;
 


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