[evolution-ews] evolution-ews: implement Exchange categories as evolution label



commit f1ced3cb045a4e509311a37b30d1929eaed1a63b
Author: James Bottomley <James Bottomley HansenPartnership com>
Date:   Mon May 23 14:41:14 2011 +0400

    evolution-ews: implement Exchange categories as evolution label
    
    This patch is a proof of concept for adding evolution labels to an
    exchange back end.  The outlook categories perform roughly the same
    function, and evolution even mirrors their colour scheme.
    
    This patch allows evolution to fill in the labels from the EWS
    Category element.  That means that any colour you add to a message via
    the categories in outlook (or the outlook web server) automatically
    appears in evolution.
    
    The category modification is done from the synchronize backends and
    simply replaces all of the item categories with the camel ones.
    
    Signed-off-by: James Bottomley <James Bottomley parallels com>

 src/camel/camel-ews-folder.c |   26 +++++++++++-
 src/camel/camel-ews-utils.c  |   84 +++++++++++++++++++++++++++++++++++++++++-
 src/camel/camel-ews-utils.h  |    3 +
 src/server/e-ews-item.c      |   39 +++++++++++++++++++
 src/server/e-ews-item.h      |    2 +
 5 files changed, 150 insertions(+), 4 deletions(-)
---
diff --git a/src/camel/camel-ews-folder.c b/src/camel/camel-ews-folder.c
index 7e20fc2..d71f359 100644
--- a/src/camel/camel-ews-folder.c
+++ b/src/camel/camel-ews-folder.c
@@ -60,7 +60,7 @@ which needs to be better organized via functions */
 
 #define MAX_ATTACHMENT_SIZE 1*1024*1024   /*In bytes*/
 
-#define SUMMARY_ITEM_FLAGS "item:ResponseObjects item:Sensitivity item:Importance"
+#define SUMMARY_ITEM_FLAGS "item:ResponseObjects item:Sensitivity item:Importance item:Categories"
 #define ITEM_PROPS "item:Subject item:DateTimeReceived item:DateTimeSent item:DateTimeCreated item:Size " \
 		   "item:HasAttachments item:InReplyTo"
 #define SUMMARY_ITEM_PROPS ITEM_PROPS " " SUMMARY_ITEM_FLAGS
@@ -638,6 +638,22 @@ msg_update_flags (ESoapMessage *msg, gpointer user_data)
 			e_soap_message_end_element (msg); /* Message */
 			e_soap_message_end_element (msg); /* SetItemField */
 		}
+		/* now update the Categories */
+		e_soap_message_start_element (msg, "SetItemField", NULL, NULL);
+
+		e_soap_message_start_element (msg, "FieldURI", NULL, NULL);
+		e_soap_message_add_attribute (msg, "FieldURI", "item:Categories", NULL, NULL);
+		e_soap_message_end_element (msg);
+
+		e_soap_message_start_element (msg, "Message", NULL, NULL);
+		e_soap_message_start_element (msg, "Categories", NULL, NULL);
+
+		ews_utils_replace_server_user_flags(msg, mi);
+
+		e_soap_message_end_element (msg); /* Categories */
+		e_soap_message_end_element (msg); /* Message */
+		e_soap_message_end_element (msg); /* SetItemField */
+
 		e_ews_message_end_item_change (msg);
 
 		camel_message_info_free (mi);
