Blame SOURCES/evolution-ews-3.28.5-sync-category-list.patch

12156d
diff -up evolution-ews-3.28.5/src/camel/camel-ews-store.c.sync-category-list evolution-ews-3.28.5/src/camel/camel-ews-store.c
12156d
--- evolution-ews-3.28.5/src/camel/camel-ews-store.c.sync-category-list	2019-10-24 09:39:08.336278207 +0200
12156d
+++ evolution-ews-3.28.5/src/camel/camel-ews-store.c	2019-10-24 09:39:08.341278207 +0200
12156d
@@ -673,6 +673,43 @@ ews_update_has_ooo_set (CamelSession *se
12156d
 	g_clear_object (&oof_settings);
12156d
 }
12156d
 
12156d
+static void
12156d
+ews_exchange_server_categories_cb (CamelSession *session,
12156d
+				   GCancellable *cancellable,
12156d
+				   gpointer user_data,
12156d
+				   GError **error)
12156d
+{
12156d
+	CamelEwsStore *ews_store = user_data;
12156d
+	EEwsConnection *cnc;
12156d
+	EwsFolderId fid = { 0 };
12156d
+	gchar *properties = NULL;
12156d
+	GError *local_error = NULL;
12156d
+
12156d
+	cnc = camel_ews_store_ref_connection (ews_store);
12156d
+	if (!cnc)
12156d
+		return;
12156d
+
12156d
+	fid.id = (gchar *) "calendar";
12156d
+	fid.is_distinguished_id = TRUE;
12156d
+
12156d
+	if (e_ews_connection_get_user_configuration_sync (cnc, G_PRIORITY_DEFAULT, &fid, "CategoryList",
12156d
+		E_EWS_USER_CONFIGURATION_PROPERTIES_XMLDATA, &properties, cancellable, &local_error) && properties) {
12156d
+		guchar *data;
12156d
+		gsize data_len = 0;
12156d
+
12156d
+		data = g_base64_decode (properties, &data_len);
12156d
+
12156d
+		if (data && data_len > 0)
12156d
+			camel_ews_utils_merge_category_list (ews_store, data, data_len);
12156d
+
12156d
+		g_free (data);
12156d
+	}
12156d
+
12156d
+	g_clear_error (&local_error);
12156d
+	g_clear_object (&cnc);
12156d
+	g_free (properties);
12156d
+}
12156d
+
12156d
 struct ScheduleUpdateData
