[evolution-ews] Bug 792653 - Use GetUserPhoto for GAL contacts



commit 11cf0fa4d66a42a5e5d2d1bc263278f4548363f5
Author: Milan Crha <mcrha redhat com>
Date:   Fri Apr 20 12:00:54 2018 +0200

    Bug 792653 - Use GetUserPhoto for GAL contacts

 src/addressbook/e-book-backend-ews.c  |  392 +++++++++++++++++++++++++++------
 src/addressbook/ews-oab-decoder.c     |    2 +-
 src/addressbook/ews-oab-decoder.h     |    1 +
 src/addressbook/oab-decode-test.c     |    1 +
 src/configuration/e-book-config-ews.c |   16 ++-
 src/server/e-ews-connection.c         |   21 ++-
 src/server/e-ews-connection.h         |    5 +
 src/server/e-source-ews-folder.c      |   52 +++++-
 src/server/e-source-ews-folder.h      |    5 +
 9 files changed, 420 insertions(+), 75 deletions(-)
---
diff --git a/src/addressbook/e-book-backend-ews.c b/src/addressbook/e-book-backend-ews.c
index 94fa231..078da09 100644
--- a/src/addressbook/e-book-backend-ews.c
+++ b/src/addressbook/e-book-backend-ews.c
@@ -57,6 +57,7 @@
 #define EDB_ERROR_EX(_code,_msg) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, _msg)
 
 #define X_EWS_ORIGINAL_VCARD "X-EWS-ORIGINAL-VCARD"
+#define X_EWS_PHOTO_CHECK_DATE "X-EWS-PHOTO-CHECK-DATE" /* YYYYMMDD of the last check for photo */
 
 #define EWS_MAX_FETCH_COUNT 500
 
