Hello community, here is the log from the commit of package evolution-ews for openSUSE:Factory checked in at 2020-06-08 23:48:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/evolution-ews (Old) and /work/SRC/openSUSE:Factory/.evolution-ews.new.3606 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "evolution-ews" Mon Jun 8 23:48:19 2020 rev:103 rq:811424 version:3.36.3 Changes: -------- --- /work/SRC/openSUSE:Factory/evolution-ews/evolution-ews.changes 2020-04-29 20:42:54.171724068 +0200 +++ /work/SRC/openSUSE:Factory/.evolution-ews.new.3606/evolution-ews.changes 2020-06-08 23:49:12.662323020 +0200 @@ -1,0 +2,10 @@ +Fri May 29 19:50:00 UTC 2020 - Bjørn Lie <[email protected]> + +- Update to version 3.36.3: + + EEwsNotification: Change how subscription to server change + notifications work + + Add parameter check into ews_get_error_code() + + Bugs fixed: glgo#GNOME/evolution-ews#99, + glgo#GNOME/evolution-ews#102, glgo#GNOME/evolution-ews#103. + +------------------------------------------------------------------- Old: ---- evolution-ews-3.36.2.tar.xz New: ---- evolution-ews-3.36.3.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ evolution-ews.spec ++++++ --- /var/tmp/diff_new_pack.4UJXNP/_old 2020-06-08 23:49:14.714329350 +0200 +++ /var/tmp/diff_new_pack.4UJXNP/_new 2020-06-08 23:49:14.718329362 +0200 @@ -20,7 +20,7 @@ %define _version %(echo %{version} | grep -E -o '[0-9]+\.[0-9]+\.[0-9]+') Name: evolution-ews -Version: 3.36.2 +Version: 3.36.3 Release: 0 Summary: Exchange Connector for Evolution, compatible with Exchange 2007 and later License: LGPL-2.1-only ++++++ evolution-ews-3.36.2.tar.xz -> evolution-ews-3.36.3.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/CMakeLists.txt new/evolution-ews-3.36.3/CMakeLists.txt --- old/evolution-ews-3.36.2/CMakeLists.txt 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/CMakeLists.txt 2020-05-29 14:28:10.000000000 +0200 @@ -4,7 +4,7 @@ cmake_policy(VERSION 3.1) project(evolution-ews - VERSION 3.36.2 + VERSION 3.36.3 LANGUAGES C) set(PROJECT_BUGREPORT "https://gitlab.gnome.org/GNOME/evolution-ews/issues/") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/NEWS new/evolution-ews-3.36.3/NEWS --- old/evolution-ews-3.36.2/NEWS 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/NEWS 2020-05-29 14:28:10.000000000 +0200 @@ -1,3 +1,15 @@ +Evolution-EWS 3.36.3 2020-05-29 +------------------------------- + +Bug Fixes: + I#99 - All-day events date shown by one day off (Milan Crha) + I#102 - Hidden folders are displayed normally in the UI (Milan Crha) + I#103 - Can't subscribe to a folder of a user whom is not in GAL (Milan Crha) + +Miscellaneous: + EEwsNotification: Change how subscription to server change notifications work (Milan Crha) + Add parameter check into ews_get_error_code() (Milan Crha) + Evolution-EWS 3.36.2 2020-04-24 ------------------------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/addressbook/e-book-backend-ews.c new/evolution-ews-3.36.3/src/addressbook/e-book-backend-ews.c --- old/evolution-ews-3.36.2/src/addressbook/e-book-backend-ews.c 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/addressbook/e-book-backend-ews.c 2020-05-29 14:28:10.000000000 +0200 @@ -96,6 +96,11 @@ guint subscription_key; + /* The subscription ID is not tight to the actual connection, it survives + disconnects, thus remember it and pass it back to the new connection, + thus it can eventually unsubscribe from it. */ + gchar *last_subscription_id; + /* used for storing attachments */ gchar *attachments_dir; }; @@ -3221,6 +3226,25 @@ return is_gal; } +static void +ebb_ews_subscription_id_changed_cb (EEwsConnection *cnc, + const gchar *subscription_id, + gpointer user_data) +{ + EBookBackendEws *bbews = user_data; + + g_return_if_fail (E_IS_BOOK_BACKEND_EWS (bbews)); + + g_rec_mutex_lock (&bbews->priv->cnc_lock); + + if (g_strcmp0 (bbews->priv->last_subscription_id, subscription_id) != 0) { + g_free (bbews->priv->last_subscription_id); + bbews->priv->last_subscription_id = g_strdup (subscription_id); + } + + g_rec_mutex_unlock (&bbews->priv->cnc_lock); +} + static gboolean ebb_ews_connect_sync (EBookMetaBackend *meta_backend, const ENamedParameters *credentials, @@ -3306,6 +3330,11 @@ folders = g_slist_prepend (folders, bbews->priv->folder_id); + e_ews_connection_set_last_subscription_id (bbews->priv->cnc, bbews->priv->last_subscription_id); + + g_signal_connect_object (bbews->priv->cnc, "subscription-id-changed", + G_CALLBACK (ebb_ews_subscription_id_changed_cb), bbews, 0); + e_ews_connection_enable_notifications_sync (bbews->priv->cnc, folders, &bbews->priv->subscription_key); @@ -4049,6 +4078,7 @@ g_free (bbews->priv->folder_id); g_free (bbews->priv->attachments_dir); + g_free (bbews->priv->last_subscription_id); g_rec_mutex_clear (&bbews->priv->cnc_lock); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/calendar/e-cal-backend-ews-utils.c new/evolution-ews-3.36.3/src/calendar/e-cal-backend-ews-utils.c --- old/evolution-ews-3.36.2/src/calendar/e-cal-backend-ews-utils.c 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/calendar/e-cal-backend-ews-utils.c 2020-05-29 14:28:10.000000000 +0200 @@ -1654,7 +1654,8 @@ /*meeting dates*/ dtstart = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icomp, I_CAL_DTSTART_PROPERTY, i_cal_property_get_dtstart); dtstart_old = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icomp_old, I_CAL_DTSTART_PROPERTY, i_cal_property_get_dtstart); - dt_start_changed = dtstart != dtstart_old || (dtstart && dtstart_old && i_cal_time_compare (dtstart, dtstart_old) != 0); + dt_start_changed = ((!dtstart || !dtstart_old) && dtstart != dtstart_old) || + (dtstart && dtstart_old && i_cal_time_compare (dtstart, dtstart_old) != 0); tzid_start = dtstart ? i_cal_time_get_timezone (dtstart) : NULL; if (tzid_start) { ICalTimezone *zone; @@ -1670,7 +1671,8 @@ dtend = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icomp, I_CAL_DTEND_PROPERTY, i_cal_property_get_dtend); dtend_old = e_cal_backend_ews_get_datetime_with_zone (convert_data->timezone_cache, convert_data->vcalendar, icomp_old, I_CAL_DTEND_PROPERTY, i_cal_property_get_dtend); - dt_end_changed = dtend != dtend_old || (dtend && dtend_old && i_cal_time_compare (dtend, dtend_old) != 0); + dt_end_changed = ((!dtend || !dtend_old) && dtend != dtend_old) || + (dtend && dtend_old && i_cal_time_compare (dtend, dtend_old) != 0); tzid_end = dtend ? i_cal_time_get_timezone (dtend) : NULL; if (tzid_end) { ICalTimezone *zone; @@ -1687,21 +1689,23 @@ satisfies = e_ews_connection_satisfies_server_version (convert_data->connection, E_EWS_EXCHANGE_2010); if (satisfies) { - if (old_ical_location_start != NULL) { + if (old_ical_location_start) old_msdn_location_start = e_cal_backend_ews_tz_util_get_msdn_equivalent (old_ical_location_start); + + if (ical_location_start) msdn_location_start = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location_start); - if (g_strcmp0 (old_msdn_location_start, msdn_location_start) != 0) - dt_start_changed = TRUE; - } + if (g_strcmp0 (old_msdn_location_start, msdn_location_start) != 0) + dt_start_changed = TRUE; - if (old_ical_location_end != NULL) { + if (old_ical_location_end) old_msdn_location_end = e_cal_backend_ews_tz_util_get_msdn_equivalent (old_ical_location_end); + + if (ical_location_end) msdn_location_end = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location_end); - if (g_strcmp0 (old_msdn_location_end, msdn_location_end) != 0) - dt_end_changed = TRUE; - } + if (g_strcmp0 (old_msdn_location_end, msdn_location_end) != 0) + dt_end_changed = TRUE; if ((dt_start_changed || dt_start_changed_timezone_name) && ical_location_start != NULL) e_ews_message_add_set_item_field_extended_distinguished_name_string ( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/calendar/e-cal-backend-ews.c new/evolution-ews-3.36.3/src/calendar/e-cal-backend-ews.c --- old/evolution-ews-3.36.2/src/calendar/e-cal-backend-ews.c 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/calendar/e-cal-backend-ews.c 2020-05-29 14:28:10.000000000 +0200 @@ -70,6 +70,12 @@ gchar *folder_id; guint subscription_key; + + /* The subscription ID is not tight to the actual connection, it survives + disconnects, thus remember it and pass it back to the new connection, + thus it can eventually unsubscribe from it. */ + gchar *last_subscription_id; + gboolean is_freebusy_calendar; gchar *attachments_dir; @@ -387,6 +393,12 @@ dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, icomp, prop_kind, get_func); + if (i_cal_time_is_date (dt)) { + g_clear_object (&prop); + g_clear_object (&dt); + return; + } + val = i_cal_time_new_from_timet_with_zone (utc_value, i_cal_time_is_date (dt), i_cal_timezone_get_utc_timezone ()); i_cal_time_convert_to_zone_inplace (val, i_cal_time_get_timezone (dt)); set_func (prop, val); @@ -728,8 +740,12 @@ if (start_zone != NULL) { dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, icomp, I_CAL_DTSTART_PROPERTY, i_cal_property_get_dtstart); - i_cal_time_convert_to_zone_inplace (dt, start_zone); - i_cal_component_set_dtstart (icomp, dt); + + if (!i_cal_time_is_date (dt)) { + i_cal_time_convert_to_zone_inplace (dt, start_zone); + i_cal_component_set_dtstart (icomp, dt); + } + g_clear_object (&dt); timezone_set = TRUE; @@ -737,8 +753,12 @@ if (end_zone != NULL) { dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, icomp, I_CAL_DTEND_PROPERTY, i_cal_property_get_dtend); - i_cal_time_convert_to_zone_inplace (dt, end_zone); - i_cal_component_set_dtend (icomp, dt); + + if (!i_cal_time_is_date (dt)) { + i_cal_time_convert_to_zone_inplace (dt, end_zone); + i_cal_component_set_dtend (icomp, dt); + } + g_clear_object (&dt); e_timezone_cache_add_timezone (timezone_cache, end_zone); @@ -811,13 +831,21 @@ if (zone != NULL) { dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, icomp, I_CAL_DTSTART_PROPERTY, i_cal_property_get_dtstart); - i_cal_time_convert_to_zone_inplace (dt, zone); - i_cal_component_set_dtstart (icomp, dt); + + if (!i_cal_time_is_date (dt)) { + i_cal_time_convert_to_zone_inplace (dt, zone); + i_cal_component_set_dtstart (icomp, dt); + } + g_object_unref (dt); dt = e_cal_backend_ews_get_datetime_with_zone (timezone_cache, vcomp, icomp, I_CAL_DTEND_PROPERTY, i_cal_property_get_dtend); - i_cal_time_convert_to_zone_inplace (dt, zone); - i_cal_component_set_dtend (icomp, dt); + + if (!i_cal_time_is_date (dt)) { + i_cal_time_convert_to_zone_inplace (dt, zone); + i_cal_component_set_dtend (icomp, dt); + } + g_object_unref (dt); } @@ -1621,6 +1649,25 @@ return ecb_ews_organizer_is_user (cbews, comp); } +static void +ecb_ews_subscription_id_changed_cb (EEwsConnection *cnc, + const gchar *subscription_id, + gpointer user_data) +{ + ECalBackendEws *cbews = user_data; + + g_return_if_fail (E_IS_CAL_BACKEND_EWS (cbews)); + + g_rec_mutex_lock (&cbews->priv->cnc_lock); + + if (g_strcmp0 (cbews->priv->last_subscription_id, subscription_id) != 0) { + g_free (cbews->priv->last_subscription_id); + cbews->priv->last_subscription_id = g_strdup (subscription_id); + } + + g_rec_mutex_unlock (&cbews->priv->cnc_lock); +} + static gboolean ecb_ews_connect_sync (ECalMetaBackend *meta_backend, const ENamedParameters *credentials, @@ -1683,6 +1730,11 @@ folders = g_slist_prepend (folders, cbews->priv->folder_id); + e_ews_connection_set_last_subscription_id (cbews->priv->cnc, cbews->priv->last_subscription_id); + + g_signal_connect_object (cbews->priv->cnc, "subscription-id-changed", + G_CALLBACK (ecb_ews_subscription_id_changed_cb), cbews, 0); + e_ews_connection_enable_notifications_sync (cbews->priv->cnc, folders, &cbews->priv->subscription_key); @@ -4310,6 +4362,7 @@ g_free (cbews->priv->folder_id); g_free (cbews->priv->attachments_dir); + g_free (cbews->priv->last_subscription_id); g_rec_mutex_clear (&cbews->priv->cnc_lock); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/camel/camel-ews-store.c new/evolution-ews-3.36.3/src/camel/camel-ews-store.c --- old/evolution-ews-3.36.2/src/camel/camel-ews-store.c 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/camel/camel-ews-store.c 2020-05-29 14:28:10.000000000 +0200 @@ -77,6 +77,12 @@ gboolean listen_notifications; guint subscription_key; + + /* The subscription ID is not tight to the actual connection, it survives + disconnects, thus remember it and pass it back to the new connection, + thus it can eventually unsubscribe from it. */ + gchar *last_subscription_id; + guint update_folder_id; guint update_folder_list_id; GCancellable *updates_cancellable; @@ -1427,6 +1433,25 @@ camel_ews_store_handle_notifications (ews_store, ews_settings); } +static void +ews_camel_subscription_id_changed_cb (EEwsConnection *cnc, + const gchar *subscription_id, + gpointer user_data) +{ + CamelEwsStore *ews_store = user_data; + + g_return_if_fail (CAMEL_IS_EWS_STORE (ews_store)); + + g_mutex_lock (&ews_store->priv->connection_lock); + + if (g_strcmp0 (ews_store->priv->last_subscription_id, subscription_id) != 0) { + g_free (ews_store->priv->last_subscription_id); + ews_store->priv->last_subscription_id = g_strdup (subscription_id); + } + + g_mutex_unlock (&ews_store->priv->connection_lock); +} + static gboolean ews_connect_sync (CamelService *service, GCancellable *cancellable, @@ -1506,6 +1531,12 @@ "server-notification", G_CALLBACK (camel_ews_store_server_notification_cb), ews_store); + + e_ews_connection_set_last_subscription_id (connection, ews_store->priv->last_subscription_id); + + g_signal_connect_object (connection, "subscription-id-changed", + G_CALLBACK (ews_camel_subscription_id_changed_cb), ews_store, 0); + g_clear_object (&connection); } } @@ -4000,6 +4031,7 @@ ews_store = CAMEL_EWS_STORE (object); g_free (ews_store->storage_path); + g_free (ews_store->priv->last_subscription_id); g_mutex_clear (&ews_store->priv->get_finfo_lock); g_mutex_clear (&ews_store->priv->connection_lock); g_rec_mutex_clear (&ews_store->priv->update_lock); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/collection/e-ews-backend.c new/evolution-ews-3.36.3/src/collection/e-ews-backend.c --- old/evolution-ews-3.36.2/src/collection/e-ews-backend.c 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/collection/e-ews-backend.c 2020-05-29 14:28:10.000000000 +0200 @@ -225,32 +225,6 @@ e_source_authentication_get_user (coll_authentication_extension)); } -static gboolean -ews_backend_is_uuid_like_name (const gchar *name) -{ - const gchar *uuid_mask = "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}"; - const gchar *ptr, *msk_ptr; - gint len; - - if (!name || *name != '{') - return FALSE; - - len = strlen (name); - if (name[len - 1] != '}' || len != strlen (uuid_mask)) - return FALSE; - - for (ptr = name, msk_ptr = uuid_mask; *ptr && *msk_ptr; ptr++, msk_ptr++) { - if (*msk_ptr == 'X') { - if (!g_ascii_isxdigit (*ptr)) - break; - } else if (*msk_ptr != *ptr) { - break; - } - } - - return *msk_ptr == *ptr && !*msk_ptr; -} - static ESource * ews_backend_new_child (EEwsBackend *backend, EEwsFolder *folder) @@ -268,11 +242,9 @@ display_name = e_ews_folder_get_name (folder); - if (e_ews_folder_get_folder_type (folder) == E_EWS_FOLDER_TYPE_CONTACTS && - ews_backend_is_uuid_like_name (display_name)) { - /* Ignore address books with UUID-like name */ + /* Hide on-the-server hidden folders */ + if (e_ews_folder_get_is_hidden (folder)) return NULL; - } collection_backend = E_COLLECTION_BACKEND (backend); source = e_collection_backend_new_child (collection_backend, fid->id); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/configuration/e-ews-subscribe-foreign-folder.c new/evolution-ews-3.36.3/src/configuration/e-ews-subscribe-foreign-folder.c --- old/evolution-ews-3.36.2/src/configuration/e-ews-subscribe-foreign-folder.c 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/configuration/e-ews-subscribe-foreign-folder.c 2020-05-29 14:28:10.000000000 +0200 @@ -308,48 +308,42 @@ } } - if (!mailboxes) { - g_set_error ( - perror, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_MAILRECIPIENTNOTFOUND, - _("User “%s” was not found on the server"), cffd->email); - g_object_unref (conn); - return; - } - - /* is there only one result? */ - if (mailboxes->next == NULL) { - mailbox = mailboxes->data; - } else { - GSList *iter; - - for (iter = mailboxes; iter; iter = iter->next) { - EwsMailbox *mb = iter->data; - - if (!mb) - continue; - - if (mb->name && g_utf8_collate (mb->name, cffd->email) == 0) { - mailbox = mb; - break; + if (mailboxes) { + /* is there only one result? */ + if (!mailboxes->next) { + mailbox = mailboxes->data; + } else { + GSList *iter; + + for (iter = mailboxes; iter; iter = iter->next) { + EwsMailbox *mb = iter->data; + + if (!mb) + continue; + + if (mb->name && g_utf8_collate (mb->name, cffd->email) == 0) { + mailbox = mb; + break; + } } } - } - if (mailbox) { - g_free (cffd->user_displayname); - cffd->user_displayname = g_strdup (mailbox->name); - g_free (cffd->email); - cffd->email = g_strdup (mailbox->email); - } + if (mailbox) { + g_free (cffd->user_displayname); + cffd->user_displayname = g_strdup (mailbox->name); + g_free (cffd->email); + cffd->email = g_strdup (mailbox->email); + } - g_slist_free_full (mailboxes, (GDestroyNotify) e_ews_mailbox_free); + g_slist_free_full (mailboxes, (GDestroyNotify) e_ews_mailbox_free); - if (!mailbox) { - g_set_error ( - perror, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ITEMNOTFOUND, - _("User name “%s” is ambiguous, specify it more precisely, please"), cffd->email); - g_object_unref (conn); - return; + if (!mailbox) { + g_set_error ( + perror, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ITEMNOTFOUND, + _("User name “%s” is ambiguous, specify it more precisely, please"), cffd->email); + g_object_unref (conn); + return; + } } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/server/e-ews-connection.c new/evolution-ews-3.36.3/src/server/e-ews-connection.c --- old/evolution-ews-3.36.2/src/server/e-ews-connection.c 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/server/e-ews-connection.c 2020-05-29 14:28:10.000000000 +0200 @@ -82,6 +82,7 @@ GMainContext *soup_context; GProxyResolver *proxy_resolver; EEwsNotification *notification; + guint notification_delay_id; CamelEwsSettings *settings; guint concurrent_connections; @@ -102,6 +103,10 @@ GHashTable *subscriptions; GSList *subscribed_folders; + /* The subscription ID is not tight to the actual connection, it survives + disconnects, thus remember it and unsubscribe from it, before adding + a new subscription. */ + gchar *last_subscription_id; EEwsServerVersion version; gboolean backoff_enabled; @@ -126,7 +131,8 @@ enum { SERVER_NOTIFICATION, PASSWORD_WILL_EXPIRE, - LAST_SIGNAL, + SUBSCRIPTION_ID_CHANGED, + LAST_SIGNAL }; static guint signals[LAST_SIGNAL]; @@ -1181,32 +1187,38 @@ for (subparam1 = e_soap_parameter_get_first_child_by_name (node, "Create"); subparam1 != NULL; subparam1 = e_soap_parameter_get_next_child_by_name (subparam1, "Create")) { - EEwsFolder *folder; + GObject *object; - folder = parser (subparam1); - if (folder) - items_created = g_slist_append (items_created, folder); + object = parser (subparam1); + if (object && (!E_IS_EWS_FOLDER (object) || !e_ews_folder_get_is_hidden (E_EWS_FOLDER (object)))) + items_created = g_slist_append (items_created, object); + else + g_clear_object (&object); } for (subparam1 = e_soap_parameter_get_first_child_by_name (node, "Update"); subparam1 != NULL; subparam1 = e_soap_parameter_get_next_child_by_name (subparam1, "Update")) { - EEwsFolder *folder; + GObject *object; - folder = parser (subparam1); - if (folder) - items_updated = g_slist_append (items_updated, folder); + object = parser (subparam1); + if (object && (!E_IS_EWS_FOLDER (object) || !e_ews_folder_get_is_hidden (E_EWS_FOLDER (object)))) + items_updated = g_slist_append (items_updated, object); + else + g_clear_object (&object); } /* Exchange 2007SP1 introduced <ReadFlagChange> which is basically identical * to <Update>; no idea why they thought it was a good idea. */ for (subparam1 = e_soap_parameter_get_first_child_by_name (node, "ReadFlagChange"); subparam1 != NULL; subparam1 = e_soap_parameter_get_next_child_by_name (subparam1, "ReadFlagChange")) { - EEwsFolder *folder; + GObject *object; - folder = parser (subparam1); - if (folder) - items_updated = g_slist_append (items_updated, folder); + object = parser (subparam1); + if (object && (!E_IS_EWS_FOLDER (object) || !e_ews_folder_get_is_hidden (E_EWS_FOLDER (object)))) + items_updated = g_slist_append (items_updated, object); + else + g_clear_object (&object); } for (subparam1 = e_soap_parameter_get_first_child_by_name (node, "Delete"); @@ -2052,6 +2064,11 @@ g_mutex_unlock (&connecting); NOTIFICATION_LOCK (cnc); + if (cnc->priv->notification_delay_id) { + g_source_remove (cnc->priv->notification_delay_id); + cnc->priv->notification_delay_id = 0; + } + if (cnc->priv->notification) { e_ews_notification_stop_listening_sync (cnc->priv->notification); g_clear_object (&cnc->priv->notification); @@ -2110,6 +2127,7 @@ g_free (priv->hash_key); g_free (priv->impersonate_user); g_free (priv->ssl_certificate_pem); + g_free (priv->last_subscription_id); g_clear_object (&priv->bearer_auth); @@ -2214,6 +2232,15 @@ G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_STRING); + + signals[SUBSCRIPTION_ID_CHANGED] = g_signal_new ( + "subscription-id-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); } static void @@ -3015,6 +3042,38 @@ cnc->priv->disconnected_flag = disconnected_flag; } +gchar * +e_ews_connection_dup_last_subscription_id (EEwsConnection *cnc) +{ + gchar *res; + + g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), NULL); + + g_mutex_lock (&cnc->priv->property_lock); + + res = g_strdup (cnc->priv->last_subscription_id); + + g_mutex_unlock (&cnc->priv->property_lock); + + return res; +} + +void +e_ews_connection_set_last_subscription_id (EEwsConnection *cnc, + const gchar *subscription_id) +{ + g_return_if_fail (E_IS_EWS_CONNECTION (cnc)); + + g_mutex_lock (&cnc->priv->property_lock); + + if (g_strcmp0 (subscription_id, cnc->priv->last_subscription_id) != 0) { + g_free (cnc->priv->last_subscription_id); + cnc->priv->last_subscription_id = g_strdup (subscription_id); + } + + g_mutex_unlock (&cnc->priv->property_lock); +} + static xmlDoc * e_ews_autodiscover_ws_xml (const gchar *email_address) { @@ -5077,7 +5136,13 @@ TRUE); e_soap_message_start_element (msg, "FolderShape", "messages", NULL); e_ews_message_write_string_parameter (msg, "BaseShape", NULL, "AllProperties"); - e_soap_message_end_element (msg); + e_soap_message_start_element (msg, "AdditionalProperties", NULL, NULL); + e_soap_message_start_element (msg, "ExtendedFieldURI", NULL, NULL); + e_soap_message_add_attribute (msg, "PropertyTag", "4340", NULL, NULL); /* PidTagAttributeHidden */ + e_soap_message_add_attribute (msg, "PropertyType", "Boolean", NULL, NULL); + e_soap_message_end_element (msg); /* ExtendedFieldURI */ + e_soap_message_end_element (msg); /* AdditionalProperties */ + e_soap_message_end_element (msg); /* FolderShape */ if (sync_state) e_ews_message_write_string_parameter (msg, "SyncState", "messages", sync_state); @@ -10494,6 +10559,97 @@ } } +static void +ews_connection_subscription_id_changed_cb (EEwsNotification *notification, + const gchar *subscription_id, + gpointer user_data) +{ + EEwsConnection *cnc = user_data; + + g_return_if_fail (E_IS_EWS_CONNECTION (cnc)); + + NOTIFICATION_LOCK (cnc); + + if (cnc->priv->notification == notification) + g_signal_emit (cnc, signals[SUBSCRIPTION_ID_CHANGED], 0, subscription_id, NULL); + + NOTIFICATION_UNLOCK (cnc); +} + +static gpointer +ews_connection_notification_start_thread (gpointer user_data) +{ + GWeakRef *weakref = user_data; + EEwsConnection *cnc; + + g_return_val_if_fail (weakref != NULL, NULL); + + cnc = g_weak_ref_get (weakref); + + if (cnc && !e_ews_connection_get_disconnected_flag (cnc)) { + gchar *last_subscription_id = e_ews_connection_dup_last_subscription_id (cnc); + + NOTIFICATION_LOCK (cnc); + + if (cnc->priv->subscribed_folders) { + g_warn_if_fail (cnc->priv->notification == NULL); + g_clear_object (&cnc->priv->notification); + + cnc->priv->notification = e_ews_notification_new (cnc, last_subscription_id); + + /* The 'notification' assumes ownership of the 'last_subscription_id' */ + last_subscription_id = NULL; + + g_signal_connect_object (cnc->priv->notification, "subscription-id-changed", + G_CALLBACK (ews_connection_subscription_id_changed_cb), cnc, 0); + + e_ews_notification_start_listening_sync (cnc->priv->notification, cnc->priv->subscribed_folders); + } + + NOTIFICATION_UNLOCK (cnc); + + g_free (last_subscription_id); + } + + g_clear_object (&cnc); + e_weak_ref_free (weakref); + + return NULL; +} + +static gboolean +ews_connection_notification_delay_cb (gpointer user_data) +{ + GWeakRef *weakref = user_data; + EEwsConnection *cnc; + + if (g_source_is_destroyed (g_main_current_source ())) + return FALSE; + + g_return_val_if_fail (weakref != NULL, FALSE); + + cnc = g_weak_ref_get (weakref); + + if (cnc) { + NOTIFICATION_LOCK (cnc); + + if (cnc->priv->notification_delay_id == g_source_get_id (g_main_current_source ())) { + cnc->priv->notification_delay_id = 0; + + if (cnc->priv->subscribed_folders) { + g_thread_unref (g_thread_new (NULL, ews_connection_notification_start_thread, + e_weak_ref_new (cnc))); + } + } + + NOTIFICATION_UNLOCK (cnc); + + g_object_unref (cnc); + } + + return FALSE; +} + /* * Enables server notification on a folder (or a set of folders). * The events we are listen for notifications are: Copied, Created, Deleted, Modified and Moved. @@ -10521,7 +10677,7 @@ GSList *folders, guint *subscription_key) { - GSList *new_folders = NULL, *l; + GSList *new_folders = NULL, *l, *flink; gint subscriptions_size; g_return_if_fail (cnc != NULL); @@ -10535,10 +10691,25 @@ if (subscriptions_size == G_MAXUINT - 1) goto exit; - if (subscriptions_size > 0) { - e_ews_notification_stop_listening_sync (cnc->priv->notification); + for (flink = folders; flink; flink = g_slist_next (flink)) { + for (l = cnc->priv->subscribed_folders; l; l = g_slist_next (l)) { + if (g_strcmp0 (l->data, flink->data) == 0) + break; + } - g_clear_object (&cnc->priv->notification); + if (!l) + break; + } + + /* All requested folders are already subscribed */ + if (!flink && cnc->priv->notification) + goto exit; + + if (subscriptions_size > 0) { + if (cnc->priv->notification) { + e_ews_notification_stop_listening_sync (cnc->priv->notification); + g_clear_object (&cnc->priv->notification); + } g_slist_free_full (cnc->priv->subscribed_folders, g_free); cnc->priv->subscribed_folders = NULL; @@ -10558,9 +10729,11 @@ g_hash_table_foreach (cnc->priv->subscriptions, ews_connection_build_subscribed_folders_list, cnc); - cnc->priv->notification = e_ews_notification_new (cnc); + if (cnc->priv->notification_delay_id) + g_source_remove (cnc->priv->notification_delay_id); - e_ews_notification_start_listening_sync (cnc->priv->notification, cnc->priv->subscribed_folders); + cnc->priv->notification_delay_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, 5, + ews_connection_notification_delay_cb, e_weak_ref_new (cnc), (GDestroyNotify) e_weak_ref_free); exit: *subscription_key = notification_key; @@ -10591,7 +10764,7 @@ cnc->priv->subscribed_folders = NULL; g_hash_table_foreach (cnc->priv->subscriptions, ews_connection_build_subscribed_folders_list, cnc); - if (cnc->priv->subscribed_folders != NULL) { + if (cnc->priv->subscribed_folders != NULL && !e_ews_connection_get_disconnected_flag (cnc)) { e_ews_notification_start_listening_sync (cnc->priv->notification, cnc->priv->subscribed_folders); } else { g_clear_object (&cnc->priv->notification); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/server/e-ews-connection.h new/evolution-ews-3.36.3/src/server/e-ews-connection.h --- old/evolution-ews-3.36.2/src/server/e-ews-connection.h 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/server/e-ews-connection.h 2020-05-29 14:28:10.000000000 +0200 @@ -477,6 +477,11 @@ void e_ews_connection_set_disconnected_flag (EEwsConnection *cnc, gboolean disconnected_flag); +gchar * e_ews_connection_dup_last_subscription_id + (EEwsConnection *cnc); +void e_ews_connection_set_last_subscription_id + (EEwsConnection *cnc, + const gchar *subscription_id); EEwsConnection *e_ews_connection_find (const gchar *uri, const gchar *username); GSList * e_ews_connection_list_existing (void); /* EEwsConnection * */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/server/e-ews-folder.c new/evolution-ews-3.36.3/src/server/e-ews-folder.c --- old/evolution-ews-3.36.2/src/server/e-ews-folder.c 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/server/e-ews-folder.c 2020-05-29 14:28:10.000000000 +0200 @@ -47,6 +47,7 @@ gboolean foreign; gchar *foreign_mail; gboolean is_public; + gboolean is_hidden; }; static void @@ -110,6 +111,7 @@ folder->priv->folder_type = E_EWS_FOLDER_TYPE_UNKNOWN; folder->priv->foreign = FALSE; folder->priv->is_public = FALSE; + folder->priv->is_hidden = FALSE; } static gboolean @@ -214,10 +216,19 @@ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "ExtendedFieldURI"); if (subparam1) { prop_tag = e_soap_parameter_get_property (subparam1, "PropertyTag"); - if (g_strcmp0 (prop_tag, "0xe08") == 0) { + if (prop_tag && g_ascii_strcasecmp (prop_tag, "0xe08") == 0) { subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Value"); if (subparam1) priv->size = e_soap_parameter_get_int_value (subparam1); + } else if (prop_tag && g_ascii_strcasecmp (prop_tag, "0x10f4") == 0) { /* PidTagAttributeHidden */ + subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Value"); + if (subparam1) { + gchar *value; + + value = e_soap_parameter_get_string_value (subparam1); + priv->is_hidden = g_strcmp0 (value, "true") == 0; + g_free (value); + } } g_free (prop_tag); } @@ -474,6 +485,14 @@ priv->parent_fid = parent_fid; } +gboolean +e_ews_folder_get_is_hidden (EEwsFolder *folder) +{ + g_return_val_if_fail (E_IS_EWS_FOLDER (folder), FALSE); + + return folder->priv->is_hidden; +} + EEwsFolderType e_ews_folder_get_folder_type (const EEwsFolder *folder) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/server/e-ews-folder.h new/evolution-ews-3.36.3/src/server/e-ews-folder.h --- old/evolution-ews-3.36.2/src/server/e-ews-folder.h 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/server/e-ews-folder.h 2020-05-29 14:28:10.000000000 +0200 @@ -74,8 +74,7 @@ guint32 e_ews_folder_get_unread_count (const EEwsFolder *folder); guint32 e_ews_folder_get_child_count (const EEwsFolder *folder); guint64 e_ews_folder_get_size (const EEwsFolder *folder); -gboolean e_ews_folder_get_is_writable (const EEwsFolder *folder); -void e_ews_folder_set_is_writable (EEwsFolder *folder, gboolean writable); +gboolean e_ews_folder_get_is_hidden (EEwsFolder *folder); EEwsFolderType e_ews_folder_get_folder_type (const EEwsFolder *folder); void e_ews_folder_set_folder_type (EEwsFolder *folder, EEwsFolderType folder_type); gboolean e_ews_folder_get_foreign (const EEwsFolder *folder); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/server/e-ews-notification.c new/evolution-ews-3.36.3/src/server/e-ews-notification.c --- old/evolution-ews-3.36.2/src/server/e-ews-notification.c 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/server/e-ews-notification.c 2020-05-29 14:28:10.000000000 +0200 @@ -36,6 +36,7 @@ GWeakRef connection_wk; GByteArray *chunk; GCancellable *cancellable; + gchar *last_subscription_id; /* guarded by the caller, because it can be set only after construct */ }; enum { @@ -43,6 +44,13 @@ PROP_CONNECTION }; +enum { + SUBSCRIPTION_ID_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + static const gchar *default_events_names[] = { "CopiedEvent", "CreatedEvent", @@ -91,13 +99,20 @@ } EEwsNotification * -e_ews_notification_new (EEwsConnection *connection) +e_ews_notification_new (EEwsConnection *connection, + gchar *last_subscription_id) { + EEwsNotification *notif; + g_return_val_if_fail (E_IS_EWS_CONNECTION (connection), NULL); - return g_object_new ( + notif = g_object_new ( E_TYPE_EWS_NOTIFICATION, "connection", connection, NULL); + + notif->priv->last_subscription_id = last_subscription_id; + + return notif; } static void @@ -203,6 +218,7 @@ notif = E_EWS_NOTIFICATION (object); g_weak_ref_clear (¬if->priv->connection_wk); + g_free (notif->priv->last_subscription_id); /* Chain up to parent's method. */ G_OBJECT_CLASS (e_ews_notification_parent_class)->finalize (object); @@ -233,6 +249,15 @@ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + signals[SUBSCRIPTION_ID_CHANGED] = g_signal_new ( + "subscription-id-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); } static void @@ -416,6 +441,9 @@ } g_object_unref (response); + + g_signal_emit (notification, signals[SUBSCRIPTION_ID_CHANGED], 0, *subscription_id, NULL); + return TRUE; } @@ -504,6 +532,8 @@ return FALSE; } + g_signal_emit (notification, signals[SUBSCRIPTION_ID_CHANGED], 0, NULL, NULL); + return TRUE; } @@ -898,6 +928,11 @@ g_return_val_if_fail (td->notification != NULL, NULL); g_return_val_if_fail (td->folders != NULL, NULL); + if (td->notification->priv->last_subscription_id) { + e_ews_notification_unsubscribe_folder_sync (td->notification, td->notification->priv->last_subscription_id); + g_clear_pointer (&td->notification->priv->last_subscription_id, g_free); + } + if (!e_ews_notification_subscribe_folder_sync (td->notification, td->folders, &subscription_id, td->cancellable)) goto exit; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/server/e-ews-notification.h new/evolution-ews-3.36.3/src/server/e-ews-notification.h --- old/evolution-ews-3.36.2/src/server/e-ews-notification.h 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/server/e-ews-notification.h 2020-05-29 14:28:10.000000000 +0200 @@ -53,7 +53,8 @@ GType e_ews_notification_get_type (void); EEwsNotification * - e_ews_notification_new (EEwsConnection *connection); + e_ews_notification_new (EEwsConnection *connection, + gchar *last_subscription_id); /* assumes ownership of it */ void e_ews_notification_start_listening_sync (EEwsNotification *notification, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/evolution-ews-3.36.2/src/server/ews-errors.c new/evolution-ews-3.36.3/src/server/ews-errors.c --- old/evolution-ews-3.36.2/src/server/ews-errors.c 2020-04-24 10:17:15.000000000 +0200 +++ new/evolution-ews-3.36.3/src/server/ews-errors.c 2020-05-29 14:28:10.000000000 +0200 @@ -331,6 +331,9 @@ gint error_code = EWS_CONNECTION_ERROR_UNKNOWN; gpointer data; + if (!str) + return error_code; + g_once (&setup_error_once, setup_error_map, NULL); data = g_hash_table_lookup (ews_error_hash, (gconstpointer) str);
