Skip to content
Commits on Source (6)
......@@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.1)
cmake_policy(VERSION 3.1)
project(evolution-ews
VERSION 3.40.1
VERSION 3.40.2
LANGUAGES C)
set(PROJECT_BUGREPORT "https://gitlab.gnome.org/GNOME/evolution-ews/issues/")
......
Evolution-EWS 3.40.2 2021-06-04
-------------------------------
Bug Fixes:
I#152 - Declining Single Calendar Event Results in Declining the Whole Series (Milan Crha)
Miscellaneous:
Calendar: Clamp the timezone component when saving meeting time (Milan Crha)
Translations:
Daniel Șerbănescu (ro)
Evolution-EWS 3.40.1 2021-04-30
-------------------------------
......
This diff is collapsed.
......@@ -641,9 +641,10 @@ ewscal_set_timezone (ESoapMessage *msg,
void
ewscal_set_meeting_timezone (ESoapMessage *msg,
ICalTimezone *icaltz)
ICalTimezone *icaltz,
ICalComponent *icomp)
{
ICalComponent *comp;
ICalComponent *comp, *copy;
ICalComponent *xstd, *xdaylight;
ICalDuration *duration;
const gchar *location;
......@@ -657,14 +658,18 @@ ewscal_set_meeting_timezone (ESoapMessage *msg,
if (!comp)
return;
/* Clamp the time zone component, to get the relevant part only */
copy = i_cal_component_clone (comp);
g_clear_object (&comp);
comp = copy;
e_cal_util_clamp_vtimezone_by_component (comp, icomp);
/* Exchange needs a BaseOffset, followed by either *both*
* Standard and Daylight zones, or neither of them. If there's
* more than one STANDARD or DAYLIGHT component in the VTIMEZONE,
* we ignore the extra. So fully-specified timezones including
* historical DST rules cannot be handled by Exchange. */
/* FIXME: Walk through them all to find the *latest* ones, like
* i_cal_timezone_get_tznames_from_vtimezone() does. */
xstd = i_cal_component_get_first_component (comp, I_CAL_XSTANDARD_COMPONENT);
xdaylight = i_cal_component_get_first_component (comp, I_CAL_XDAYLIGHT_COMPONENT);
......@@ -1284,7 +1289,7 @@ convert_vevent_calcomp_to_xml (ESoapMessage *msg,
} else {
e_ews_message_replace_server_version (msg, E_EWS_EXCHANGE_2007_SP1);
ewscal_set_meeting_timezone (msg, tzid_start);
ewscal_set_meeting_timezone (msg, tzid_start, icomp);
}
e_soap_message_end_element (msg); /* "CalendarItem" */
......@@ -1523,31 +1528,14 @@ convert_vevent_component_to_updatexml (ESoapMessage *msg,
gboolean dt_start_changed = FALSE, dt_end_changed = FALSE, dt_changed;
gboolean dt_start_changed_timezone_name = FALSE, dt_end_changed_timezone_name = FALSE;
gboolean satisfies, rsvp_requested = TRUE, is_all_day_event = FALSE;
gchar *recid;
/* Modifying a recurring meeting ? */
if (e_cal_util_component_has_property (icomp_old, I_CAL_RRULE_PROPERTY)) {
/* A single occurrence ? */
prop = i_cal_component_get_first_property (icomp, I_CAL_RECURRENCEID_PROPERTY);
if (prop != NULL) {
recid = i_cal_property_get_value_as_string (prop);
e_ews_message_start_item_change (
msg,
E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM,
convert_data->item_id,
convert_data->change_key,
e_cal_backend_ews_rid_to_index (
convert_data->default_zone,
recid,
icomp_old,
NULL));
g_object_unref (prop);
g_free (recid);
} else {
e_ews_message_start_item_change (
msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
convert_data->item_id, convert_data->change_key, 0);
}
if (convert_data->change_type == E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM && convert_data->index > 0) {
e_ews_message_start_item_change (
msg,
convert_data->change_type,
convert_data->item_id,
convert_data->change_key,
convert_data->index);
} else {
e_ews_message_start_item_change (msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
convert_data->item_id, convert_data->change_key, 0);
......@@ -1836,7 +1824,7 @@ convert_vevent_component_to_updatexml (ESoapMessage *msg,
e_ews_message_replace_server_version (msg, E_EWS_EXCHANGE_2007_SP1);
e_ews_message_start_set_item_field (msg, "MeetingTimeZone", "calendar", "CalendarItem");
ewscal_set_meeting_timezone (msg, tzid_start ? tzid_start : convert_data->default_zone);
ewscal_set_meeting_timezone (msg, tzid_start ? tzid_start : convert_data->default_zone, icomp);
e_ews_message_end_set_item_field (msg);
}
......
......@@ -42,7 +42,7 @@ const gchar *e_ews_collect_organizer (ICalComponent *comp);
void e_ews_collect_attendees (ICalComponent *comp, GSList **required, GSList **optional, GSList **resource, gboolean *out_rsvp_requested);
void ewscal_set_timezone (ESoapMessage *msg, const gchar *name, EEwsCalendarTimeZoneDefinition *tzd);
void ewscal_set_meeting_timezone (ESoapMessage *msg, ICalTimezone *icaltz);
void ewscal_set_meeting_timezone (ESoapMessage *msg, ICalTimezone *icaltz, ICalComponent *icomp);
void ewscal_set_reccurence (ESoapMessage *msg, ICalProperty *rrule, ICalTime *dtstart);
void ewscal_set_reccurence_exceptions (ESoapMessage *msg, ICalComponent *comp);
gchar *e_ews_extract_attachment_id_from_uri (const gchar *uri);
......
......@@ -839,6 +839,15 @@ ecb_ews_item_to_component_sync (ECalBackendEws *cbews,
}
g_object_unref (dt);
dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, icomp, I_CAL_RECURRENCEID_PROPERTY, i_cal_property_get_recurrenceid);
if (dt && !i_cal_time_is_date (dt)) {
i_cal_time_convert_to_zone_inplace (dt, zone);
i_cal_component_set_recurrenceid (icomp, dt);
}
g_clear_object (&dt);
}
g_free (new_tzid);
......@@ -988,6 +997,18 @@ ecb_ews_item_to_component_sync (ECalBackendEws *cbews,
i_cal_property_remove_parameter_by_kind (prop, I_CAL_TZID_PARAMETER);
}
for (prop = i_cal_component_get_first_property (icomp, I_CAL_RECURRENCEID_PROPERTY);
prop;
g_object_unref (prop), prop = i_cal_component_get_next_property (icomp, I_CAL_RECURRENCEID_PROPERTY)) {
g_clear_object (&itt);
itt = i_cal_property_get_recurrenceid (prop);
i_cal_time_set_is_date (itt, TRUE);
i_cal_property_set_recurrenceid (prop, itt);
i_cal_property_remove_parameter_by_kind (prop, I_CAL_TZID_PARAMETER);
}
}
g_clear_object (&itt);
......@@ -2530,10 +2551,11 @@ ecb_ews_remove_item_sync (ECalBackendEws *cbews,
if (rid && !*rid)
rid = NULL;
if (!e_cal_cache_get_component (cal_cache, uid, rid, &comp, cancellable, error) ||
(rid && !e_cal_cache_get_component (cal_cache, uid, NULL, &parent, cancellable, error))) {
if (!e_cal_cache_get_component (cal_cache, uid, rid, &comp, cancellable, NULL) ||
(rid && !e_cal_cache_get_component (cal_cache, uid, NULL, &parent, cancellable, NULL))) {
if (!parent && !comp) {
g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
if (!g_cancellable_set_error_if_cancelled (cancellable, error))
g_propagate_error (error, ECC_ERROR (E_CAL_CLIENT_ERROR_OBJECT_NOT_FOUND));
return FALSE;
}
}
......@@ -2690,6 +2712,101 @@ ecb_ews_pick_all_tzids_out (ECalBackendEws *cbews,
i_cal_component_foreach_tzid (icomp, tzid_cb, &cbd);
}
static gboolean
ecb_ews_get_change_type_is_instance (ECalBackendEws *cbews,
ICalComponent *vcalendar,
ICalComponent *subcomp,
GCancellable *cancellable,
EEwsItemChangeType *out_change_type,
gint *out_index)
{
gboolean res = FALSE;
gchar *rid;
g_return_val_if_fail (out_change_type != NULL, FALSE);
g_return_val_if_fail (out_index != NULL, FALSE);
if (!e_cal_util_component_is_instance (subcomp))
return FALSE;
rid = e_cal_util_component_get_recurid_as_string (subcomp);
if (rid && *rid) {
ICalComponent *main_comp = NULL;
if (vcalendar) {
ICalComponentKind kind;
ICalCompIter *iter;
const gchar *uid;
uid = i_cal_component_get_uid (subcomp);
kind = i_cal_component_isa (subcomp);
iter = i_cal_component_begin_component (vcalendar, kind);
main_comp = i_cal_comp_iter_deref (iter);
while (main_comp) {
if (g_strcmp0 (uid, i_cal_component_get_uid (main_comp)) == 0 &&
!e_cal_util_component_is_instance (main_comp) &&
e_cal_util_component_has_rrules (main_comp)) {
break;
}
g_object_unref (main_comp);
main_comp = i_cal_comp_iter_next (iter);
}
g_clear_object (&iter);
}
if (!main_comp) {
ECalCache *cal_cache;
ECalComponent *existing = NULL;
cal_cache = e_cal_meta_backend_ref_cache (E_CAL_META_BACKEND (cbews));
if (cal_cache && e_cal_cache_get_component (cal_cache, i_cal_component_get_uid (subcomp), NULL, &existing, cancellable, NULL) && existing) {
main_comp = e_cal_component_get_icalcomponent (existing);
g_object_ref (main_comp);
g_object_unref (existing);
}
g_clear_object (&cal_cache);
}
if (main_comp) {
gchar *mid, *sid;
mid = e_cal_util_component_dup_x_property (main_comp, "X-EVOLUTION-ITEMID");
sid = e_cal_util_component_dup_x_property (subcomp, "X-EVOLUTION-ITEMID");
/* Already detached instances do not need to do this */
if (mid && g_strcmp0 (mid, sid) == 0) {
gint index;
index = e_cal_backend_ews_rid_to_index (
ecb_ews_get_timezone_from_icomponent (cbews, main_comp),
rid,
main_comp,
NULL);
if (index > 0) {
res = TRUE;
*out_change_type = E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM;
*out_index = index;
}
}
g_clear_object (&main_comp);
g_free (mid);
g_free (sid);
}
}
g_free (rid);
return res;
}
static gboolean
ecb_ews_modify_item_sync (ECalBackendEws *cbews,
guint32 opflags,
......@@ -2839,6 +2956,12 @@ ecb_ews_modify_item_sync (ECalBackendEws *cbews,
const gchar *send_meeting_invitations;
const gchar *send_or_save;
if (!ecb_ews_get_change_type_is_instance (cbews, NULL, e_cal_component_get_icalcomponent (comp),
cancellable, &convert_data.change_type, &convert_data.index)) {
convert_data.change_type = E_EWS_ITEMCHANGE_TYPE_ITEM;
convert_data.index = -1;
}
ews_settings = ecb_ews_get_collection_settings (cbews);
convert_data.connection = cbews->priv->cnc;
......@@ -3736,6 +3859,51 @@ ecb_ews_do_method_request_publish_reply (ECalBackendEws *cbews,
ecb_ews_receive_objects_no_exchange_mail (cbews, vcalendar, subcomp, &ids, cancellable, &local_error);
} else {
EwsCalendarConvertData convert_data = { 0 };
EEwsItemChangeType change_type = E_EWS_ITEMCHANGE_TYPE_ITEM;
gint index = -1;
/* Need to detach an instance before modifying the response on it */
if (ecb_ews_get_change_type_is_instance (cbews, vcalendar, subcomp, cancellable, &change_type, &index)) {
EwsCalendarConvertData sub_convert_data = { 0 };
CamelEwsSettings *ews_settings;
ews_settings = ecb_ews_get_collection_settings (cbews);
sub_convert_data.change_type = change_type;
sub_convert_data.index = index;
sub_convert_data.connection = cbews->priv->cnc;
sub_convert_data.timezone_cache = E_TIMEZONE_CACHE (cbews);
sub_convert_data.user_email = camel_ews_settings_dup_email (ews_settings);
sub_convert_data.comp = comp;
sub_convert_data.old_comp = comp; /* no change, just detach the instance */
sub_convert_data.item_id = item_id;
sub_convert_data.change_key = change_key;
sub_convert_data.default_zone = i_cal_timezone_get_utc_timezone ();
e_ews_connection_update_items_sync (cbews->priv->cnc, EWS_PRIORITY_MEDIUM,
"AlwaysOverwrite", "SaveOnly", "SendToNone", cbews->priv->folder_id,
e_cal_backend_ews_convert_component_to_updatexml, &sub_convert_data,
&ids, cancellable, &local_error);
g_free (sub_convert_data.user_email);
if (!local_error && ids && !ids->next) {
EEwsItem *item = ids->data;
const EwsId *id = e_ews_item_get_id (item);
if (id) {
g_free (item_id);
g_free (change_key);
item_id = g_strdup (id->id);
change_key = g_strdup (id->change_key);
}
}
g_clear_error (&local_error);
g_slist_free_full (ids, g_object_unref);
ids = NULL;
}
convert_data.timezone_cache = E_TIMEZONE_CACHE (cbews);
convert_data.response_type = (gchar *) response_type;
......@@ -3885,11 +4053,12 @@ ecb_ews_receive_objects_sync (ECalBackendSync *sync_backend,
ECalBackendEws *cbews;
ECalBackend *cal_backend;
CamelEwsSettings *ews_settings;
ICalComponent *icomp, *subcomp;
ICalComponent *icomp, *subcomp, *decline_main = NULL;
ICalComponentKind kind;
GHashTable *aliases;
gchar *user_email;
gboolean success = TRUE, do_refresh = FALSE;
gboolean decline_main_rsvp_requested = FALSE;
g_return_if_fail (E_IS_CAL_BACKEND_EWS (sync_backend));
......@@ -3934,9 +4103,20 @@ ecb_ews_receive_objects_sync (ECalBackendSync *sync_backend,
response_type = ecb_ews_get_current_user_meeting_reponse (cbews, subcomp, user_email, aliases, &rsvp_requested);
rsvp_requested = rsvp_requested && !(opflags & E_CAL_OPERATION_FLAG_DISABLE_ITIP_MESSAGE);
/* When the main component is declined, then decline also all detached instances and do them
first, because the main component decline removes the whole series from the calendar. */
if (!decline_main && response_type && g_ascii_strcasecmp (response_type, "DECLINED") == 0 &&
!e_cal_util_component_is_instance (subcomp)) {
decline_main = g_object_ref (subcomp);
decline_main_rsvp_requested = rsvp_requested;
g_free (response_type);
continue;
}
comp = e_cal_component_new_from_icalcomponent (i_cal_component_clone (subcomp));
success = ecb_ews_do_method_request_publish_reply (cbews, icomp, comp, subcomp, response_type, user_email, rsvp_requested, cancellable, error);
success = ecb_ews_do_method_request_publish_reply (cbews, icomp, comp, subcomp,
decline_main ? "DECLINED" : response_type, user_email, rsvp_requested, cancellable, error);
do_refresh = TRUE;
......@@ -3944,6 +4124,21 @@ ecb_ews_receive_objects_sync (ECalBackendSync *sync_backend,
g_free (response_type);
}
g_clear_object (&subcomp);
if (decline_main && success) {
ECalComponent *comp;
comp = e_cal_component_new_from_icalcomponent (i_cal_component_clone (decline_main));
success = ecb_ews_do_method_request_publish_reply (cbews, icomp, comp, decline_main,
"DECLINED", user_email, decline_main_rsvp_requested, cancellable, error);
do_refresh = TRUE;
g_object_unref (comp);
}
g_clear_object (&decline_main);
break;
case I_CAL_METHOD_COUNTER:
/*
......