@@ -698,7 +714,11 @@ ews_synchronize_sync (CamelFolder *folder, gboolean expunge, EVO3(GCancellable *
 		} else if (flags_changed & CAMEL_MESSAGE_DELETED) {
 			deleted_uids = g_slist_prepend (deleted_uids, (gpointer) camel_pstring_strdup (uids->pdata [i]));
 			camel_message_info_free (mi);
-		}
+		} else {
+			/* OK, the change must have been the labels */
+			mi_list = g_slist_append (mi_list, mi);
+			mi_list_len++;
+		}			
 
 		if (mi_list_len == EWS_MAX_FETCH_COUNT) {
 			success = ews_sync_mi_flags (folder, mi_list, cancellable, error);
@@ -1328,7 +1348,7 @@ camel_ews_folder_init (CamelEwsFolder *ews_folder)
 
 	folder->permanent_flags = CAMEL_MESSAGE_ANSWERED | CAMEL_MESSAGE_DELETED |
 		CAMEL_MESSAGE_DRAFT | CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_SEEN |
-		CAMEL_MESSAGE_FORWARDED;
+		CAMEL_MESSAGE_FORWARDED | CAMEL_MESSAGE_USER;
 
 	folder->folder_flags = CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY | CAMEL_FOLDER_HAS_SEARCH_CAPABILITY;
 
diff --git a/src/camel/camel-ews-utils.c b/src/camel/camel-ews-utils.c
index dbddc52..481ae05 100644
--- a/src/camel/camel-ews-utils.c
+++ b/src/camel/camel-ews-utils.c
@@ -33,6 +33,7 @@
 #include "camel-ews-utils.h"
 #include "ews-esource-utils.h"
 #include "e-ews-compat.h"
+#include "e-ews-message.h"
 
 #define SUBFOLDER_DIR_NAME     "subfolders"
 #define SUBFOLDER_DIR_NAME_LEN 10
@@ -651,6 +652,86 @@ camel_ews_utils_sync_deleted_items (CamelEwsFolder *ews_folder, GSList *items_de
 	g_slist_free (items_deleted);
 }
 
+static const gchar*
+ews_utils_rename_label (const gchar *cat, int from_cat)
+{
+	gint i;
+
+	/* this is a mapping from Exchange/Outlook categories to
+	 * evolution labels based on the standard colours */
+	const gchar *labels[] = {
+		"Red Category", "$Labelimportant",
+		"Orange Category", "$Labelwork",
+		"Green Category", "$Labelpersonal",
+		"Blue Category", "$Labeltodo",
+		"Purple Category", "$Labellater",
+		NULL, NULL
+	};
+
+	if (!cat || !*cat)
+		return "";
+
+	for (i = 0; labels[i]; i += 2) {
+		if (from_cat) {
+			if (!g_ascii_strcasecmp (cat, labels[i]))
+				return labels[i + 1];
+		} else {
+			if (!g_ascii_strcasecmp (cat, labels[i + 1]))
+				return labels[i];
+		}
+	}
+	return cat;
+}
+
+void
+ews_utils_replace_server_user_flags (ESoapMessage *msg, CamelEwsMessageInfo *mi)
+{
+	const CamelFlag *flag;
+
+	/* transfer camel flags to become the categories as an XML
+	 * array of strings */
+	for (flag = camel_message_info_user_flags (&mi->info); flag;
+	     flag = flag->next) {
+		const gchar *n = ews_utils_rename_label (flag->name, 0);
+		if (*n == '\0')
+			continue;
+		/* This is a mismatch between evolution flags and
+		 * exchange categories.  Evolution uses a
+		 * receipt-handled flag for message receipts, which we
+		 * don't want showing up in the categories, so
+		 * silently drop it here */
+		if (strcmp (n, "receipt-handled") == 0)
+			continue;
+		e_ews_message_write_string_parameter (msg, "String", NULL, n);
+	}
+}
+
+static void
+ews_utils_merge_server_user_flags (EEwsItem *item, CamelEwsMessageInfo *mi)
+{
+	GSList *list = NULL;
+	const GSList *p;
+	const CamelFlag *flag;
+
+	/* transfer camel flags to a list */
+	for (flag = camel_message_info_user_flags (&mi->info); flag;
+	     flag = flag->next)
+		list = g_slist_append (list, (gchar *)flag->name);
+
+	/* we're transferring from server only, so just dump them */
+	for (p = list; p; p = p->next) {
+		camel_flag_set (&mi->info.user_flags, p->data, 0);
+	}
+	//g_slist_foreach(list, (GFunc)g_free, NULL);
+	g_slist_free(list);
+
+	/* now transfer over all the categories */
+	for (p = e_ews_item_get_categories (item); p; p = p->next) {
+		camel_flag_set (&mi->info.user_flags,
+				ews_utils_rename_label(p->data, 1), 1);
+	}
+}
+
 static gint
 ews_utils_get_server_flags (EEwsItem *item)
 {
@@ -833,8 +914,9 @@ camel_ews_utils_sync_updated_items (CamelEwsFolder *ews_folder, GSList *items_up
 			gint server_flags;
 
 			server_flags = ews_utils_get_server_flags (item);
+			ews_utils_merge_server_user_flags (item, mi);
 			if (camel_ews_update_message_info_flags (folder->summary, (CamelMessageInfo *)mi,
-						server_flags, NULL))
+								 server_flags, NULL))
 				camel_folder_change_info_change_uid (ci, mi->info.uid);
 
 			mi->change_key = g_strdup (id->change_key);
diff --git a/src/camel/camel-ews-utils.h b/src/camel/camel-ews-utils.h
index 2c4d02d..961c9a8 100644
--- a/src/camel/camel-ews-utils.h
+++ b/src/camel/camel-ews-utils.h
@@ -89,6 +89,9 @@ void	camel_ews_utils_sync_created_items	(CamelEwsFolder *ews_folder,
 						 GSList *items_created);
 void	camel_ews_utils_sync_updated_items	(CamelEwsFolder *ews_folder,
 						 GSList *items_updated);
+void	ews_utils_replace_server_user_flags	(ESoapMessage *msg,
+						 CamelEwsMessageInfo *mi);
+
 
 G_END_DECLS
 
diff --git a/src/server/e-ews-item.c b/src/server/e-ews-item.c
index 9aa7cda..b3295ee 100644
--- a/src/server/e-ews-item.c
+++ b/src/server/e-ews-item.c
@@ -184,6 +184,12 @@ struct _EEwsItemPrivate {
 
 	EwsId *calendar_item_accept_id;
 
+	/* the evolution labels are implemented as exchange
+	 * Categories.  These appear in the message headers as
+	 * Keywords: and are set and extracted from the EWS server as
+	 * <Categories> which is a string array valued XML element */
+	GSList *categories;
+
 	struct _EEwsContactFields *contact_fields;
 	struct _EEwsTaskFields *task_fields;
 };
@@ -503,6 +509,29 @@ static void parse_extended_property (EEwsItemPrivate *priv, ESoapParameter *para
 	}
 }
 