12156d
 {
12156d
 	GCancellable *cancellable;
12156d
@@ -1252,6 +1289,12 @@ ews_connect_sync (CamelService *service,
12156d
 				g_object_ref (ews_store),
12156d
 				g_object_unref);
12156d
 
12156d
+		camel_session_submit_job (
12156d
+			session, _("Look up Exchange server categories"),
12156d
+			ews_exchange_server_categories_cb,
12156d
+			g_object_ref (ews_store),
12156d
+			g_object_unref);
12156d
+
12156d
 		if (!priv->updates_cancellable)
12156d
 			priv->updates_cancellable = g_cancellable_new ();
12156d
 
12156d
@@ -2377,6 +2420,17 @@ ews_get_folder_info_sync (CamelStore *st
12156d
 	ews_store = (CamelEwsStore *) store;
12156d
 	priv = ews_store->priv;
12156d
 
12156d
+	if ((flags & CAMEL_STORE_FOLDER_INFO_REFRESH) != 0 &&
12156d
+	    camel_offline_store_get_online (CAMEL_OFFLINE_STORE (ews_store))) {
12156d
+		CamelSession *session;
12156d
+
12156d
+		session = camel_service_ref_session (CAMEL_SERVICE (ews_store));
12156d
+		if (session) {
12156d
+			ews_exchange_server_categories_cb (session, cancellable, ews_store, NULL);
12156d
+			g_object_unref (session);
12156d
+		}
12156d
+	}
12156d
+
12156d
 	if ((flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST) != 0) {
12156d
 		gboolean includes_last_folder = TRUE;
12156d
 		GSList *folders = NULL, *to_check = NULL;
12156d
diff -up evolution-ews-3.28.5/src/camel/camel-ews-store-summary.c.sync-category-list evolution-ews-3.28.5/src/camel/camel-ews-store-summary.c
12156d
--- evolution-ews-3.28.5/src/camel/camel-ews-store-summary.c.sync-category-list	2018-07-30 16:01:00.000000000 +0200
12156d
+++ evolution-ews-3.28.5/src/camel/camel-ews-store-summary.c	2019-10-24 09:39:08.341278207 +0200
12156d
@@ -31,6 +31,7 @@
12156d
 #define S_UNLOCK(x) (g_rec_mutex_unlock(&(x)->priv->s_lock))
12156d
 
12156d
 #define STORE_GROUP_NAME "##storepriv"
12156d
+#define CATEGORIES_KEY "Categories"
12156d
 #define CURRENT_SUMMARY_VERSION 3
12156d
 
12156d
 struct _CamelEwsStoreSummaryPrivate {
12156d
@@ -1047,3 +1048,159 @@ camel_ews_store_summary_has_folder (Came
12156d
 
12156d
 	return ret;
12156d
 }
12156d
+
12156d
+static gchar *
12156d
+camel_ews_category_to_string (const CamelEwsCategory *cat)
12156d
+{
12156d
+	gchar *guid, *name, *color_def = NULL, *str;
12156d
+
12156d
+	g_return_val_if_fail (cat != NULL, NULL);
12156d
+
12156d
+	guid = g_uri_escape_string (cat->guid, NULL, TRUE);
12156d
+	name = g_uri_escape_string (cat->name, NULL, TRUE);
12156d
+
12156d
+	if (cat->color_def)
12156d
+		color_def = g_uri_escape_string (cat->color_def, NULL, TRUE);
12156d
+
12156d
+	str = g_strconcat (
12156d
+		guid ? guid : "", "\t",
12156d
+		name ? name : "", "\t",
12156d
+		color_def ? color_def : "",
12156d
+		NULL);
12156d
+
12156d
+	g_free (guid);
12156d
+	g_free (name);
12156d
+	g_free (color_def);
12156d
+
12156d
+	return str;
12156d
+}
12156d
+
12156d
+static CamelEwsCategory *
12156d
+camel_ews_category_from_string (const gchar *str)
12156d
+{
12156d
+	CamelEwsCategory *cat;
12156d
+	gchar **strv, *guid, *name, *color_def;
12156d
+
12156d
+	g_return_val_if_fail (str != NULL, NULL);
12156d
+
12156d
+	strv = g_strsplit (str, "\t", -1);
12156d
+	if (!strv || !strv[0] || !strv[1]) {
12156d
+		g_strfreev (strv);
12156d
+		return NULL;
12156d
+	}
12156d
+
12156d
+	guid = g_uri_unescape_string (strv[0], NULL);
12156d
+	name = g_uri_unescape_string (strv[1], NULL);
12156d
+	color_def = (strv[2] && strv[2][0]) ? g_uri_unescape_string (strv[2], NULL) : NULL;
12156d
+
12156d
+	cat = camel_ews_category_new (guid, name, color_def);
12156d
+
12156d
+	g_free (guid);
12156d
+	g_free (name);
12156d
+	g_free (color_def);
12156d
+	g_strfreev (strv);
12156d
+
12156d
+	return cat;
12156d
+}
12156d
+
12156d
+GHashTable * /* gchar *guid ~> CamelEwsCategory * */
12156d
+camel_ews_store_summary_get_categories (CamelEwsStoreSummary *ews_summary)
12156d
+{
12156d
+	GHashTable *categories;
12156d
+	gchar **strv;
12156d
+	g_return_val_if_fail (CAMEL_IS_EWS_STORE_SUMMARY (ews_summary), NULL);
12156d
+
12156d
+	S_LOCK (ews_summary);
12156d
+
12156d
+	strv = g_key_file_get_string_list (ews_summary->priv->key_file, STORE_GROUP_NAME, CATEGORIES_KEY, NULL, NULL);
12156d
+
12156d
+	S_UNLOCK (ews_summary);
12156d
+
12156d
+	categories = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, camel_ews_category_free);
12156d
+
12156d
+	if (strv) {
12156d
+		gint ii;
12156d
+
12156d
+		for (ii = 0; strv[ii]; ii++) {
12156d
+			CamelEwsCategory *cat;
12156d
+
12156d
+			cat = camel_ews_category_from_string (strv[ii]);
12156d
+			if (cat)
12156d
+				g_hash_table_insert (categories, cat->guid, cat);
12156d
+		}
12156d
+
12156d
+		g_strfreev (strv);
12156d
+	}
12156d
+
12156d
+	return categories;
12156d
+}
12156d
+
12156d
+void
12156d
+camel_ews_store_summary_set_categories (CamelEwsStoreSummary *ews_summary,
12156d
+					GHashTable *categories) /* gchar *guid ~> CamelEwsCategory * */
12156d
+{
12156d
+	GPtrArray *array;
12156d
+	GHashTableIter iter;
12156d
+	gpointer value;
12156d
+
12156d
+	g_return_if_fail (CAMEL_IS_EWS_STORE_SUMMARY (ews_summary));
12156d
+	g_return_if_fail (categories != NULL);
12156d
+
12156d
+	array = g_ptr_array_new_full (g_hash_table_size (categories), g_free);
12156d
+
12156d
+	g_hash_table_iter_init (&iter, categories);
12156d
+	while (g_hash_table_iter_next (&iter, NULL, &value)) {
12156d
+		CamelEwsCategory *cat = value;
12156d
+
12156d
+		if (cat) {
12156d
+			gchar *str;
12156d
+
12156d
+			str = camel_ews_category_to_string (cat);
12156d
+
12156d
+			if (str)
12156d
+				g_ptr_array_add (array, str);
12156d
+		}
12156d
+	}
12156d
+
12156d
+	S_LOCK (ews_summary);
12156d
+
12156d
+	g_key_file_set_string_list (ews_summary->priv->key_file, STORE_GROUP_NAME, CATEGORIES_KEY,
12156d
+		(const gchar * const *) array->pdata, array->len);
12156d
+
12156d
+	ews_summary->priv->dirty = TRUE;
12156d
+
12156d
+	S_UNLOCK (ews_summary);
12156d
+
12156d
+	g_ptr_array_free (array, TRUE);
12156d
+}
12156d
+
12156d
+CamelEwsCategory *
12156d
+camel_ews_category_new (const gchar *guid,
12156d
+			const gchar *name,
12156d
+			const gchar *color_def)
12156d
+{
12156d
+	CamelEwsCategory *cat;
12156d
+
12156d
+	g_return_val_if_fail (guid != NULL, NULL);
12156d
+	g_return_val_if_fail (name != NULL, NULL);
12156d
+
12156d
+	cat = g_new0 (CamelEwsCategory, 1);
12156d
+	cat->guid = g_strdup (guid);
12156d
+	cat->name = g_strdup (name);
12156d
+	cat->color_def = g_strdup (color_def);
12156d
+
12156d
+	return cat;
12156d
+}
12156d
+
12156d
+void
12156d
+camel_ews_category_free (gpointer ptr)
12156d
+{
12156d
+	CamelEwsCategory *cat = ptr;
12156d
+
12156d
+	if (cat) {
12156d
+		g_free (cat->guid);
12156d
+		g_free (cat->name);
12156d
+		g_free (cat->color_def);
12156d
+		g_free (cat);
12156d
+	}
12156d
+}
12156d
diff -up evolution-ews-3.28.5/src/camel/camel-ews-store-summary.h.sync-category-list evolution-ews-3.28.5/src/camel/camel-ews-store-summary.h
12156d
--- evolution-ews-3.28.5/src/camel/camel-ews-store-summary.h.sync-category-list	2018-07-30 16:01:00.000000000 +0200
12156d
+++ evolution-ews-3.28.5/src/camel/camel-ews-store-summary.h	2019-10-24 09:39:08.341278207 +0200
12156d
@@ -50,6 +50,12 @@
12156d
 
12156d
 G_BEGIN_DECLS
12156d
 
12156d
+typedef struct _CamelEwsCategory {
12156d
+	gchar *guid;
12156d
+	gchar *name;
12156d
+	gchar *color_def;
12156d
+} CamelEwsCategory;
12156d
+
12156d
 typedef struct _CamelEwsStoreSummary CamelEwsStoreSummary;
12156d
 typedef struct _CamelEwsStoreSummaryClass CamelEwsStoreSummaryClass;
12156d
 typedef struct _CamelEwsStoreSummaryPrivate CamelEwsStoreSummaryPrivate;
12156d
@@ -215,6 +221,17 @@ gchar *		camel_ews_store_summary_get_fol
12156d
 gboolean	camel_ews_store_summary_has_folder
12156d
 						(CamelEwsStoreSummary *ews_summary,
12156d
 						 const gchar *id);
12156d
+GHashTable *	camel_ews_store_summary_get_categories /* gchar *guid ~> CamelEwsCategory * */
12156d
+						(CamelEwsStoreSummary *ews_summary);
12156d
+void		camel_ews_store_summary_set_categories
12156d
+						(CamelEwsStoreSummary *ews_summary,
12156d
+						 GHashTable *categories); /* gchar *guid ~> CamelEwsCategory * */
12156d
+
12156d
+CamelEwsCategory *
12156d
+		camel_ews_category_new		(const gchar *guid,
12156d
+						 const gchar *name,
12156d
+						 const gchar *color_def);
12156d
+void		camel_ews_category_free		(gpointer ptr); /* CamelEwsCategory * */
12156d
 
12156d
 G_END_DECLS
12156d
 
12156d
diff -up evolution-ews-3.28.5/src/camel/camel-ews-utils.c.sync-category-list evolution-ews-3.28.5/src/camel/camel-ews-utils.c
12156d
--- evolution-ews-3.28.5/src/camel/camel-ews-utils.c.sync-category-list	2018-07-30 16:01:00.000000000 +0200
12156d
+++ evolution-ews-3.28.5/src/camel/camel-ews-utils.c	2019-10-24 09:39:08.341278207 +0200
12156d
@@ -29,6 +29,7 @@
12156d
 #include <glib/gstdio.h>
12156d
 
12156d
 #include <libemail-engine/libemail-engine.h>
12156d
+#include <e-util/e-util.h>
12156d
 
12156d
 #include "server/camel-ews-settings.h"
12156d
 #include "server/e-ews-camel-common.h"
12156d
@@ -381,6 +382,43 @@ camel_ews_utils_sync_deleted_items (Came
12156d
 }
12156d
 
12156d
 static const gchar *
12156d
+ews_utils_outlook_color_index_to_color_def (gint color_index)
12156d
+{
12156d
+	const gchar *colors_array[] = {
12156d
+		"#ff1a36", /* Red */
12156d
+		"#ff8c00", /* Orange */
12156d
+		"#f4b10b", /* Peach */
12156d
+		"#fff100", /* Yellow */
12156d
+		"#009e48", /* Green */
12156d
+		"#00b294", /* Teal */
12156d
+		"#89933f", /* Olive */
12156d
+		"#00bcf2", /* Blue */
12156d
+		"#8e69df", /* Purple */
12156d
+		"#f30092", /* Maroon */
12156d
+		"#6c7e9a", /* Steel */
12156d
+		"#425066", /* DarkSteel */
12156d
+		"#969696", /* Gray */
12156d
+		"#525552", /* DarkGray */
12156d
+		"#282828", /* Black */
12156d
+		"#a00023", /* DarkRed */
12156d
+		"#c45502", /* DarkOrange */
12156d
+		"#af7000", /* DarkPeach */
12156d
+		"#b59b02", /* DarkYellow */
12156d
+		"#176002", /* DarkGreen */
12156d
+		"#00725c", /* DarkTeal */
12156d
+		"#5c6022", /* DarkOlive */
12156d
+		"#036393", /* DarkBlue */
12156d
+		"#422f8e", /* DarkPurple */
12156d
+		"#960269"  /* DarkMaroon */
12156d
+	};
12156d
+
12156d
+	if (color_index >= 0 && color_index < G_N_ELEMENTS (colors_array))
12156d
+		return colors_array[color_index];
12156d
+
12156d
+	return NULL;
12156d
+}
12156d
+
12156d
+static const gchar *
12156d
 ews_utils_rename_label (const gchar *cat,
12156d
                         gboolean from_cat)
12156d
 {
12156d
@@ -422,6 +460,58 @@ ews_utils_is_system_user_flag (const gch
12156d
 		g_str_equal (name, "$has-cal");
12156d
 }
12156d
 
12156d
+/* From Exchange name (which allows spaces) to evolution-name */
12156d
+static gchar *
12156d
+camel_ews_utils_encode_category_name (const gchar *name)
12156d
+{
12156d
+	if (name && strchr (name, ' ')) {
12156d
+		GString *str;
12156d
+
12156d
+		str = g_string_sized_new (strlen (name) + 16);
12156d
+
12156d
+		while (*name) {
12156d
+			if (*name == '_')
12156d
+				g_string_append_c (str, '_');
12156d
+
12156d
+			g_string_append_c (str, *name == ' ' ? '_' : *name);
12156d
+
12156d
+			name++;
12156d
+		}
12156d
+
12156d
+		return g_string_free (str, FALSE);
12156d
+	}
12156d
+
12156d
+	return g_strdup (name);
12156d
+}
12156d
+
12156d
+/* From evolution-name to Exchange name (which allows spaces) */
12156d
+static gchar *
12156d
+camel_ews_utils_decode_category_name (const gchar *flag)
12156d
+{
12156d
+	if (flag && strchr (flag, '_')) {
12156d
+		GString *str = g_string_sized_new (strlen (flag));
12156d
+
12156d
+		while (*flag) {
12156d
+			if (*flag == '_') {
12156d
+				if (flag[1] == '_') {
12156d
+					g_string_append_c (str, '_');
12156d
+					flag++;
12156d
+				} else {
12156d
+					g_string_append_c (str, ' ');
12156d
+				}
12156d
+			} else {
12156d
+				g_string_append_c (str, *flag);
12156d
+			}
12156d
+
12156d
+			flag++;
12156d
+		}
12156d
+
12156d
+		return g_string_free (str, FALSE);
12156d
+	}
12156d
+
12156d
+	return g_strdup (flag);
12156d
+}
12156d
+
12156d
 /* free with g_slist_free_full (flags, g_free);
12156d
    the lists' members are values for the String xml element. */
12156d
 GSList *
12156d
@@ -441,6 +531,7 @@ ews_utils_gather_server_user_flags (ESoa
12156d
 	 * array of strings */
12156d
 	for (ii = 0; ii < len; ii++) {
12156d
 		const gchar *n = ews_utils_rename_label (camel_named_flags_get (user_flags, ii), FALSE);
12156d
+
12156d
 		if (*n == '\0')
12156d
 			continue;
12156d
 
12156d
@@ -449,26 +540,7 @@ ews_utils_gather_server_user_flags (ESoa
12156d
 		if (ews_utils_is_system_user_flag (n))
12156d
 			continue;
12156d
 
12156d
-		if (strchr (n, '_')) {
12156d
-			GString *str = g_string_sized_new (strlen (n));
12156d
-
12156d
-			while (*n) {
12156d
-				if (*n == '_') {
12156d
-					if (n[1] == '_')
12156d
-						g_string_append_c (str, '_');
12156d
-					else
12156d
-						g_string_append_c (str, ' ');
12156d
-				} else {
12156d
-					g_string_append_c (str, *n);
12156d
-				}
12156d
-
12156d
-				n++;
12156d
-			}
12156d
-
12156d
-			out_user_flags = g_slist_prepend (out_user_flags, g_string_free (str, FALSE));
12156d
-		} else {
12156d
-			out_user_flags = g_slist_prepend (out_user_flags, g_strdup (n));
12156d
-		}
12156d
+		out_user_flags = g_slist_prepend (out_user_flags, camel_ews_utils_decode_category_name (n));
12156d
 	}
12156d
 
12156d
 	camel_message_info_property_unlock (mi);
12156d
@@ -512,33 +584,17 @@ ews_utils_merge_server_user_flags (EEwsI
12156d
 
12156d
 	/* now transfer over all the categories */
12156d
 	for (p = e_ews_item_get_categories (item); p; p = p->next) {
12156d
-		const gchar *flag = ews_utils_rename_label (p->data, 1);
12156d
-		gchar *underscored = NULL;
12156d
+		const gchar *name = ews_utils_rename_label (p->data, 1);
12156d
+		gchar *flag;
12156d
 
12156d
-		if (!flag || !*flag)
12156d
+		if (!name || !*name)
12156d
 			continue;
12156d
 
12156d
-		if (strchr (flag, ' ')) {
12156d
-			GString *str;
12156d
-
12156d
-			str = g_string_sized_new (strlen (flag) + 16);
12156d
-
12156d
-			while (*flag) {
12156d
-				if (*flag == '_')
12156d
-					g_string_append_c (str, '_');
12156d
-
12156d
-				g_string_append_c (str, *flag == ' ' ? '_' : *flag);
12156d
-
12156d
-				flag++;
12156d
-			}
12156d
-
12156d
-			underscored = g_string_free (str, FALSE);
12156d
-			flag = underscored;
12156d
-		}
12156d
+		flag = camel_ews_utils_encode_category_name (name);
12156d
 
12156d
 		camel_message_info_set_user_flag (mi, flag, TRUE);
12156d
 
12156d
-		g_free (underscored);
12156d
+		g_free (flag);
12156d
 	}
12156d
 
12156d
 	camel_message_info_thaw_notifications (mi);
12156d
@@ -1281,3 +1337,279 @@ camel_ews_utils_ref_corresponding_source
12156d
 
12156d
 	return source;
12156d
 }
12156d
+
12156d
+static gboolean
12156d
+ews_util_equal_label_tag_cb (gconstpointer ptr1,
12156d
+			     gconstpointer ptr2)
12156d
+{
12156d
+	const gchar *evo_label_def = ptr1;
12156d
+	const gchar *tag = ptr2;
12156d
+	const gchar *pos;
12156d
+
12156d
+	if (!evo_label_def || !tag || !*tag)
12156d
+		return FALSE;
12156d
+
12156d
+	pos = g_strrstr (evo_label_def, tag);
12156d
+
12156d
+	return pos > evo_label_def && pos[-1] == '|' && !pos[strlen (tag)];
12156d
+}
12156d
+
12156d
+static gboolean
12156d
+ews_utils_find_in_ptr_array (GPtrArray *haystack,
12156d
+			     gconstpointer needle,
12156d
+			     GEqualFunc equal_func,
12156d
+			     guint *out_index)
12156d
+{
12156d
+	guint ii;
12156d
+
12156d
+	if (!haystack)
12156d
+		return FALSE;
12156d
+
12156d
+	if (!equal_func)
12156d
+		equal_func = g_direct_equal;
12156d
+
12156d
+	for (ii = 0; ii < haystack->len; ii++) {
12156d
+		if (equal_func (haystack->pdata[ii], needle)) {
12156d
+			if (out_index)
12156d
+				*out_index = ii;
12156d
+
12156d
+			return TRUE;
12156d
+		}
12156d
+	}
12156d
+
12156d
+	return FALSE;
12156d
+}
12156d
+
12156d
+/* Returns whether had been done any changes */
12156d
+static gboolean
12156d
+ews_utils_save_category_changes (GHashTable *old_categories, /* gchar *guid ~> CamelEwsCategory * */
12156d
+				 GHashTable *new_categories) /* gchar *guid ~> CamelEwsCategory * */
12156d
+{
12156d
+	GHashTableIter iter;
12156d
+	GSettings *settings;
12156d
+	GPtrArray *evo_labels; /* gchar * (encoded label definition) */
12156d
+	gchar **strv;
12156d
+	gint ii;
12156d
+	gpointer value;
12156d
+	gboolean changed = FALSE;
12156d
+
12156d
+	if (!old_categories || !new_categories)
12156d
+		return new_categories != NULL;
12156d
+
12156d
+	evo_labels = g_ptr_array_new_full (5, g_free);
12156d
+
12156d
+	settings = e_util_ref_settings ("org.gnome.evolution.mail");
12156d
+	strv = g_settings_get_strv (settings, "labels");
12156d
+
12156d
+	for (ii = 0; strv && strv[ii]; ii++) {
12156d
+		g_ptr_array_add (evo_labels, g_strdup (strv[ii]));
12156d
+	}
12156d
+
12156d
+	g_strfreev (strv);
12156d
+
12156d
+	g_hash_table_iter_init (&iter, new_categories);
12156d
+	while (g_hash_table_iter_next (&iter, NULL, &value)) {
12156d
+		CamelEwsCategory *new_cat = value, *old_cat;
12156d
+		gchar *tag = NULL;
12156d
+
12156d
+		if (!new_cat)
12156d
+			continue;
12156d
+
12156d
+		old_cat = g_hash_table_lookup (old_categories, new_cat->guid);
12156d
+		if (old_cat) {
12156d
+			if (g_strcmp0 (old_cat->name, new_cat->name) != 0 ||
12156d
+			    g_strcmp0 (old_cat->color_def, new_cat->color_def) != 0) {
12156d
+				/* Old category changed name or color */
12156d
+				tag = camel_ews_utils_encode_category_name (new_cat->name);
12156d
+			}
12156d
+		} else {
12156d
+			/* This is a new category */
12156d
+			tag = camel_ews_utils_encode_category_name (new_cat->name);
12156d
+		}
12156d
+
12156d
+		if (tag && *tag) {
12156d
+			guint index = (guint) -1;
12156d
+			gchar *label_def;
12156d
+
12156d
+			changed = TRUE;
12156d
+
12156d
+			/* Sanitize value */
12156d
+			for (ii = 0; tag[ii]; ii++) {
12156d
+				if (tag[ii] == '|')
12156d
+					tag[ii] = '-';
12156d
+			}
12156d
+
12156d
+			if (old_cat && g_strcmp0 (old_cat->name, new_cat->name) != 0) {
12156d
+				gchar *old_tag = camel_ews_utils_encode_category_name (old_cat->name);
12156d
+
12156d
+				if (old_tag && *old_tag) {
12156d
+					if (!ews_utils_find_in_ptr_array (evo_labels, old_tag, ews_util_equal_label_tag_cb, &index))
12156d
+						index = (guint) -1;
12156d
+				}
12156d
+
12156d
+				g_free (old_tag);
12156d
+			}
12156d
+
12156d
+			for (ii = 0; new_cat->name[ii]; ii++) {
12156d
+				if (new_cat->name[ii] == '|')
12156d
+					new_cat->name[ii] = '-';
12156d
+			}
12156d
+
12156d
+			if (index == (guint) -1 &&
12156d
+			    !ews_utils_find_in_ptr_array (evo_labels, tag, ews_util_equal_label_tag_cb, &index))
12156d
+				index = (guint) -1;
12156d
+
12156d
+			label_def = g_strconcat (new_cat->name, "|", new_cat->color_def ? new_cat->color_def : "#FF0000", "|", tag, NULL);
12156d
+
12156d
+			if (index == (guint) -1 || index >= (gint) evo_labels->len) {
12156d
+				g_ptr_array_add (evo_labels, label_def);
12156d
+			} else {
12156d
+				g_free (evo_labels->pdata[index]);
12156d
+				evo_labels->pdata[index] = label_def;
12156d
+			}
12156d
+		}
12156d
+
12156d
+		g_hash_table_remove (old_categories, new_cat->guid);
12156d
+
12156d
+		g_free (tag);
12156d
+	}
12156d
+
12156d
+	if (g_hash_table_size (old_categories) > 0) {
12156d
+		/* Some categories had been removed */
12156d
+		changed = TRUE;
12156d
+
12156d
+		g_hash_table_iter_init (&iter, old_categories);
12156d
+		while (g_hash_table_iter_next (&iter, NULL, &value)) {
12156d
+			CamelEwsCategory *old_cat = value;
12156d
+			gchar *old_tag;
12156d
+			guint index;
12156d
+
12156d
+			if (!old_cat)
12156d
+				continue;
12156d
+
12156d
+			old_tag = camel_ews_utils_encode_category_name (old_cat->name);
12156d
+
12156d
+			for (ii = 0; old_tag && old_tag[ii]; ii++) {
12156d
+				if (old_tag[ii] == '|')
12156d
+					old_tag[ii] = '-';
12156d
+			}
12156d
+
12156d
+			if (old_tag &&
12156d
+			    ews_utils_find_in_ptr_array (evo_labels, old_tag, ews_util_equal_label_tag_cb, &index))
12156d
+				g_ptr_array_remove_index (evo_labels, index);
12156d
+
12156d
+			g_free (old_tag);
12156d
+		}
12156d
+	}
12156d
+
12156d
+	if (changed) {
12156d
+		/* NULL-terminated array of strings */
12156d
+		g_ptr_array_add (evo_labels, NULL);
12156d
+
12156d
+		g_settings_set_strv (settings, "labels", (const gchar * const *) evo_labels->pdata);
12156d
+	}
12156d
+
12156d
+	g_ptr_array_free (evo_labels, TRUE);
12156d
+	g_object_unref (settings);
12156d
+
12156d
+	return changed;
12156d
+}
12156d
+
12156d
+void
12156d
+camel_ews_utils_merge_category_list (CamelEwsStore *ews_store,
12156d
+				     const guchar *xml_data,
12156d
+				     gsize xml_data_len)
12156d
+{
12156d
+	xmlDocPtr doc;
12156d
+	xmlXPathContextPtr xpath_ctx;
12156d
+
12156d
+	g_return_if_fail (CAMEL_IS_EWS_STORE (ews_store));
12156d
+	g_return_if_fail (xml_data != NULL);
12156d
+
12156d
+	doc = e_xml_parse_data (xml_data, xml_data_len);
12156d
+	if (!doc)
12156d
+		return;
12156d
+
12156d
+	xpath_ctx = e_xml_new_xpath_context_with_namespaces (doc, "C", "CategoryList.xsd", NULL);
12156d
+
12156d
+	if (xpath_ctx) {
12156d
+		xmlXPathObjectPtr xpath_obj_categories;
12156d
+
12156d
+		xpath_obj_categories = e_xml_xpath_eval (xpath_ctx, "%s", "/C:categories/C:category");
12156d
+
12156d
+		if (xpath_obj_categories) {
12156d
+			GHashTable *old_categories, *new_categories;
12156d
+			gint response_index, response_length;
12156d
+
12156d
+			new_categories = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, camel_ews_category_free);
12156d
+
12156d
+			response_length = xmlXPathNodeSetGetLength (xpath_obj_categories->nodesetval);
12156d
+
12156d
+			for (response_index = 0; response_index < response_length; response_index++) {
12156d
+				xmlXPathObjectPtr xpath_obj_category;
12156d
+
12156d
+				xpath_obj_category = e_xml_xpath_eval (xpath_ctx,
12156d
+					"/C:categories/C:category[%d]",
12156d
+					response_index + 1);
12156d
+
12156d
+				if (xpath_obj_category) {
12156d
+					gchar *name;
12156d
+
12156d
+					name = e_xml_xpath_eval_as_string (xpath_ctx, "/C:categories/C:category[%d]/@name", response_index + 1);
12156d
+
12156d
+					if (name && ews_utils_rename_label (name, 1) == name) {
12156d
+						const gchar *color_def = NULL;
12156d
+						gchar *color, *guid;
12156d
+						gint color_index = -1;
12156d
+
12156d
+						color = e_xml_xpath_eval_as_string (xpath_ctx, "/C:categories/C:category[%d]/@color", response_index + 1);
12156d
+						if (color) {
12156d
+							gchar *endptr = NULL;
12156d
+
12156d
+							color_index = (gint) g_ascii_strtoll (color, &endptr, 10);
12156d
+
12156d
+							if (endptr == color)
12156d
+								color_index = -1;
12156d
+						}
12156d
+
12156d
+						g_free (color);
12156d
+
12156d
+						if (color_index >= 0)
12156d
+							color_def = ews_utils_outlook_color_index_to_color_def (color_index);
12156d
+
12156d
+						guid = e_xml_xpath_eval_as_string (xpath_ctx, "/C:categories/C:category[%d]/@guid", response_index + 1);
12156d
+
12156d
+						if (guid && *guid) {
12156d
+							CamelEwsCategory *cat;
12156d
+
12156d
+							cat = camel_ews_category_new (guid, name, color_def);
12156d
+							if (cat)
12156d
+								g_hash_table_insert (new_categories, cat->guid, cat);
12156d
+						}
12156d
+
12156d
+						g_free (guid);
12156d
+					}
12156d
+
12156d
+					g_free (name);
12156d
+					xmlXPathFreeObject (xpath_obj_category);
12156d
+				}
12156d
+			}
12156d
+
12156d
+			xmlXPathFreeObject (xpath_obj_categories);
12156d
+
12156d
+			old_categories = camel_ews_store_summary_get_categories (ews_store->summary);
12156d
+
12156d
+			if (ews_utils_save_category_changes (old_categories, new_categories)) {
12156d
+				camel_ews_store_summary_set_categories (ews_store->summary, new_categories);
12156d
+				camel_ews_store_summary_save (ews_store->summary, NULL);
12156d
+			}
12156d
+
12156d
+			g_hash_table_destroy (new_categories);
12156d
+			g_hash_table_destroy (old_categories);
12156d
+		}
12156d
+	}
12156d
+
12156d
+	if (xpath_ctx)
12156d
+		xmlXPathFreeContext (xpath_ctx);
12156d
+	xmlFreeDoc (doc);
12156d
+}
12156d
diff -up evolution-ews-3.28.5/src/camel/camel-ews-utils.h.sync-category-list evolution-ews-3.28.5/src/camel/camel-ews-utils.h
12156d
--- evolution-ews-3.28.5/src/camel/camel-ews-utils.h.sync-category-list	2018-07-30 16:01:00.000000000 +0200
12156d
+++ evolution-ews-3.28.5/src/camel/camel-ews-utils.h	2019-10-24 09:39:08.341278207 +0200
12156d
@@ -94,6 +94,10 @@ CamelMessageInfo * /* (transfer full) */
12156d
 						 EEwsConnection *cnc,
12156d
 						 EEwsItem *item,
12156d
 						 GCancellable *cancellable);
12156d
+void		camel_ews_utils_merge_category_list
12156d
+						(CamelEwsStore *ews_store,
12156d
+						 const guchar *xml_data,
12156d
+						 gsize xml_data_len);
12156d
 
12156d
 G_END_DECLS
12156d
 
12156d
diff -up evolution-ews-3.28.5/src/server/e-ews-connection.c.sync-category-list evolution-ews-3.28.5/src/server/e-ews-connection.c
12156d
--- evolution-ews-3.28.5/src/server/e-ews-connection.c.sync-category-list	2019-10-24 09:39:08.339278207 +0200
12156d
+++ evolution-ews-3.28.5/src/server/e-ews-connection.c	2019-10-24 09:46:14.667272312 +0200
12156d
@@ -155,7 +155,7 @@ struct _EwsAsyncData {
12156d
 	EwsDelegateDeliver deliver_to;
12156d
 	EEwsFolderType folder_type;
12156d
 	EEwsConnection *cnc;
12156d
-	gchar *user_photo; /* base64-encoded, as GetUserPhoto result */
12156d
+	gchar *custom_data; /* Can be re-used by operations, will be freed with g_free() */
12156d
 };
12156d
 
12156d
 struct _EwsNode {
12156d
@@ -200,7 +200,7 @@ ews_connection_error_quark (void)
12156d
 static void
12156d
 async_data_free (EwsAsyncData *async_data)
12156d
 {
12156d
-	g_free (async_data->user_photo);
12156d
+	g_free (async_data->custom_data);
12156d
 	g_free (async_data);
12156d
 }
12156d
 
12156d
@@ -10830,10 +10830,10 @@ get_user_photo_response_cb (ESoapRespons
12156d
 		return;
12156d
 	}
12156d
 
12156d
-	async_data->user_photo = e_soap_parameter_get_string_value (param);
12156d
-	if (async_data->user_photo && !*async_data->user_photo) {
12156d
-		g_free (async_data->user_photo);
12156d
-		async_data->user_photo = NULL;
12156d
+	async_data->custom_data = e_soap_parameter_get_string_value (param);
12156d
+	if (async_data->custom_data && !*async_data->custom_data) {
12156d
+		g_free (async_data->custom_data);
12156d
+		async_data->custom_data = NULL;
12156d
 	}
12156d
 }
12156d
 
12156d
@@ -10918,11 +10918,11 @@ e_ews_connection_get_user_photo_finish (
12156d
 	if (g_simple_async_result_propagate_error (simple, error))
12156d
 		return FALSE;
12156d
 
12156d
-	if (!async_data->user_photo)
12156d
+	if (!async_data->custom_data)
12156d
 		return FALSE;
12156d
 
12156d
-	*out_picture_data = async_data->user_photo;
12156d
-	async_data->user_photo = NULL;
12156d
+	*out_picture_data = async_data->custom_data;
12156d
+	async_data->custom_data = NULL;
12156d
 
12156d
 	return TRUE;
12156d
 }
12156d
@@ -10953,5 +10953,256 @@ e_ews_connection_get_user_photo_sync (EE
12156d
 
12156d
 	e_async_closure_free (closure);
12156d
 
12156d
+	return success;
12156d
+}
12156d
+
12156d
+static void
12156d
+get_user_configuration_response_cb (ESoapResponse *response,
12156d
+				    GSimpleAsyncResult *simple)
12156d
+{
12156d
+	EwsAsyncData *async_data;
12156d
+	ESoapParameter *param, *subparam;
12156d
+	GError *error = NULL;
12156d
+
12156d
+	async_data = g_simple_async_result_get_op_res_gpointer (simple);
12156d
+
12156d
+	param = e_soap_response_get_first_parameter_by_name (response, "ResponseMessages", &error);
12156d
+
12156d
+	if (param) {
12156d
+		param = e_soap_parameter_get_first_child_by_name (param, "GetUserConfigurationResponseMessage");
12156d
+		if (!param) {
12156d
+			g_set_error (&error,
12156d
+				SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED,
12156d
+				"Missing <%s> in SOAP response", "GetUserConfigurationResponseMessage");
12156d
+		}
12156d
+	}
12156d
+
12156d
+	if (param) {
12156d
+		param = e_soap_parameter_get_first_child_by_name (param, "UserConfiguration");
12156d
+		if (!param) {
12156d
+			g_set_error (&error,
12156d
+				SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED,
12156d
+				"Missing <%s> in SOAP response", "UserConfiguration");
12156d
+		}
12156d
+	}
12156d
+
12156d
+	/* Sanity check */
12156d
+	g_return_if_fail (
12156d
+		(param != NULL && error == NULL) ||
12156d
+		(param == NULL && error != NULL));
12156d
+
12156d
+	if (error != NULL) {
12156d
+		g_simple_async_result_take_error (simple, error);
12156d
+		return;
12156d
+	}
12156d
+
12156d
+	subparam = e_soap_parameter_get_first_child_by_name (param, "ItemId");
12156d
+	if (subparam) {
12156d
+		gchar *id, *changekey;
12156d
+
12156d
+		id = e_soap_parameter_get_property (subparam, "Id");
12156d
+		changekey = e_soap_parameter_get_property (subparam, "ChangeKey");
12156d
+
12156d
+		/* Encoded as: Id + "\n" + ChangeKey */
12156d
+		async_data->custom_data = g_strconcat (id ? id : "", "\n", changekey, NULL);
12156d
+
12156d
+		g_free (changekey);
12156d
+		g_free (id);
12156d
+	}
12156d
+
12156d
+	if (!subparam) {
12156d
+		subparam = e_soap_parameter_get_first_child_by_name (param, "Dictionary");
12156d
+		if (subparam)
12156d
+			async_data->custom_data = e_soap_response_dump_parameter (response, subparam);
12156d
+	}
12156d
+
12156d
+	if (!subparam) {
12156d
+		subparam = e_soap_parameter_get_first_child_by_name (param, "XmlData");
12156d
+		if (subparam) {
12156d
+			async_data->custom_data = e_soap_parameter_get_string_value (subparam);
12156d
+		}
12156d
+	}
12156d
+
12156d
+	if (!subparam) {
12156d
+		subparam = e_soap_parameter_get_first_child_by_name (param, "BinaryData");
12156d
+		if (subparam) {
12156d
+			async_data->custom_data = e_soap_parameter_get_string_value (subparam);
12156d
+		}
12156d
+	}
12156d
+
12156d
+	if (async_data->custom_data && !*async_data->custom_data) {
12156d
+		g_free (async_data->custom_data);
12156d
+		async_data->custom_data = NULL;
12156d
+	}
12156d
+}
12156d
+
12156d
+static void
12156d
+e_ews_folder_id_append_to_msg (ESoapMessage *msg,
12156d
+			       const gchar *email,
12156d
+			       const EwsFolderId *fid)
12156d
+{
12156d
+	g_return_if_fail (msg != NULL);
12156d
+	g_return_if_fail (fid != NULL);
12156d
+
12156d
+	if (fid->is_distinguished_id)
12156d
+		e_soap_message_start_element (msg, "DistinguishedFolderId", NULL, NULL);
12156d
+	else
12156d
+		e_soap_message_start_element (msg, "FolderId", NULL, NULL);
12156d
+
12156d
+	e_soap_message_add_attribute (msg, "Id", fid->id, NULL, NULL);
12156d
+	if (fid->change_key)
12156d
+		e_soap_message_add_attribute (msg, "ChangeKey", fid->change_key, NULL, NULL);
12156d
+
12156d
+	if (fid->is_distinguished_id && email) {
12156d
+		e_soap_message_start_element (msg, "Mailbox", NULL, NULL);
12156d
+		e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, email);
12156d
+		e_soap_message_end_element (msg);
12156d
+	}
12156d
+
12156d
+	e_soap_message_end_element (msg);
12156d
+}
12156d
+
12156d
+void
12156d
+e_ews_connection_get_user_configuration (EEwsConnection *cnc,
12156d
+					 gint pri,
12156d
+					 const EwsFolderId *fid,
12156d
+					 const gchar *config_name,
12156d
+					 EEwsUserConfigurationProperties props,
12156d
+					 GCancellable *cancellable,
12156d
+					 GAsyncReadyCallback callback,
12156d
+					 gpointer user_data)
12156d
+{
12156d
+	ESoapMessage *msg;
12156d
+	GSimpleAsyncResult *simple;
12156d
+	EwsAsyncData *async_data;
12156d
+	EwsFolderId local_fid;
12156d
+
12156d
+	g_return_if_fail (cnc != NULL);
12156d
+	g_return_if_fail (cnc->priv != NULL);
12156d
+	g_return_if_fail (fid != NULL);
12156d
+	g_return_if_fail (config_name != NULL);
12156d
+
12156d
+	simple = g_simple_async_result_new (G_OBJECT (cnc), callback, user_data, e_ews_connection_get_user_configuration);
12156d
+	async_data = g_new0 (EwsAsyncData, 1);
12156d
+	g_simple_async_result_set_op_res_gpointer (simple, async_data, (GDestroyNotify) async_data_free);
12156d
+
12156d
+	/* EWS server version earlier than 2010 doesn't support it. */
12156d
+	if (!e_ews_connection_satisfies_server_version (cnc, E_EWS_EXCHANGE_2010)) {
12156d
+		g_simple_async_result_complete_in_idle (simple);
12156d
+		g_object_unref (simple);
12156d
+		return;
12156d
+	}
12156d
+
12156d
+	local_fid = *fid;
12156d
+	local_fid.change_key = NULL;
12156d
+
12156d
+	msg = e_ews_message_new_with_header (
12156d
+		cnc->priv->settings,
12156d
+		cnc->priv->uri,
12156d
+		cnc->priv->impersonate_user,
12156d
+		"GetUserConfiguration",
12156d
+		NULL,
12156d
+		NULL,
12156d
+		cnc->priv->version,
12156d
+		E_EWS_EXCHANGE_2010,
12156d
+		FALSE,
12156d
+		TRUE);
12156d
+
12156d
+	e_soap_message_start_element (msg, "UserConfigurationName", "messages", NULL);
12156d
+	e_soap_message_add_attribute (msg, "Name", config_name, NULL, NULL);
12156d
+
12156d
+	e_ews_folder_id_append_to_msg (msg, cnc->priv->email, &local_fid);
12156d
+
12156d
+	e_soap_message_end_element (msg); /* UserConfigurationName */
12156d
+
12156d
+	e_soap_message_start_element (msg, "UserConfigurationProperties", "messages", NULL);
12156d
+
12156d
+	switch (props) {
12156d
+	case E_EWS_USER_CONFIGURATION_PROPERTIES_ID:
12156d
+		e_soap_message_write_string (msg, "Id");
12156d
+		break;
12156d
+	case E_EWS_USER_CONFIGURATION_PROPERTIES_DICTIONARY:
12156d
+		e_soap_message_write_string (msg, "Dictionary");
12156d
+		break;
12156d
+	case E_EWS_USER_CONFIGURATION_PROPERTIES_XMLDATA:
12156d
+		e_soap_message_write_string (msg, "XmlData");
12156d
+		break;
12156d
+	case E_EWS_USER_CONFIGURATION_PROPERTIES_BINARYDATA:
12156d
+		e_soap_message_write_string (msg, "BinaryData");
12156d
+		break;
12156d
+	/* case E_EWS_USER_CONFIGURATION_PROPERTIES_ALL:
12156d
+		e_soap_message_write_string (msg, "All");
12156d
+		break; */
12156d
+	default:
12156d
+		e_soap_message_write_string (msg, "Unknown");
12156d
+		break;
12156d
+	}
12156d
+
12156d
+	e_soap_message_end_element (msg); /* UserConfigurationProperties */
12156d
+
12156d
+	e_ews_message_write_footer (msg);
12156d
+
12156d
+	e_ews_connection_queue_request (cnc, msg, get_user_configuration_response_cb, pri, cancellable, simple);
12156d
+
12156d
+	g_object_unref (simple);
12156d
+}
12156d
+
12156d
+gboolean
12156d
+e_ews_connection_get_user_configuration_finish (EEwsConnection *cnc,
12156d
+						GAsyncResult *result,
12156d
+						gchar **out_properties,
12156d
+						GError **error)
12156d
+{
12156d
+	GSimpleAsyncResult *simple;
12156d
+	EwsAsyncData *async_data;
12156d
+
12156d
+	g_return_val_if_fail (cnc != NULL, FALSE);
12156d
+	g_return_val_if_fail (
12156d
+		g_simple_async_result_is_valid (result, G_OBJECT (cnc), e_ews_connection_get_user_configuration),
12156d
+		FALSE);
12156d
+	g_return_val_if_fail (out_properties != NULL, FALSE);
12156d
+
12156d
+	simple = G_SIMPLE_ASYNC_RESULT (result);
12156d
+	async_data = g_simple_async_result_get_op_res_gpointer (simple);
12156d
+
12156d
+	if (g_simple_async_result_propagate_error (simple, error))
12156d
+		return FALSE;
12156d
+
12156d
+	if (!async_data->custom_data)
12156d
+		return FALSE;
12156d
+
12156d
+	*out_properties = async_data->custom_data;
12156d
+	async_data->custom_data = NULL;
12156d
+
12156d
+	return TRUE;
12156d
+}
12156d
+
12156d
+gboolean
12156d
+e_ews_connection_get_user_configuration_sync (EEwsConnection *cnc,
12156d
+					      gint pri,
12156d
+					      const EwsFolderId *fid,
12156d
+					      const gchar *config_name,
12156d
+					      EEwsUserConfigurationProperties props,
12156d
+					      gchar **out_properties,
12156d
+					      GCancellable *cancellable,
12156d
+					      GError **error)
12156d
+{
12156d
+	EAsyncClosure *closure;
12156d
+	GAsyncResult *result;
12156d
+	gboolean success;
12156d
+
12156d
+	g_return_val_if_fail (cnc != NULL, FALSE);
12156d
+
12156d
+	closure = e_async_closure_new ();
12156d
+
12156d
+	e_ews_connection_get_user_configuration (
12156d
+		cnc, pri, fid, config_name, props, cancellable, e_async_closure_callback, closure);
12156d
+
12156d
+	result = e_async_closure_wait (closure);
12156d
+
12156d
+	success = e_ews_connection_get_user_configuration_finish (cnc, result, out_properties, error);
12156d
+
12156d
+	e_async_closure_free (closure);
12156d
+
12156d
 	return success;
12156d
 }
12156d
diff -up evolution-ews-3.28.5/src/server/e-ews-connection.h.sync-category-list evolution-ews-3.28.5/src/server/e-ews-connection.h
12156d
--- evolution-ews-3.28.5/src/server/e-ews-connection.h.sync-category-list	2019-10-24 09:39:08.339278207 +0200
12156d
+++ evolution-ews-3.28.5/src/server/e-ews-connection.h	2019-10-24 09:39:08.342278207 +0200
12156d
@@ -132,6 +132,15 @@ typedef enum {
12156d
 	E_EWS_SIZE_REQUESTED_648X648 = 648
12156d
 } EEwsSizeRequested;
12156d
 
12156d
+typedef enum {
12156d
+	E_EWS_USER_CONFIGURATION_PROPERTIES_UNKNOWN = -1,
12156d
+	E_EWS_USER_CONFIGURATION_PROPERTIES_ID,
12156d
+	E_EWS_USER_CONFIGURATION_PROPERTIES_DICTIONARY,
12156d
+	E_EWS_USER_CONFIGURATION_PROPERTIES_XMLDATA,
12156d
+	E_EWS_USER_CONFIGURATION_PROPERTIES_BINARYDATA /*,
12156d
+	E_EWS_USER_CONFIGURATION_PROPERTIES_ALL - skip it, be specific */
12156d
+} EEwsUserConfigurationProperties;
12156d
+
12156d
 typedef struct {
12156d
 	gchar *id;
12156d
 	gchar *dn;
12156d
@@ -1377,6 +1386,29 @@ gboolean	e_ews_connection_get_user_photo
12156d
 						 gchar **out_picture_data, /* base64-encoded */
12156d
 						 GCancellable *cancellable,
12156d
 						 GError **error);
12156d
+void		e_ews_connection_get_user_configuration
12156d
+						(EEwsConnection *cnc,
12156d
+						 gint pri,
12156d
+						 const EwsFolderId *fid,
12156d
+						 const gchar *config_name,
12156d
+						 EEwsUserConfigurationProperties props,
12156d
+						 GCancellable *cancellable,
12156d
+						 GAsyncReadyCallback callback,
12156d
+						 gpointer user_data);
12156d
+gboolean	e_ews_connection_get_user_configuration_finish
12156d
+						(EEwsConnection *cnc,
12156d
+						 GAsyncResult *result,
12156d
+						 gchar **out_properties,
12156d
+						 GError **error);
12156d
+gboolean	e_ews_connection_get_user_configuration_sync
12156d
+						(EEwsConnection *cnc,
12156d
+						 gint pri,
12156d
+						 const EwsFolderId *fid,
12156d
+						 const gchar *config_name,
12156d
+						 EEwsUserConfigurationProperties props,
12156d
+						 gchar **out_properties,
12156d
+						 GCancellable *cancellable,
12156d
+						 GError **error);
12156d
 
12156d
 G_END_DECLS
12156d
 
12156d
diff -up evolution-ews-3.28.5/src/server/e-soap-response.c.sync-category-list evolution-ews-3.28.5/src/server/e-soap-response.c
12156d
--- evolution-ews-3.28.5/src/server/e-soap-response.c.sync-category-list	2018-07-30 16:01:00.000000000 +0200
12156d
+++ evolution-ews-3.28.5/src/server/e-soap-response.c	2019-10-24 09:39:08.342278207 +0200
12156d
@@ -685,3 +685,29 @@ e_soap_response_dump_response (ESoapResp
12156d
 
12156d
 	return ret;
12156d
 }
12156d
+
12156d
+gchar *
12156d
+e_soap_response_dump_parameter (ESoapResponse *response,
12156d
+				ESoapParameter *param)
12156d
+{
12156d
+	xmlBuffer *buffer;
12156d
+	gint len;
12156d
+	gchar *data;
12156d
+
12156d
+	g_return_val_if_fail (E_IS_SOAP_RESPONSE (response), NULL);
12156d
+	g_return_val_if_fail (param != NULL, NULL);
12156d
+
12156d
+	buffer = xmlBufferCreate ();
12156d
+	len = xmlNodeDump (buffer, response->priv->xmldoc, param, 0, 0);
12156d
+
12156d
+	if (len <= 0) {
12156d
+		xmlBufferFree (buffer);
12156d
+		return NULL;
12156d
+	}
12156d
+
12156d
+	data = g_strndup ((const gchar *) buffer->content, len);
12156d
+
12156d
+	xmlBufferFree (buffer);
12156d
+
12156d
+	return data;
12156d
+}
12156d
diff -up evolution-ews-3.28.5/src/server/e-soap-response.h.sync-category-list evolution-ews-3.28.5/src/server/e-soap-response.h
12156d
--- evolution-ews-3.28.5/src/server/e-soap-response.h.sync-category-list	2018-07-30 16:01:00.000000000 +0200
12156d
+++ evolution-ews-3.28.5/src/server/e-soap-response.h	2019-10-24 09:39:08.343278207 +0200
12156d
@@ -101,6 +101,8 @@ ESoapParameter *
12156d
 						 const gchar *name);
12156d
 gint		e_soap_response_dump_response	(ESoapResponse *response,
12156d
 						 FILE *buffer);
12156d
+gchar *		e_soap_response_dump_parameter	(ESoapResponse *response,
12156d
+						 ESoapParameter *param);
12156d
 
12156d
 G_END_DECLS
12156d