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

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