+static void parse_categories (EEwsItemPrivate *priv, ESoapParameter *param)
+{
+	gchar *value;
+	ESoapParameter *subparam;
+
+	/* release all the old data (if any) */
+	if (priv->categories) {
+		g_slist_foreach (priv->categories, (GFunc) g_free, NULL);
+		g_slist_free (priv->categories);
+		priv->categories = NULL;
+	}
+
+	/* categories are an array of <string> */
+	for (subparam = e_soap_parameter_get_first_child(param);
+	     subparam != NULL;
+	     subparam = e_soap_parameter_get_next_child(subparam)) {
+		value = e_soap_parameter_get_string_value (subparam);
+
+		priv->categories = g_slist_append(priv->categories, value);
+	}
+
+}
+
 static EwsImportance
 parse_importance (ESoapParameter *param)
 {
@@ -882,6 +911,8 @@ e_ews_item_set_from_soap_parameter (EEwsItem *item, ESoapParameter *param)
 			g_free (value);
 		} else if (!g_ascii_strcasecmp (name, "Size")) {
 			priv->size = e_soap_parameter_get_int_value (subparam);
+		} else if (!g_ascii_strcasecmp (name, "Categories")) {
+			parse_categories (priv, subparam);
 		} else if (!g_ascii_strcasecmp (name, "Importance")) {
 			priv->importance = parse_importance (subparam);
 		} else if (!g_ascii_strcasecmp (name, "InReplyTo")) {
@@ -1177,6 +1208,14 @@ e_ews_item_get_from		(EEwsItem *item)
 	return (const EwsMailbox *) item->priv->from;
 }
 
+const GSList *
+e_ews_item_get_categories	(EEwsItem *item)
+{
+	g_return_val_if_fail (E_IS_EWS_ITEM (item), NULL);
+
+	return item->priv->categories;
+}
+
 EwsImportance
 e_ews_item_get_importance	(EEwsItem *item)
 {
diff --git a/src/server/e-ews-item.h b/src/server/e-ews-item.h
index 736aa63..cf3be10 100644
--- a/src/server/e-ews-item.h
+++ b/src/server/e-ews-item.h
@@ -141,6 +141,8 @@ const EwsMailbox *
 		e_ews_item_get_from		(EEwsItem *item);
 EwsImportance
 		e_ews_item_get_importance	(EEwsItem *item);
+const GSList *
+		e_ews_item_get_categories	(EEwsItem *item);
 EwsMailbox *
 		e_ews_item_mailbox_from_soap_param
 						(ESoapParameter *param);



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