[evolution-ews] Bug 792411 - Use GetUserPhoto to lookup sender's photo



commit 4785f636f46d2271173b7c0aeb3eb164cd9d9765
Author: Milan Crha <mcrha redhat com>
Date:   Thu Jan 11 19:21:08 2018 +0100

    Bug 792411 - Use GetUserPhoto to lookup sender's photo

 src/configuration/CMakeLists.txt             |    2 +
 src/configuration/e-ews-photo-source.c       |  274 ++++++++++++++++++++++++++
 src/configuration/e-ews-photo-source.h       |   29 +++
 src/configuration/module-ews-configuration.c |    2 +
 src/server/e-ews-connection.c                |  183 +++++++++++++++++
 src/server/e-ews-connection.h                |   34 ++++
 src/server/e-ews-debug.c                     |   13 +-
 src/server/e-ews-message.c                   |    6 +-
 src/server/e-ews-message.h                   |    1 +
 9 files changed, 539 insertions(+), 5 deletions(-)
---
diff --git a/src/configuration/CMakeLists.txt b/src/configuration/CMakeLists.txt
index b6a298f..76779bb 100644
--- a/src/configuration/CMakeLists.txt
+++ b/src/configuration/CMakeLists.txt
@@ -41,6 +41,8 @@ set(sources
        e-ews-subscribe-foreign-folder.h
        e-ews-ooo-notificator.c
        e-ews-ooo-notificator.h
+       e-ews-photo-source.c
+       e-ews-photo-source.h
 )
 set(extra_defines)
 set(extra_cflags
diff --git a/src/configuration/e-ews-photo-source.c b/src/configuration/e-ews-photo-source.c
new file mode 100644
index 0000000..4d0a26d
--- /dev/null
+++ b/src/configuration/e-ews-photo-source.c
@@ -0,0 +1,274 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2018 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "evolution-ews-config.h"
+
+#include <e-util/e-util.h>
+
+#include "server/camel-ews-settings.h"
+#include "server/e-ews-connection.h"
+
+#include "e-ews-photo-source.h"
+
+/* Standard GObject macros */
+#define E_TYPE_EWS_PHOTO_SOURCE \
+       (e_ews_photo_source_get_type ())
+#define E_EWS_PHOTO_SOURCE(obj) \
+       (G_TYPE_CHECK_INSTANCE_CAST \
+       ((obj), E_TYPE_EWS_PHOTO_SOURCE, EEwsPhotoSource))
+#define E_EWS_PHOTO_SOURCE_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_CAST \
+       ((cls), E_TYPE_EWS_PHOTO_SOURCE, EEwsPhotoSourceClass))
+#define E_IS_EWS_PHOTO_SOURCE(obj) \
+       (G_TYPE_CHECK_INSTANCE_TYPE \
+       ((obj), E_TYPE_EWS_PHOTO_SOURCE))
+#define E_IS_EWS_PHOTO_SOURCE_CLASS(cls) \
+       (G_TYPE_CHECK_CLASS_TYPE \
+       ((cls), E_TYPE_EWS_PHOTO_SOURCE))
+#define E_EWS_PHOTO_SOURCE_GET_CLASS(obj) \
+       (G_TYPE_INSTANCE_GET_CLASS \
+       ((obj), E_TYPE_EWS_PHOTO_SOURCE, EEwsPhotoSourceClass))
+
+typedef struct _EEwsPhotoSource EEwsPhotoSource;
+typedef struct _EEwsPhotoSourceClass EEwsPhotoSourceClass;
+
+struct _EEwsPhotoSource {
+       EExtension parent;
+};
+
+struct _EEwsPhotoSourceClass {
+       EExtensionClass parent_class;
+};
+
+GType e_ews_photo_source_get_type (void) G_GNUC_CONST;
+
+static void ews_photo_source_iface_init (EPhotoSourceInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (EEwsPhotoSource, e_ews_photo_source, E_TYPE_EXTENSION, 0,
+       G_IMPLEMENT_INTERFACE_DYNAMIC (E_TYPE_PHOTO_SOURCE, ews_photo_source_iface_init))
+
+typedef struct _PhotoSourceData {
+       GMutex lock;
+       guint n_running;
+       ESimpleAsyncResult *simple;
+       GCancellable *cancellable;
+} PhotoSourceData;
+
+static void
+ews_photo_source_dec_running (PhotoSourceData *psd)
+{
+       if (!g_atomic_int_dec_and_test (&psd->n_running))
+               return;
+
+       if (psd->simple)
+               e_simple_async_result_complete_idle (psd->simple);
+
+       g_clear_object (&psd->simple);
+       g_clear_object (&psd->cancellable);
+       g_mutex_clear (&psd->lock);
+       g_free (psd);
+}
+
+static void
+ews_photo_source_get_user_photo_cb (GObject *source_object,
+                                   GAsyncResult *result,
+                                   gpointer user_data)
+{
+       PhotoSourceData *psd = user_data;
+       GCancellable *cancellable = NULL;
+       gchar *picture_data = NULL;
+       GError *error = NULL;
+
+       g_return_if_fail (E_IS_EWS_CONNECTION (source_object));
+       g_return_if_fail (psd != NULL);
+
+       g_mutex_lock (&psd->lock);
+
+       if (e_ews_connection_get_user_photo_finish (E_EWS_CONNECTION (source_object), result, &picture_data, 
&error)) {
+               if (psd->simple && picture_data && *picture_data) {
+                       gsize len = 0;
+                       guchar *decoded;
+
+                       decoded = g_base64_decode (picture_data, &len);
+                       if (len && decoded) {
+                               GInputStream *stream;
+
+                               stream = g_memory_input_stream_new_from_data (decoded, len, g_free);
+                               decoded = NULL;
+
+                               e_simple_async_result_set_op_pointer (psd->simple, stream, g_object_unref);
+                               e_simple_async_result_complete_idle (psd->simple);
+                               g_clear_object (&psd->simple);
+
+                               cancellable = g_object_ref (psd->cancellable);
+                       }
+
+                       g_free (decoded);
+               }
+       } else {
+               if (psd->simple && error) {
+                       e_simple_async_result_take_error (psd->simple, error);
+                       error = NULL;
+               }
+       }
+
+       g_mutex_unlock (&psd->lock);
+
+       ews_photo_source_dec_running (psd);
+
+       if (cancellable)
+               g_cancellable_cancel (cancellable);
+
+       g_clear_object (&cancellable);
+       g_clear_error (&error);
+       g_free (picture_data);
+}
+
+static void
+ews_photo_source_get_photo (EPhotoSource *photo_source,
+                           const gchar *email_address,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
+{
+       GSList *connections, *link;
+       GHashTable *covered_uris;
+       PhotoSourceData *psd;
+
+       g_return_if_fail (E_IS_EWS_PHOTO_SOURCE (photo_source));
+       g_return_if_fail (email_address != NULL);
+
+       psd = g_new0 (PhotoSourceData, 1);
+       psd->n_running = 1;
+       psd->simple = e_simple_async_result_new (G_OBJECT (photo_source), callback, user_data, 
ews_photo_source_get_photo);
+       psd->cancellable = camel_operation_new_proxy (cancellable);
+       g_mutex_init (&psd->lock);
+
+       covered_uris = g_hash_table_new_full (camel_strcase_hash, camel_strcase_equal, g_free, NULL);
+       connections = e_ews_connection_list_existing ();
+
+       for (link = connections; link; link = g_slist_next (link)) {
+               EEwsConnection *cnc = link->data;
+               const gchar *uri;
+
+               if (!E_IS_EWS_CONNECTION (cnc) ||
+                   !e_ews_connection_satisfies_server_version (cnc, E_EWS_EXCHANGE_2013))
+                       continue;
+
+               uri = e_ews_connection_get_uri (cnc);
+               if (!uri || !*uri || g_hash_table_contains (covered_uris, uri))
+                       continue;
+
+               g_hash_table_insert (covered_uris, g_strdup (uri), NULL);
+
+               g_atomic_int_inc (&psd->n_running);
+
+               e_ews_connection_get_user_photo (cnc, G_PRIORITY_LOW, email_address, 
E_EWS_SIZE_REQUESTED_48X48,
+                       psd->cancellable, ews_photo_source_get_user_photo_cb, psd);
+       }
+
+       g_slist_free_full (connections, g_object_unref);
+       g_hash_table_destroy (covered_uris);
+
+       ews_photo_source_dec_running (psd);
+}
+
+static gboolean
+ews_photo_source_get_photo_finish (EPhotoSource *photo_source,
+                                  GAsyncResult *result,
+                                  GInputStream **out_stream,
+                                  gint *out_priority,
+                                  GError **error)
+{
+       ESimpleAsyncResult *simple;
+
+       g_return_val_if_fail (E_IS_EWS_PHOTO_SOURCE (photo_source), FALSE);
+       g_return_val_if_fail (E_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
+
+       g_return_val_if_fail (e_simple_async_result_is_valid (result, G_OBJECT (photo_source), 
ews_photo_source_get_photo), FALSE);
+
+       if (out_priority)
+               *out_priority = G_PRIORITY_DEFAULT;
+
+       simple = E_SIMPLE_ASYNC_RESULT (result);
+
+       if (e_simple_async_result_propagate_error (simple, error))
+               return FALSE;
+
+       *out_stream = e_simple_async_result_get_op_pointer (simple);
+       if (*out_stream) {
+               g_object_ref (*out_stream);
+               return TRUE;
+       }
+
+       /* Do not localize the string, it won't go into the UI/be visible to users */
+       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "Not Found");
+
+       return FALSE;
+}
+
+static void
+ews_photo_source_constructed (GObject *object)
+{
+       EPhotoCache *photo_cache;
+
+       /* Chain up to parent's method. */
+       G_OBJECT_CLASS (e_ews_photo_source_parent_class)->constructed (object);
+
+       photo_cache = E_PHOTO_CACHE (e_extension_get_extensible (E_EXTENSION (object)));
+
+       e_photo_cache_add_photo_source (photo_cache, E_PHOTO_SOURCE (object));
+}
+
+static void
+e_ews_photo_source_class_init (EEwsPhotoSourceClass *class)
+{
+       GObjectClass *object_class;
+       EExtensionClass *extension_class;
+
+       object_class = G_OBJECT_CLASS (class);
+       object_class->constructed = ews_photo_source_constructed;
+
+       extension_class = E_EXTENSION_CLASS (class);
+       extension_class->extensible_type = E_TYPE_PHOTO_CACHE;
+}
+
+static void
+e_ews_photo_source_class_finalize (EEwsPhotoSourceClass *class)
+{
+}
+
+static void
+ews_photo_source_iface_init (EPhotoSourceInterface *iface)
+{
+       iface->get_photo = ews_photo_source_get_photo;
+       iface->get_photo_finish = ews_photo_source_get_photo_finish;
+}
+
+static void
+e_ews_photo_source_init (EEwsPhotoSource *extension)
+{
+}
+
+void
+e_ews_photo_source_type_register (GTypeModule *type_module)
+{
+       /* XXX G_DEFINE_DYNAMIC_TYPE declares a static type registration
+        *     function, so we have to wrap it with a public function in
+        *     order to register types from a separate compilation unit. */
+       e_ews_photo_source_register_type (type_module);
+}
diff --git a/src/configuration/e-ews-photo-source.h b/src/configuration/e-ews-photo-source.h
new file mode 100644
index 0000000..f43ea27
--- /dev/null
+++ b/src/configuration/e-ews-photo-source.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2018 Red Hat, Inc. (www.redhat.com)
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef E_EWS_PHOTO_SOURCE_H
+#define E_EWS_PHOTO_SOURCE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+void e_ews_photo_source_type_register (GTypeModule *type_module);
+
+G_END_DECLS
+
+#endif /* E_EWS_PHOTO_SOURCE_H */
diff --git a/src/configuration/module-ews-configuration.c b/src/configuration/module-ews-configuration.c
index 935648c..ca43f4d 100644
--- a/src/configuration/module-ews-configuration.c
+++ b/src/configuration/module-ews-configuration.c
@@ -33,6 +33,7 @@
 #include "e-mail-config-ews-folder-sizes-page.h"
 #include "e-ews-ooo-notificator.h"
 #include "e-ews-config-lookup.h"
+#include "e-ews-photo-source.h"
 
 #include "e-ews-config-ui-extension.h"
 #include "server/e-source-ews-folder.h"
@@ -61,6 +62,7 @@ e_module_load (GTypeModule *type_module)
        e_ews_config_lookup_type_register (type_module);
        e_ews_config_ui_extension_type_register (type_module);
        e_ews_ooo_notificator_type_register (type_module);
+       e_ews_photo_source_type_register (type_module);
 
        e_source_ews_folder_type_register (type_module);
 }
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index ab3b2dc..8daf945 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -146,6 +146,7 @@ struct _EwsAsyncData {
        EwsDelegateDeliver deliver_to;
        EEwsFolderType folder_type;
        EEwsConnection *cnc;
+       gchar *user_photo; /* base64-encoded, as GetUserPhoto result */
 };
 
 struct _EwsNode {
@@ -190,6 +191,7 @@ ews_connection_error_quark (void)
 static void
 async_data_free (EwsAsyncData *async_data)
 {
+       g_free (async_data->user_photo);
        g_free (async_data);
 }
 
@@ -2384,6 +2386,38 @@ e_ews_connection_find (const gchar *uri,
 }
 
 /**
+ * e_ews_connection_list_existing:
+ *
+ * Returns: (transfer full) (element-type EEwsConnection): a new #GSList of all currently
+ *    opened connections to all servers. Free the returned #GSList with
+ *    g_slist_free_full (connections, g_object_unref);
+ *    when no longer needed.
+ **/
+GSList * /* EEwsConnection * */
+e_ews_connection_list_existing (void)
+{
+       GSList *connections = NULL;
+
+       g_mutex_lock (&connecting);
+
+       /* search the connection in our hash table */
+       if (loaded_connections_permissions != NULL) {
+               GHashTableIter iter;
+               gpointer value;
+
+               g_hash_table_iter_init (&iter, loaded_connections_permissions);
+               while (g_hash_table_iter_next (&iter, NULL, &value)) {
+                       if (value)
+                               connections = g_slist_prepend (connections, g_object_ref (value));
+               }
+       }
+
+       g_mutex_unlock (&connecting);
+
+       return connections;
+}
+
+/**
  * e_ews_connection_new_full
  * @uri: Exchange server uri
  * @settings: a #CamelEwsSettings
@@ -10460,3 +10494,152 @@ e_ews_connection_get_server_time_zones_sync (EEwsConnection *cnc,
 
        return success;
 }
+
+static void
+get_user_photo_response_cb (ESoapResponse *response,
+                           GSimpleAsyncResult *simple)
+{
+       EwsAsyncData *async_data;
+       ESoapParameter *param;
+       GError *error = NULL;
+
+       async_data = g_simple_async_result_get_op_res_gpointer (simple);
+
+       param = e_soap_response_get_first_parameter_by_name (
+               response, "PictureData", &error);
+
+       /* Sanity check */
+       g_return_if_fail (
+               (param != NULL && error == NULL) ||
+               (param == NULL && error != NULL));
+
+       if (error != NULL) {
+               g_simple_async_result_take_error (simple, error);
+               return;
+       }
+
+       async_data->user_photo = e_soap_parameter_get_string_value (param);
+       if (async_data->user_photo && !*async_data->user_photo) {
+               g_free (async_data->user_photo);
+               async_data->user_photo = NULL;
+       }
+}
+
+void
+e_ews_connection_get_user_photo (EEwsConnection *cnc,
+                                gint pri,
+                                const gchar *email,
+                                EEwsSizeRequested size_requested,
+                                GCancellable *cancellable,
+                                GAsyncReadyCallback callback,
+                                gpointer user_data)
+{
+       ESoapMessage *msg;
+       GSimpleAsyncResult *simple;
+       EwsAsyncData *async_data;
+       gchar *tmp;
+
+       g_return_if_fail (cnc != NULL);
+       g_return_if_fail (cnc->priv != NULL);
+       g_return_if_fail (email != NULL);
+
+       simple = g_simple_async_result_new (G_OBJECT (cnc), callback, user_data, 
e_ews_connection_get_user_photo);
+       async_data = g_new0 (EwsAsyncData, 1);
+       g_simple_async_result_set_op_res_gpointer (simple, async_data, (GDestroyNotify) async_data_free);
+
+       /*
+        * EWS server version earlier than 2013 doesn't have support to "GetUserPhoto".
+        */
+       if (!e_ews_connection_satisfies_server_version (cnc, E_EWS_EXCHANGE_2013)) {
+               g_simple_async_result_complete_in_idle (simple);
+               g_object_unref (simple);
+               return;
+       }
+
+       msg = e_ews_message_new_with_header (
+               cnc->priv->settings,
+               cnc->priv->uri,
+               cnc->priv->impersonate_user,
+               "GetUserPhoto",
+               NULL,
+               NULL,
+               cnc->priv->version,
+               E_EWS_EXCHANGE_2013,
+               FALSE,
+               TRUE);
+
+       e_soap_message_start_element (msg, "Email", "messages", NULL);
+       e_soap_message_write_string (msg, email);
+       e_soap_message_end_element (msg); /* Email */
+
+       e_soap_message_start_element (msg, "SizeRequested", "messages", NULL);
+       tmp = g_strdup_printf ("HR%dx%d", (gint) size_requested, size_requested);
+       e_soap_message_write_string (msg, tmp);
+       g_free (tmp);
+       e_soap_message_end_element (msg); /* SizeRequested */
+
+       e_ews_message_write_footer (msg); /* Complete the footer and print the request */
+
+       e_ews_connection_queue_request (cnc, msg, get_user_photo_response_cb, pri, cancellable, simple);
+
+       g_object_unref (simple);
+}
+
+gboolean
+e_ews_connection_get_user_photo_finish (EEwsConnection *cnc,
+                                       GAsyncResult *result,
+                                       gchar **out_picture_data, /* base64-encoded */
+                                       GError **error)
+{
+       GSimpleAsyncResult *simple;
+       EwsAsyncData *async_data;
+
+       g_return_val_if_fail (cnc != NULL, FALSE);
+       g_return_val_if_fail (
+               g_simple_async_result_is_valid (result, G_OBJECT (cnc), e_ews_connection_get_user_photo),
+               FALSE);
+       g_return_val_if_fail (out_picture_data != NULL, FALSE);
+
+       simple = G_SIMPLE_ASYNC_RESULT (result);
+       async_data = g_simple_async_result_get_op_res_gpointer (simple);
+
+       if (g_simple_async_result_propagate_error (simple, error))
+               return FALSE;
+
+       if (!async_data->user_photo)
+               return FALSE;
+
+       *out_picture_data = async_data->user_photo;
+       async_data->user_photo = NULL;
+
+       return TRUE;
+}
+
+gboolean
+e_ews_connection_get_user_photo_sync (EEwsConnection *cnc,
+                                     gint pri,
+                                     const gchar *email,
+                                     EEwsSizeRequested size_requested,
+                                     gchar **out_picture_data, /* base64-encoded */
+                                     GCancellable *cancellable,
+                                     GError **error)
+{
+       EAsyncClosure *closure;
+       GAsyncResult *result;
+       gboolean success;
+
+       g_return_val_if_fail (cnc != NULL, FALSE);
+
+       closure = e_async_closure_new ();
+
+       e_ews_connection_get_user_photo (
+               cnc, pri, email, size_requested, cancellable, e_async_closure_callback, closure);
+
+       result = e_async_closure_wait (closure);
+
+       success = e_ews_connection_get_user_photo_finish (cnc, result, out_picture_data, error);
+
+       e_async_closure_free (closure);
+
+       return success;
+}
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index a50bcf9..af74708 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -115,6 +115,19 @@ typedef enum {
        E_EWS_BODY_TYPE_TEXT
 } EEwsBodyType;
 
+typedef enum {
+       E_EWS_SIZE_REQUESTED_UNKNOWN = 0,
+       E_EWS_SIZE_REQUESTED_48X48 = 48,
+       E_EWS_SIZE_REQUESTED_64X64 = 64,
+       E_EWS_SIZE_REQUESTED_96X96 = 96,
+       E_EWS_SIZE_REQUESTED_120X120 = 120,
+       E_EWS_SIZE_REQUESTED_240X240 = 240,
+       E_EWS_SIZE_REQUESTED_360X360 = 360,
+       E_EWS_SIZE_REQUESTED_432X432 = 432,
+       E_EWS_SIZE_REQUESTED_504X504 = 504,
+       E_EWS_SIZE_REQUESTED_648X648 = 648
+} EEwsSizeRequested;
+
 typedef struct {
        gchar *id;
        gchar *dn;
@@ -424,6 +437,7 @@ SoupSession *       e_ews_connection_ref_soup_session
                                                (EEwsConnection *cnc);
 EEwsConnection *e_ews_connection_find          (const gchar *uri,
                                                 const gchar *username);
+GSList *       e_ews_connection_list_existing  (void); /* EEwsConnection * */
 void           e_ews_connection_queue_request  (EEwsConnection *cnc,
                                                 ESoapMessage *msg,
                                                 EEwsResponseCallback cb,
@@ -1302,6 +1316,26 @@ gboolean e_ews_connection_get_server_time_zones_sync
                                                 GSList **tzds, /* EEwsCalendarTimeZoneDefinition */
                                                 GCancellable *cancellable,
                                                 GError **error);
+void           e_ews_connection_get_user_photo (EEwsConnection *cnc,
+                                                gint pri,
+                                                const gchar *email,
+                                                EEwsSizeRequested size_requested,
+                                                GCancellable *cancellable,
+                                                GAsyncReadyCallback callback,
+                                                gpointer user_data);
+gboolean       e_ews_connection_get_user_photo_finish
+                                               (EEwsConnection *cnc,
+                                                GAsyncResult *result,
+                                                gchar **out_picture_data, /* base64-encoded */
+                                                GError **error);
+gboolean       e_ews_connection_get_user_photo_sync
+                                               (EEwsConnection *cnc,
+                                                gint pri,
+                                                const gchar *email,
+                                                EEwsSizeRequested size_requested,
+                                                gchar **out_picture_data, /* base64-encoded */
+                                                GCancellable *cancellable,
+                                                GError **error);
 
 G_END_DECLS
 
diff --git a/src/server/e-ews-debug.c b/src/server/e-ews-debug.c
index 96fe0a4..475f016 100644
--- a/src/server/e-ews-debug.c
+++ b/src/server/e-ews-debug.c
@@ -53,8 +53,10 @@ e_ews_connection_get_server_version_string (EEwsConnection *cnc)
                case E_EWS_EXCHANGE_2010_SP1:
                        return "2010_SP1";
                case E_EWS_EXCHANGE_2010_SP2:
-               case E_EWS_EXCHANGE_FUTURE:
                        return "2010_SP2";
+               case E_EWS_EXCHANGE_2013:
+               case E_EWS_EXCHANGE_FUTURE:
+                       return "2013";
                case E_EWS_EXCHANGE_UNKNOWN:
                        return "Unknown";
                default:
@@ -67,14 +69,19 @@ e_ews_debug_get_server_version_from_string (const gchar *version)
 {
        if (g_strcmp0 (version, "Exchange2007") == 0)
                return E_EWS_EXCHANGE_2007;
-       else if (g_strcmp0 (version, "Exchange2007_SP1") == 0)
+       else if (g_strcmp0 (version, "Exchange2007_SP1") == 0 ||
+                (version && g_str_has_prefix (version, "Exchange2007")))
                return E_EWS_EXCHANGE_2007_SP1;
        else if (g_strcmp0 (version, "Exchange2010") == 0)
                return E_EWS_EXCHANGE_2010;
        else if (g_strcmp0 (version, "Exchange2010_SP1") == 0)
                return E_EWS_EXCHANGE_2010_SP1;
-       else if (g_strcmp0 (version, "Exchange2010_SP2") == 0)
+       else if (g_strcmp0 (version, "Exchange2010_SP2") == 0 ||
+                (version && g_str_has_prefix (version, "Exchange2010")))
                return E_EWS_EXCHANGE_2010_SP2;
+       else if (g_strcmp0 (version, "Exchange2013") == 0 ||
+                (version && g_str_has_prefix (version, "Exchange2013")))
+               return E_EWS_EXCHANGE_2013;
        else
                return E_EWS_EXCHANGE_FUTURE;
 }
diff --git a/src/server/e-ews-message.c b/src/server/e-ews-message.c
index e0aaaf9..e009bf2 100644
--- a/src/server/e-ews-message.c
+++ b/src/server/e-ews-message.c
@@ -70,12 +70,14 @@ convert_server_version_to_string (EEwsServerVersion version)
                        return "Exchange2010";
                case E_EWS_EXCHANGE_2010_SP1:
                        return "Exchange2010_SP1";
+               case E_EWS_EXCHANGE_2010_SP2:
+                       return "Exchange2010_SP2";
                /*
                 * If we don't have support for the latest version, let's use the latest possible
                 */
-               case E_EWS_EXCHANGE_2010_SP2:
                case E_EWS_EXCHANGE_FUTURE:
-                       return "Exchange2010_SP2";
+               case E_EWS_EXCHANGE_2013:
+                       return "Exchange2013";
        }
 
        return "Exchange2007";
diff --git a/src/server/e-ews-message.h b/src/server/e-ews-message.h
index 60b0d6c..21a7eef 100644
--- a/src/server/e-ews-message.h
+++ b/src/server/e-ews-message.h
@@ -36,6 +36,7 @@ typedef enum {
        E_EWS_EXCHANGE_2010,
        E_EWS_EXCHANGE_2010_SP1,
        E_EWS_EXCHANGE_2010_SP2,
+       E_EWS_EXCHANGE_2013,
        E_EWS_EXCHANGE_FUTURE
 } EEwsServerVersion;
 


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