@@ -83,6 +84,144 @@ struct _EBookBackendEwsPrivate {
 
 G_DEFINE_TYPE (EBookBackendEws, e_book_backend_ews, E_TYPE_BOOK_META_BACKEND)
 
+static void
+ebb_ews_remove_x_attribute (EContact *contact,
+                           const gchar *xname)
+{
+       g_return_if_fail (E_IS_CONTACT (contact));
+       g_return_if_fail (xname != NULL);
+
+       e_vcard_remove_attributes (E_VCARD (contact), NULL, xname);
+}
+
+static void
+ebb_ews_store_x_attribute (EContact *contact,
+                          const gchar *xname,
+                          const gchar *value)
+{
+       EVCardAttribute *attr;
+
+       g_return_if_fail (E_IS_CONTACT (contact));
+       g_return_if_fail (xname != NULL);
+
+       ebb_ews_remove_x_attribute (contact, xname);
+
+       if (!value)
+               return;
+
+       attr = e_vcard_attribute_new ("", xname);
+       e_vcard_attribute_add_value (attr, value);
+       e_vcard_add_attribute (E_VCARD (contact), attr);
+}
+
+static const gchar *
+ebb_ews_get_x_attribute (EContact *contact,
+                        const gchar *xname)
+{
+       EVCardAttribute *attr;
+       GList *values = NULL;
+       const gchar *value;
+
+       g_return_val_if_fail (E_IS_CONTACT (contact), NULL);
+       g_return_val_if_fail (xname != NULL, NULL);
+
+       attr = e_vcard_get_attribute (E_VCARD (contact), xname);
+       if (!attr)
+               return NULL;
+
+       values = e_vcard_attribute_get_values (attr);
+       if (!values)
+               return NULL;
+
+       value = values->data;
+
+       if (value && *value)
+               return value;
+
+       return NULL;
+}
+
+static const gchar *
+ebb_ews_get_original_vcard (EContact *contact)
+{
+       g_return_val_if_fail (E_IS_CONTACT (contact), NULL);
+
+       return ebb_ews_get_x_attribute (contact, X_EWS_ORIGINAL_VCARD);
+}
+
+static void
+ebb_ews_store_original_vcard (EContact *contact)
+{
+       gchar *vcard_str;
+
+       g_return_if_fail (E_IS_CONTACT (contact));
+
+       vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+
+       ebb_ews_store_x_attribute (contact, X_EWS_ORIGINAL_VCARD, vcard_str);
+
+       g_free (vcard_str);
+}
+
+static gchar *
+ebb_ews_get_today_as_string (void)
+{
+       GDate date;
+
+       g_date_clear (&date, 1);
+       g_date_set_time_t (&date, time (NULL));
+
+       return g_strdup_printf ("%04d%02d%02d", g_date_get_year (&date), g_date_get_month (&date), 
g_date_get_day (&date));
+}
+
+static const gchar *
+ebb_ews_get_photo_check_date (EContact *contact)
+{
+       g_return_val_if_fail (E_IS_CONTACT (contact), NULL);
+
+       return ebb_ews_get_x_attribute (contact, X_EWS_PHOTO_CHECK_DATE);
+}
+
+static void
+ebb_ews_store_photo_check_date (EContact *contact,
+                               const gchar *value)
+{
+       gchar *today_str = NULL;
+
+       g_return_if_fail (E_IS_CONTACT (contact));
+
+       if (!value) {
+               today_str = ebb_ews_get_today_as_string ();
+               value = today_str;
+       }
+
+       ebb_ews_store_x_attribute (contact, X_EWS_PHOTO_CHECK_DATE, value);
+
+       g_free (today_str);
+}
+
+static gboolean
+ebb_ews_can_check_user_photo (EContact *contact)
+{
+       const gchar *last_check;
+       gboolean can;
+
+       g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
+
+       last_check = ebb_ews_get_photo_check_date (contact);
+       if (last_check && *last_check) {
+               gchar *today_str;
+
+               today_str = ebb_ews_get_today_as_string ();
+               can = g_strcmp0 (last_check, today_str) != 0;
+               g_free (today_str);
+       } else {
+               can = TRUE;
+       }
+
+       return can;
+}
+
 static CamelEwsSettings *
 ebb_ews_get_collection_settings (EBookBackendEws *bbews)
 {
@@ -2124,7 +2263,64 @@ ebb_ews_remove_old_gal_file (EBookCache *book_cache)
        g_free (filename);
 }
 
+static gboolean
+ebb_ews_fetch_gal_photo_sync (EBookBackendEws *bbews,
+                             EContact *contact,
+                             GCancellable *cancellable,
+                             GError **error)
+{
+       const gchar *email;
+       gboolean success = FALSE;
+
+       g_return_val_if_fail (E_IS_BOOK_BACKEND_EWS (bbews), FALSE);
+       g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
+
+       email = e_contact_get_const (contact, E_CONTACT_EMAIL_1);
+       if (!email || !*email)
+               return FALSE;
+
+       g_rec_mutex_lock (&bbews->priv->cnc_lock);
+
+       if (bbews->priv->cnc) {
+               gchar *photo_base64 = NULL;
+               gboolean backoff_enabled;
+
+               backoff_enabled = e_ews_connection_get_backoff_enabled (bbews->priv->cnc);
+               e_ews_connection_set_backoff_enabled (bbews->priv->cnc, FALSE);
+
+               if (e_ews_connection_get_user_photo_sync (bbews->priv->cnc, EWS_PRIORITY_MEDIUM, email,
+                   E_EWS_SIZE_REQUESTED_96X96, &photo_base64, cancellable, error) && photo_base64) {
+                       guchar *bytes;
+                       gsize nbytes;
+
+                       bytes = g_base64_decode (photo_base64, &nbytes);
+                       if (bytes && nbytes > 0) {
+                               EContactPhoto *photo;
+
+                               photo = e_contact_photo_new ();
+                               photo->type = E_CONTACT_PHOTO_TYPE_INLINED;
+                               e_contact_photo_set_inlined (photo, bytes, nbytes);
+                               e_contact_set (contact, E_CONTACT_PHOTO, photo);
+                               e_contact_photo_free (photo);
+
+                               success = TRUE;
+                       }
+
+                       g_free (photo_base64);
+                       g_free (bytes);
+               }
+
+               e_ews_connection_set_backoff_enabled (bbews->priv->cnc, backoff_enabled);
+       }
+
+       g_rec_mutex_unlock (&bbews->priv->cnc_lock);
+
+       return success;
+}
+
 struct _db_data {
+       EBookBackendEws *bbews;
+       gboolean fetch_gal_photos;
        GHashTable *uids;
        GHashTable *sha1s;
        gint unchanged;
@@ -2164,6 +2360,7 @@ ebb_ews_gal_store_contact (EContact *contact,
                           const gchar *sha1,
                           guint percent,
                           gpointer user_data,
+                          GCancellable *cancellable,
                           GError **error)
 {
        struct _db_data *data = (struct _db_data *) user_data;
@@ -2174,6 +2371,19 @@ ebb_ews_gal_store_contact (EContact *contact,
 
                e_contact_set (contact, E_CONTACT_REV, sha1);
 
+               if (data->fetch_gal_photos && !g_cancellable_is_cancelled (cancellable)) {
+                       GError *local_error = NULL;
+
+                       if (!ebb_ews_fetch_gal_photo_sync (data->bbews, contact, cancellable, &local_error))
+                               ebb_ews_store_photo_check_date (contact, NULL);
+
+                       /* The server can kick-off the flood of photo requests, then better stop it */
+                       if (g_error_matches (local_error, EWS_CONNECTION_ERROR, 
EWS_CONNECTION_ERROR_SERVERBUSY))
+                               data->fetch_gal_photos = FALSE;
+
+                       g_clear_error (&local_error);
+               }
+
                nfo = e_book_meta_backend_info_new (uid, sha1, NULL, NULL);
                nfo->object = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
 
@@ -2230,6 +2440,7 @@ ebb_ews_check_gal_changes (EBookBackendEws *bbews,
                           GCancellable *cancellable,
                           GError **error)
 {
+       ESourceEwsFolder *ews_folder;
        EwsOabDecoder *eod;
        gboolean success = TRUE;
        struct _db_data data;
@@ -2245,6 +2456,10 @@ ebb_ews_check_gal_changes (EBookBackendEws *bbews,
        g_return_val_if_fail (out_modified_objects != NULL, FALSE);
        g_return_val_if_fail (out_removed_objects != NULL, FALSE);
 
+       ews_folder = e_source_get_extension (e_backend_get_source (E_BACKEND (bbews)), 
E_SOURCE_EXTENSION_EWS_FOLDER);
+
+       data.bbews = bbews;
+       data.fetch_gal_photos = e_source_ews_folder_get_fetch_gal_photos (ews_folder);
        data.created_objects = NULL;
        data.modified_objects = NULL;
        data.unchanged = data.changed = data.added = 0;
@@ -2297,61 +2512,6 @@ ebb_ews_check_gal_changes (EBookBackendEws *bbews,
        return success;
 }
 
-static void
-ebb_ews_remove_original_vcard (EContact *contact)
-{
-       g_return_if_fail (E_IS_CONTACT (contact));
-
-       e_vcard_remove_attributes (E_VCARD (contact), NULL, X_EWS_ORIGINAL_VCARD);
-}
-
-static void
-ebb_ews_store_original_vcard (EContact *contact)
-{
-       EVCard *vcard;
-       EVCardAttribute *attr;
-       gchar *vcard_str;
-
-       g_return_if_fail (E_IS_CONTACT (contact));
-
-       ebb_ews_remove_original_vcard (contact);
-
-       vcard = E_VCARD (contact);
-
-       vcard_str = e_vcard_to_string (vcard, EVC_FORMAT_VCARD_30);
-
-       attr = e_vcard_attribute_new ("", X_EWS_ORIGINAL_VCARD);
-       e_vcard_attribute_add_value (attr, vcard_str);
-       e_vcard_add_attribute (vcard, attr);
-
-       g_free (vcard_str);
-}
-
-static const gchar *
-ebb_ews_get_original_vcard (EContact *contact)
-{
-       EVCardAttribute *attr;
-       GList *values = NULL;
-       const gchar *vcard;
-
-       g_return_val_if_fail (E_IS_CONTACT (contact), NULL);
-
-       attr = e_vcard_get_attribute (E_VCARD (contact), X_EWS_ORIGINAL_VCARD);
-       if (!attr)
-               return NULL;
-
-       values = e_vcard_attribute_get_values (attr);
-       if (!values)
-               return NULL;
-
-       vcard = values->data;
-
-       if (vcard && *vcard)
-               return vcard;
-
-       return NULL;
-}
-
 typedef struct {
        /* For future use */
        gpointer restriction;
@@ -2601,18 +2761,20 @@ ebb_ews_update_cache_for_expression (EBookBackendEws *bbews,
                                EWS_SEARCH_AD, NULL, TRUE, &mailboxes, &contacts, &includes_last_item, 
cancellable, error);
 
                if (success) {
+                       EBookCache *book_cache;
                        ESourceEwsFolder *ews_folder;
                        gboolean use_primary_address;
                        GSList *mlink, *clink;
 
                        ews_folder = e_source_get_extension (e_backend_get_source (E_BACKEND (bbews)), 
E_SOURCE_EXTENSION_EWS_FOLDER);
                        use_primary_address = e_source_ews_folder_get_use_primary_address (ews_folder);
+                       book_cache = e_book_meta_backend_ref_cache (meta_backend);
 
                        for (mlink = mailboxes, clink = contacts; mlink; mlink = g_slist_next (mlink), clink 
= g_slist_next (clink)) {
                                EwsMailbox *mb = mlink->data;
                                EEwsItem *contact_item = clink ? clink->data : NULL;
                                EBookMetaBackendInfo *nfo;
-                               EContact *contact = NULL;
+                               EContact *contact = NULL, *old_contact = NULL;
                                gboolean is_public_dl = FALSE, mailbox_address_set = FALSE;
                                const gchar *str;
                                gchar *fake_rev;
@@ -2699,6 +2861,25 @@ ebb_ews_update_cache_for_expression (EBookBackendEws *bbews,
                                        }
                                }
 
+                               /* Copy photo information, if any there */
+                               if (e_book_cache_get_contact (book_cache, mb->email, FALSE, &old_contact, 
cancellable, NULL) && old_contact) {
+                                       EContactPhoto *photo;
+
+                                       photo = e_contact_get (old_contact, E_CONTACT_PHOTO);
+                                       if (photo) {
+                                               e_contact_set (contact, E_CONTACT_PHOTO, photo);
+                                               e_contact_photo_free (photo);
+                                       } else {
+                                               const gchar *photo_check_date;
+
+                                               photo_check_date = ebb_ews_get_photo_check_date (old_contact);
+                                               if (photo_check_date)
+                                                       ebb_ews_store_photo_check_date (contact, 
photo_check_date);
+                                       }
+
+                                       g_clear_object (&old_contact);
+                               }
+
                                ebb_ews_store_original_vcard (contact);
 
                                nfo = e_book_meta_backend_info_new (e_contact_get_const (contact, 
E_CONTACT_UID),
@@ -2709,6 +2890,8 @@ ebb_ews_update_cache_for_expression (EBookBackendEws *bbews,
 
                                g_object_unref (contact);
                        }
+
+                       g_clear_object (&book_cache);
                }
 
                g_slist_free_full (mailboxes, (GDestroyNotify) e_ews_mailbox_free);
@@ -2776,6 +2959,25 @@ ebb_ews_verify_changes (EBookCache *book_cache,
        return items;
 }
 
+static EBookMetaBackendInfo *
+ebb_ews_contact_to_info (EContact *contact)
+{
+       EBookMetaBackendInfo *nfo;
+
+       if (!E_IS_CONTACT (contact))
+               return NULL;
+
+       ebb_ews_store_original_vcard (contact);
+
+       nfo = e_book_meta_backend_info_new (
+               e_contact_get_const (contact, E_CONTACT_UID),
+               e_contact_get_const (contact, E_CONTACT_REV),
+               NULL, NULL);
+       nfo->object = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+
+       return nfo;
+}
+
 static GSList * /* EBookMetaBackendInfo */
 ebb_ews_contacts_to_infos (const GSList *contacts) /* EContact * */
 {
@@ -2785,18 +2987,9 @@ ebb_ews_contacts_to_infos (const GSList *contacts) /* EContact * */
                EContact *contact = link->data;
                EBookMetaBackendInfo *nfo;
 
-               if (!E_IS_CONTACT (contact))
-                       continue;
-
-               ebb_ews_store_original_vcard (contact);
-
-               nfo = e_book_meta_backend_info_new (
-                       e_contact_get_const (contact, E_CONTACT_UID),
-                       e_contact_get_const (contact, E_CONTACT_REV),
-                       NULL, NULL);
-               nfo->object = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
-
-               nfos = g_slist_prepend (nfos, nfo);
+               nfo = ebb_ews_contact_to_info (contact);
+               if (nfo)
+                       nfos = g_slist_prepend (nfos, nfo);
        }
 
        return nfos;
@@ -3369,14 +3562,71 @@ ebb_ews_search_sync (EBookMetaBackend *meta_backend,
                     GCancellable *cancellable,
                     GError **error)
 {
+       EBookBackendEws *bbews;
+
        g_return_val_if_fail (E_IS_BOOK_BACKEND_EWS (meta_backend), FALSE);
 
+       bbews = E_BOOK_BACKEND_EWS (meta_backend);
+
        /* Ignore errors, just try its best */
-       ebb_ews_update_cache_for_expression (E_BOOK_BACKEND_EWS (meta_backend), expr, cancellable, NULL);
+       ebb_ews_update_cache_for_expression (bbews, expr, cancellable, NULL);
 
        /* Chain up to parent's method */
-       return E_BOOK_META_BACKEND_CLASS (e_book_backend_ews_parent_class)->search_sync (meta_backend, expr, 
meta_contact,
-               out_contacts, cancellable, error);
+       if (!E_BOOK_META_BACKEND_CLASS (e_book_backend_ews_parent_class)->search_sync (meta_backend, expr, 
meta_contact,
+               out_contacts, cancellable, error))
+               return FALSE;
+
+       if (bbews->priv->is_gal && !meta_contact && out_contacts && *out_contacts) {
+               ESourceEwsFolder *ews_folder;
+
+               ews_folder = e_source_get_extension (e_backend_get_source (E_BACKEND (bbews)), 
E_SOURCE_EXTENSION_EWS_FOLDER);
+               if (e_source_ews_folder_get_fetch_gal_photos (ews_folder)) {
+                       g_rec_mutex_lock (&bbews->priv->cnc_lock);
+
+                       if (bbews->priv->cnc && e_ews_connection_satisfies_server_version (bbews->priv->cnc, 
E_EWS_EXCHANGE_2013)) {
+                               GSList *link, *modified = NULL;
+                               gint count = 10;
+
+                               /* Limit to first 10 without photo, no need to flood the server
+                                  and slow the response too much */
+                               for (link = *out_contacts; link && count > 0 && !g_cancellable_is_cancelled 
(cancellable); link = g_slist_next (link)) {
+                                       EContact *contact = link->data;
+                                       EBookMetaBackendInfo *nfo;
+                                       GError *local_error = NULL;
+
+                                       if (!contact || e_vcard_get_attribute (E_VCARD (contact), EVC_PHOTO) 
||
+                                           !ebb_ews_can_check_user_photo (contact))
+                                               continue;
+
+                                       count--;
+
+                                       if (!ebb_ews_fetch_gal_photo_sync (bbews, contact, cancellable, 
&local_error))
+                                               ebb_ews_store_photo_check_date (contact, NULL);
+
+                                       nfo = ebb_ews_contact_to_info (contact);
+                                       if (nfo)
+                                               modified = g_slist_prepend (modified, nfo);
+
+                                       /* Stop immediately when the server is busy */
+                                       if (g_error_matches (local_error, EWS_CONNECTION_ERROR, 
EWS_CONNECTION_ERROR_SERVERBUSY)) {
+                                               g_clear_error (&local_error);
+                                               break;
+                                       }
+
+                                       g_clear_error (&local_error);
+                               }
+
+                               if (modified) {
+                                       e_book_meta_backend_process_changes_sync (meta_backend, NULL, 
modified, NULL, cancellable, NULL);
+                                       g_slist_free_full (modified, e_book_meta_backend_info_free);
+                               }
+                       }
+
+                       g_rec_mutex_unlock (&bbews->priv->cnc_lock);
+               }
+       }
+
+       return TRUE;
 }
 
 static gboolean
diff --git a/src/addressbook/ews-oab-decoder.c b/src/addressbook/ews-oab-decoder.c
index 9920922..ee19970 100644
--- a/src/addressbook/ews-oab-decoder.c
+++ b/src/addressbook/ews-oab-decoder.c
@@ -1047,7 +1047,7 @@ ews_decode_and_store_oab_records (EwsOabDecoder *eod,
                                                   cancellable, error))
                        cb (contact, offset, sum_str,
                            ((gfloat) (i + 1) / priv->total_records) * 100,
-                           user_data, error);
+                           user_data, cancellable, error);
 
                g_object_unref (memstream);
                g_object_unref (contact);
diff --git a/src/addressbook/ews-oab-decoder.h b/src/addressbook/ews-oab-decoder.h
index 7017e81..0380f25 100644
--- a/src/addressbook/ews-oab-decoder.h
+++ b/src/addressbook/ews-oab-decoder.h
@@ -61,6 +61,7 @@ typedef void  (*EwsOabContactAddedCb)         (EContact *contact,
                                                 const gchar *sha1,
                                                 guint percent_complete,
                                                 gpointer user_data,
+                                                GCancellable *cancellable,
                                                 GError **error);
 typedef gboolean (*EwsOabContactFilterCb)      (goffset offset,
                                                 const gchar *sha1,
diff --git a/src/addressbook/oab-decode-test.c b/src/addressbook/oab-decode-test.c
index 6a6c7bf..2b22c6c 100644
--- a/src/addressbook/oab-decode-test.c
+++ b/src/addressbook/oab-decode-test.c
@@ -25,6 +25,7 @@ ews_test_store_contact (EContact *contact,
                        const gchar *sha1,
                         guint percent,
                         gpointer user_data,
+                       GCancellable *cancellable,
                         GError **error)
 {
        struct _db_data *data = (struct _db_data *) user_data;
diff --git a/src/configuration/e-book-config-ews.c b/src/configuration/e-book-config-ews.c
index 9180a60..edfe192 100644
--- a/src/configuration/e-book-config-ews.c
+++ b/src/configuration/e-book-config-ews.c
@@ -95,11 +95,12 @@ book_config_ews_insert_widgets (ESourceConfigBackend *backend,
                ESourceEwsFolder *ews_folder;
                GtkWidget *checkbox;
 
+               ews_folder = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_EWS_FOLDER);
+
                checkbox = gtk_check_button_new_with_mnemonic (_("Use only _primary contact email address"));
                gtk_widget_set_tooltip_text (checkbox, _("When checked, the contacts looked up in the online 
Global Address List will contain only the primary email address"));
                gtk_widget_show (checkbox);
 
-               ews_folder = e_source_get_extension (scratch_source, E_SOURCE_EXTENSION_EWS_FOLDER);
                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox), 
e_source_ews_folder_get_use_primary_address (ews_folder));
 
                e_binding_bind_property (
@@ -108,6 +109,19 @@ book_config_ews_insert_widgets (ESourceConfigBackend *backend,
                        G_BINDING_DEFAULT);
 
                e_source_config_insert_widget (e_source_config_backend_get_config (backend), scratch_source, 
NULL, checkbox);
+
+               checkbox = gtk_check_button_new_with_mnemonic (_("_Fetch contact photos"));
+               gtk_widget_set_tooltip_text (checkbox, _("Tries to look up for user photo"));
+               gtk_widget_show (checkbox);
+
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox), 
e_source_ews_folder_get_fetch_gal_photos (ews_folder));
+
+               e_binding_bind_property (
+                       checkbox, "active",
+                       ews_folder, "fetch-gal-photos",
+                       G_BINDING_DEFAULT);
+
+               e_source_config_insert_widget (e_source_config_backend_get_config (backend), scratch_source, 
NULL, checkbox);
        }
 }
 
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index ca0913c..0cdb467 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -108,6 +108,7 @@ struct _EEwsConnectionPrivate {
        GSList *subscribed_folders;
 
        EEwsServerVersion version;
+       gboolean backoff_enabled;
 };
 
 enum {
@@ -943,7 +944,7 @@ ews_response_cb (SoupSession *session,
                g_free (value);
        }
 
-       if (wait_ms > 0) {
+       if (wait_ms > 0 && e_ews_connection_get_backoff_enabled (enode->cnc)) {
                GCancellable *cancellable = enode->cancellable;
                EFlag *flag;
 
@@ -2071,6 +2072,7 @@ e_ews_connection_init (EEwsConnection *cnc)
 
        cnc->priv->soup_context = g_main_context_new ();
        cnc->priv->soup_loop = g_main_loop_new (cnc->priv->soup_context, FALSE);
+       cnc->priv->backoff_enabled = TRUE;
 
        cnc->priv->subscriptions = g_hash_table_new_full (
                        g_direct_hash, g_direct_equal,
@@ -2773,6 +2775,23 @@ e_ews_connection_ref_soup_session (EEwsConnection *cnc)
        return g_object_ref (cnc->priv->soup_session);
 }
 
+gboolean
+e_ews_connection_get_backoff_enabled (EEwsConnection *cnc)
+{
+       g_return_val_if_fail (E_IS_EWS_CONNECTION (cnc), FALSE);
+
+       return cnc->priv->backoff_enabled;
+}
+
+void
+e_ews_connection_set_backoff_enabled (EEwsConnection *cnc,
+                                     gboolean enabled)
+{
+       g_return_if_fail (E_IS_EWS_CONNECTION (cnc));
+
+       cnc->priv->backoff_enabled = enabled;
+}
+
 static xmlDoc *
 e_ews_autodiscover_ws_xml (const gchar *email_address)
 {
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index fbbad84..30d4ff5 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -451,6 +451,11 @@ CamelEwsSettings *
                e_ews_connection_ref_settings   (EEwsConnection *cnc);
 SoupSession *  e_ews_connection_ref_soup_session
                                                (EEwsConnection *cnc);
+gboolean       e_ews_connection_get_backoff_enabled
+                                               (EEwsConnection *cnc);
+void           e_ews_connection_set_backoff_enabled
+                                               (EEwsConnection *cnc,
+                                                gboolean enabled);
 EEwsConnection *e_ews_connection_find          (const gchar *uri,
                                                 const gchar *username);
 GSList *       e_ews_connection_list_existing  (void); /* EEwsConnection * */
diff --git a/src/server/e-source-ews-folder.c b/src/server/e-source-ews-folder.c
index fccf95d..56ffb98 100644
--- a/src/server/e-source-ews-folder.c
+++ b/src/server/e-source-ews-folder.c
@@ -34,6 +34,7 @@ struct _ESourceEwsFolderPrivate {
        guint freebusy_weeks_before;
        guint freebusy_weeks_after;
        gboolean use_primary_address;
+       gboolean fetch_gal_photos;
 };
 
 enum {
@@ -46,7 +47,8 @@ enum {
        PROP_FREEBUSY_WEEKS_BEFORE,
        PROP_FREEBUSY_WEEKS_AFTER,
        PROP_PUBLIC,
-       PROP_USE_PRIMARY_ADDRESS
+       PROP_USE_PRIMARY_ADDRESS,
+       PROP_FETCH_GAL_PHOTOS
 };
 
 G_DEFINE_TYPE (
@@ -114,6 +116,12 @@ source_ews_folder_set_property (GObject *object,
                                E_SOURCE_EWS_FOLDER (object),
                                g_value_get_boolean (value));
                        return;
+
+               case PROP_FETCH_GAL_PHOTOS:
+                       e_source_ews_folder_set_fetch_gal_photos (
+                               E_SOURCE_EWS_FOLDER (object),
+                               g_value_get_boolean (value));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -188,6 +196,13 @@ source_ews_folder_get_property (GObject *object,
                                e_source_ews_folder_get_use_primary_address (
                                E_SOURCE_EWS_FOLDER (object)));
                        return;
+
+               case PROP_FETCH_GAL_PHOTOS:
+                       g_value_set_boolean (
+                               value,
+                               e_source_ews_folder_get_fetch_gal_photos (
+                               E_SOURCE_EWS_FOLDER (object)));
+                       return;
        }
 
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
@@ -341,6 +356,19 @@ e_source_ews_folder_class_init (ESourceEwsFolderClass *class)
                        G_PARAM_CONSTRUCT |
                        G_PARAM_STATIC_STRINGS |
                        E_SOURCE_PARAM_SETTING));
+
+       g_object_class_install_property (
+               object_class,
+               PROP_FETCH_GAL_PHOTOS,
+               g_param_spec_boolean (
+                       "fetch-gal-photos",
+                       "Fetch GAL Photos",
+                       "Whether fetch photos for GAL contacts",
+                       TRUE,
+                       G_PARAM_READWRITE |
+                       G_PARAM_CONSTRUCT |
+                       G_PARAM_STATIC_STRINGS |
+                       E_SOURCE_PARAM_SETTING));
 }
 
 static void
@@ -647,3 +675,25 @@ e_source_ews_folder_set_use_primary_address (ESourceEwsFolder *extension,
 
        g_object_notify (G_OBJECT (extension), "use-primary-address");
 }
+
+gboolean
+e_source_ews_folder_get_fetch_gal_photos (ESourceEwsFolder *extension)
+{
+       g_return_val_if_fail (E_IS_SOURCE_EWS_FOLDER (extension), FALSE);
+
+       return extension->priv->fetch_gal_photos;
+}
+
+void
+e_source_ews_folder_set_fetch_gal_photos (ESourceEwsFolder *extension,
+                                         gboolean fetch_gal_photos)
+{
+       g_return_if_fail (E_IS_SOURCE_EWS_FOLDER (extension));
+
+       if ((extension->priv->fetch_gal_photos ? 1 : 0) == (fetch_gal_photos ? 1 : 0))
+               return;
+
+       extension->priv->fetch_gal_photos = fetch_gal_photos;
+
+       g_object_notify (G_OBJECT (extension), "fetch-gal-photos");
+}
diff --git a/src/server/e-source-ews-folder.h b/src/server/e-source-ews-folder.h
index b8ea27d..f60eda7 100644
--- a/src/server/e-source-ews-folder.h
+++ b/src/server/e-source-ews-folder.h
@@ -109,6 +109,11 @@ gboolean   e_source_ews_folder_get_use_primary_address
 void           e_source_ews_folder_set_use_primary_address
                                                (ESourceEwsFolder *extension,
                                                 gboolean use_primary_address);
+gboolean       e_source_ews_folder_get_fetch_gal_photos
+                                               (ESourceEwsFolder *extension);
+void           e_source_ews_folder_set_fetch_gal_photos
+                                               (ESourceEwsFolder *extension,
+                                                gboolean fetch_gal_photos);
 
 G_END_DECLS
 


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