evolution-data-server r8445 - in branches/EXCHANGE_MAPI_BRANCH: camel/providers/mapi servers/mapi



Author: jjohnny
Date: Wed Jan 30 10:45:42 2008
New Revision: 8445
URL: http://svn.gnome.org/viewvc/evolution-data-server?rev=8445&view=rev

Log:
Initial support for flag sync


Modified:
   branches/EXCHANGE_MAPI_BRANCH/camel/providers/mapi/ChangeLog
   branches/EXCHANGE_MAPI_BRANCH/camel/providers/mapi/camel-mapi-folder.c
   branches/EXCHANGE_MAPI_BRANCH/camel/providers/mapi/camel-mapi-store.c
   branches/EXCHANGE_MAPI_BRANCH/servers/mapi/ChangeLog
   branches/EXCHANGE_MAPI_BRANCH/servers/mapi/exchange-mapi-connection.c
   branches/EXCHANGE_MAPI_BRANCH/servers/mapi/exchange-mapi-connection.h

Modified: branches/EXCHANGE_MAPI_BRANCH/camel/providers/mapi/camel-mapi-folder.c
==============================================================================
--- branches/EXCHANGE_MAPI_BRANCH/camel/providers/mapi/camel-mapi-folder.c	(original)
+++ branches/EXCHANGE_MAPI_BRANCH/camel/providers/mapi/camel-mapi-folder.c	Wed Jan 30 10:45:42 2008
@@ -41,7 +41,7 @@
 #include "camel-mapi-summary.h"
 
 #define DEBUG_FN( ) printf("----%u %s\n", (unsigned int)pthread_self(), __FUNCTION__);
-#define d(x) x
+#define d(x)
 
 static CamelOfflineFolderClass *parent_class = NULL;
 
@@ -55,6 +55,12 @@
 
 };
 
+/*for syncing flags back to server*/
+typedef struct {
+	guint32 changed;
+	guint32 bits;
+} flags_diff_t;
+
 static CamelMimeMessage *mapi_folder_item_to_msg( CamelFolder *folder, MapiItem *item, CamelException *ex );
 
 
@@ -122,7 +128,6 @@
 static void
 mapi_refresh_info(CamelFolder *folder, CamelException *ex)
 {
-	printf("%s(%d):%s:reached \n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
 	CamelMapiSummary *summary = (CamelMapiSummary *) folder->summary;
 	CamelStoreInfo *si;
 	CamelMapiStore *mapi_store = CAMEL_MAPI_STORE (folder->parent_store);
@@ -147,7 +152,7 @@
 			camel_store_summary_info_free ((CamelStoreSummary *)((CamelMapiStore *)folder->parent_store)->summary, si);
 		}
 		camel_folder_summary_save (folder->summary);
-/* 		camel_store_summary_save ((CamelStoreSummary *)((CamelMapiStore *)folder->parent_store)->summary); */
+		/* 		camel_store_summary_save ((CamelStoreSummary *)((CamelMapiStore *)folder->parent_store)->summary); */
 	} else {
 		/* We probably could not get the messages the first time. (get_folder) failed???!
 		 * so do a get_folder again. And hope that it works
@@ -155,7 +160,7 @@
 		g_print("Reloading folder...something wrong with the summary....\n");
 		//		gw_store_reload_folder (gw_store, folder, 0, ex);
 	}
-//#endif
+	//#endif
 
 }
 
@@ -234,6 +239,7 @@
 		}
 	}
 }
+
 static gboolean
 fetch_items_cb (struct mapi_SPropValue_array *array, const mapi_id_t fid, const mapi_id_t mid, 
 		GSList *streams, GSList *recipients, GSList *attachments, gpointer data)
@@ -336,6 +342,9 @@
 			id = temp_item->mid;
 			item = temp_item;
 		}
+
+		//		d(printf("%s(%d): Entering %s: item->mid %016llX || item->fid %016llX\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, item->mid, item->fid));
+
 		//fixme
 /* 		} else  */
 /* 			id = (char *) item_list->data; */
@@ -345,7 +354,9 @@
 		/************************ First populate summary *************************/
 		mi = NULL;
 		pmi = NULL;
-		pmi = camel_folder_summary_uid (folder->summary, g_strdup_printf ("%016llx",id));
+		char *msg_uid = exchange_mapi_util_mapi_ids_to_uid (item->fid, item->mid);
+		pmi = camel_folder_summary_uid (folder->summary, msg_uid);
+
 		if (pmi) {
 			exists = TRUE;
 			camel_message_info_ref (pmi);
@@ -409,9 +420,9 @@
 /* 				camel_medium_set_header (CAMEL_MEDIUM (mail_msg), "X-Evolution-Source", groupwise_base_url_lookup (priv)); */
 
 			CAMEL_MAPI_FOLDER_REC_LOCK (folder, cache_lock);
-			if ((cache_stream = camel_data_cache_add (mapi_folder->cache, "cache", id, NULL))) {
+			if ((cache_stream = camel_data_cache_add (mapi_folder->cache, "cache", msg_uid, NULL))) {
 				if (camel_data_wrapper_write_to_stream ((CamelDataWrapper *) mail_msg, 	cache_stream) == -1 || camel_stream_flush (cache_stream) == -1)
-					camel_data_cache_remove (mapi_folder->cache, "cache", id, NULL);
+					camel_data_cache_remove (mapi_folder->cache, "cache", msg_uid, NULL);
 				camel_object_unref (cache_stream);
 			}
 
@@ -419,6 +430,7 @@
 			CAMEL_MAPI_FOLDER_REC_UNLOCK (folder, cache_lock);
 		}
 		/******************** Caching stuff ends *************************/
+		g_free (msg_uid);
 		i++;
 	}
 	camel_operation_end (NULL);
@@ -434,25 +446,159 @@
 static void 
 mapi_sync_summary (CamelFolder *folder, CamelException *ex)
 {
-/* 	camel_folder_summary_save (folder->summary); */
-/* 	camel_store_summary_save ((CamelStoreSummary *)((CamelMapiStore *)folder->parent_store)->summary); */
+	camel_folder_summary_save (folder->summary);
+	camel_store_summary_save ((CamelStoreSummary *)((CamelMapiStore *)folder->parent_store)->summary);
+}
+
+static void
+mapi_utils_do_flags_diff (flags_diff_t *diff, guint32 old, guint32 _new)
+{
+	diff->changed = old ^ _new;
+	diff->bits = _new & diff->changed;
+}
+
+static void
+mapi_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
+{
+	CamelMapiStore *mapi_store = CAMEL_MAPI_STORE (folder->parent_store);
+	CamelMapiFolder *mapi_folder = CAMEL_MAPI_FOLDER (folder);
+	CamelMapiStorePrivate *priv = mapi_store->priv;
+	CamelMessageInfo *info = NULL;
+	CamelMapiMessageInfo *mapi_info = NULL;
+	GList *read_items = NULL, *deleted_read_items = NULL, *unread_items = NULL;
+	flags_diff_t diff, unset_flags;
+	const char *folder_id;
+	mapi_id_t fid;
+	int count, i;
+	gboolean status = FALSE;
+	
+
+	GList *deleted_items, *deleted_head;
+	deleted_items = deleted_head = NULL;
+
+	if (((CamelOfflineStore *) mapi_store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL || 
+			((CamelService *)mapi_store)->status == CAMEL_SERVICE_DISCONNECTED) {
+		mapi_sync_summary (folder, ex);
+		return;
+	}
+
+	folder_id =  camel_mapi_store_folder_id_lookup (mapi_store, folder->full_name) ;
+	exchange_mapi_util_mapi_id_from_string (folder_id, &fid);
+
+	CAMEL_SERVICE_REC_LOCK (mapi_store, connect_lock);
+	if (!camel_mapi_store_connected (mapi_store, ex)) {
+		CAMEL_SERVICE_REC_UNLOCK (mapi_store, connect_lock);
+		camel_exception_clear (ex);
+		return;
+	}
+	CAMEL_SERVICE_REC_UNLOCK (mapi_store, connect_lock);
+
+	count = camel_folder_summary_count (folder->summary);
+	CAMEL_MAPI_FOLDER_REC_LOCK (folder, cache_lock);
+	for (i=0 ; i < count ; i++) {
+		info = camel_folder_summary_index (folder->summary, i);
+		mapi_info = (CamelMapiMessageInfo *) info;
+
+		if (mapi_info && (mapi_info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED)) {
+			const char *uid;
+			mapi_id_t *mid = g_new0 (mapi_id_t, 1); /* FIXME : */
+			mapi_id_t temp_fid;
+
+			uid = camel_message_info_uid (info);
+			guint32 flags= camel_message_info_flags (info);
+
+			/* Why are we getting so much noise here :-/ */
+			if (!exchange_mapi_util_mapi_ids_from_uid (uid, &temp_fid, mid))
+				continue;
+
+			mapi_utils_do_flags_diff (&diff, mapi_info->server_flags, mapi_info->info.flags);
+			mapi_utils_do_flags_diff (&unset_flags, flags, mapi_info->server_flags);
+
+			diff.changed &= folder->permanent_flags;
+			if (!diff.changed) {
+				camel_message_info_free(info);
+				continue;
+			} else {
+				if (diff.bits & CAMEL_MESSAGE_DELETED) {
+					if (diff.bits & CAMEL_MESSAGE_SEEN) 
+						read_items = g_list_prepend (read_items, mid);
+					if (deleted_items)
+						deleted_items = g_list_prepend (deleted_items, mid);
+					else {
+						g_list_free (deleted_head);
+						deleted_head = NULL;
+						deleted_head = deleted_items = g_list_prepend (deleted_items, mid);
+					}
+
+					CAMEL_SERVICE_REC_LOCK (mapi_store, connect_lock);
+
+					}
+				}
+				
+				if (diff.bits & CAMEL_MESSAGE_SEEN) {
+					read_items = g_list_prepend (read_items, mid);
+				} else if (unset_flags.bits & CAMEL_MESSAGE_SEEN) {
+					unread_items = g_list_prepend (unread_items, mid);
+				}
+		}
+		camel_message_info_free (info);
+	}
+	
+	CAMEL_MAPI_FOLDER_REC_UNLOCK (folder, cache_lock);
+
+	/* 
+	   Sync up the READ changes before deleting the message. 
+	   Note that if a message is marked as unread and then deleted,
+	   Evo doesnt not take care of it, as I find that scenario to be impractical.
+	*/
+
+	if (read_items) {
+		CAMEL_SERVICE_REC_LOCK (mapi_store, connect_lock);
+		exchange_mapi_set_flags (NULL, fid, read_items, 0);
+		CAMEL_SERVICE_REC_UNLOCK (mapi_store, connect_lock);
+		g_list_free (read_items);
+	}
+
+	if (deleted_items) {
+		CAMEL_SERVICE_REC_LOCK (mapi_store, connect_lock);
+		exchange_mapi_remove_items(NULL, fid, deleted_items);
+		CAMEL_SERVICE_REC_UNLOCK (mapi_store, connect_lock);
+	}
+	/*Remove them from cache*/
+	while (deleted_items) {
+		char* deleted_msg_uid = NULL;
+		deleted_msg_uid = exchange_mapi_util_mapi_ids_to_uid (fid, deleted_items->data);
+		CAMEL_MAPI_FOLDER_REC_LOCK (folder, cache_lock);
+		camel_folder_summary_remove_uid (folder->summary, deleted_msg_uid);
+		camel_data_cache_remove(mapi_folder->cache, "cache", deleted_msg_uid, NULL);
+		CAMEL_MAPI_FOLDER_REC_UNLOCK (folder, cache_lock);
+		deleted_items = g_list_next (deleted_items);
+	}
+
+
+	if (unread_items) {
+		CAMEL_SERVICE_REC_LOCK (mapi_store, connect_lock);
+		/* TODO */
+		CAMEL_SERVICE_REC_UNLOCK (mapi_store, connect_lock);
+		g_list_free (unread_items);
+	}
+
+	if (expunge) {
+		CAMEL_SERVICE_REC_LOCK (mapi_store, connect_lock);
+		/* TODO */
+		CAMEL_SERVICE_REC_UNLOCK (mapi_store, connect_lock);
+	}
+
+	CAMEL_SERVICE_REC_LOCK (mapi_store, connect_lock);
+	mapi_sync_summary (folder, ex);
+	CAMEL_SERVICE_REC_UNLOCK (mapi_store, connect_lock);
 }
 
-static const uint32_t GetPropsList[] = {
-	PR_NORMALIZED_SUBJECT,
-	PR_MESSAGE_SIZE,
-	PR_MESSAGE_DELIVERY_TIME,
-	PR_MESSAGE_FLAGS,
-	PR_SENT_REPRESENTING_NAME,
-	PR_DISPLAY_TO,
-	PR_DISPLAY_CC,
-	PR_DISPLAY_BCC
-};
-static const uint16_t n_GetPropsList = G_N_ELEMENTS (GetPropsList);
 
 void
 mapi_refresh_folder(CamelFolder *folder, CamelException *ex)
 {
+
 	CamelMapiStore *mapi_store = CAMEL_MAPI_STORE (folder->parent_store);
 	CamelMapiFolder *mapi_folder = CAMEL_MAPI_FOLDER (folder);
 	CamelMapiStorePrivate *priv = mapi_store->priv;
@@ -463,14 +609,26 @@
 	gboolean status;
 	GList *list = NULL;
 	GSList *slist = NULL, *sl;
-	//	guint64 *folder_id = g_new0 (guint64, 1);
 	gchar *folder_id = NULL;
 	char *time_string = NULL, *t_str = NULL;
 	struct _folder_update_msg *msg;
 	gboolean check_all = FALSE;
+
+	const guint32 summary_prop_list[] = {
+		PR_NORMALIZED_SUBJECT,
+		PR_MESSAGE_SIZE,
+		PR_MESSAGE_DELIVERY_TIME,
+		PR_MESSAGE_FLAGS,
+		PR_SENT_REPRESENTING_NAME,
+		PR_DISPLAY_TO,
+		PR_DISPLAY_CC,
+		PR_DISPLAY_BCC
+	};
+
+
 	/* Sync-up the (un)read changes before getting updates,
 	so that the getFolderList will reflect the most recent changes too */
-	//	groupwise_sync (folder, FALSE, ex);
+	mapi_sync (folder, FALSE, ex);
 
 	if (((CamelOfflineStore *) mapi_store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
 		g_warning ("In offline mode. Cannot refresh!!!\n");
@@ -479,9 +637,8 @@
 
 	//creating a copy
 	folder_id = camel_mapi_store_folder_id_lookup (mapi_store, folder->full_name);
-	//	printf("%s(%d):%s:folder_id : %d \n", __FILE__, __LINE__, __PRETTY_FUNCTION__, *folder_id);
 	if (!folder_id) {
-		printf ("\nERROR - Folder id not present. Cannot refresh info for %s\n", folder->full_name);
+		d(printf ("\nERROR - Folder id not present. Cannot refresh info for %s\n", folder->full_name));
 		return;
 	}
 
@@ -515,7 +672,9 @@
 			goto end2;
 		}
 
-		status = exchange_mapi_connection_fetch_items (temp_folder_id, GetPropsList, n_GetPropsList, NULL, NULL, fetch_items_cb, folder);
+		status = exchange_mapi_connection_fetch_items (temp_folder_id, summary_prop_list, 
+							       G_N_ELEMENTS (summary_prop_list), NULL, NULL, 
+							       fetch_items_cb, folder);
 
 		if (!status) {
 			camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_INVALID, _("Fetch items failed"));
@@ -584,7 +743,6 @@
 /* 		} */
 
 		if (mapi_folder->priv->item_list) {
-			printf("%s(%d):%s:gonna call \n", __FILE__, __LINE__, __PRETTY_FUNCTION__);
 			mapi_update_cache (folder, mapi_folder->priv->item_list, ex, FALSE);
 		}
 	}
@@ -649,7 +807,6 @@
 	item->header.size = *(glong *)(find_mapi_SPropValue_data (array, PR_MESSAGE_SIZE));
 
 	item->msg.body = g_strdup (find_mapi_SPropValue_data (array, PR_BODY));
-	printf("%s(%d):%s:item->msg.body : %s \n", __FILE__, __LINE__, __PRETTY_FUNCTION__, item->msg.body);
 
 	delivery_date = (struct FILETIME *)find_mapi_SPropValue_data(array, PR_MESSAGE_DELIVERY_TIME);
 	if (delivery_date) {
@@ -737,12 +894,12 @@
 		/* add reply to */
 		addr = camel_internet_address_new();
 		camel_internet_address_add(addr, item->header.from, item->header.from);
-		camel_mime_message_set_reply_to(msg,addr);
+		camel_mime_message_set_reply_to(msg, addr);
 		
 		/* add from */
 		addr = camel_internet_address_new();
 		camel_internet_address_add(addr, item->header.from, item->header.from);
-		camel_mime_message_set_from(msg,addr);
+		camel_mime_message_set_from(msg, addr);
 	}
 }
 
@@ -825,7 +982,6 @@
 
 	/* see if it is there in cache */
 
-	printf("%s(%d):%s:uid : %s \n", __FILE__, __LINE__, __PRETTY_FUNCTION__, uid);
 	mi = (CamelMapiMessageInfo *) camel_folder_summary_uid (folder->summary, uid);
 	if (mi == NULL) {
 		camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_UID,
@@ -1012,7 +1168,7 @@
 	camel_folder_class->search_free = mapi_folder_search_free;
 /* 	camel_folder_class->append_message = mapi_append_message; */
 	camel_folder_class->refresh_info = mapi_refresh_info;
-/* 	camel_folder_class->sync = mapi_sync; */
+	camel_folder_class->sync = mapi_sync;
 /* 	camel_folder_class->expunge = mapi_expunge; */
 /* 	camel_folder_class->transfer_messages_to = mapi_transfer_messages_to; */
 }

Modified: branches/EXCHANGE_MAPI_BRANCH/camel/providers/mapi/camel-mapi-store.c
==============================================================================
--- branches/EXCHANGE_MAPI_BRANCH/camel/providers/mapi/camel-mapi-store.c	(original)
+++ branches/EXCHANGE_MAPI_BRANCH/camel/providers/mapi/camel-mapi-store.c	Wed Jan 30 10:45:42 2008
@@ -235,16 +235,12 @@
 	
 	/*store summary*/
 	path = g_alloca (strlen (priv->storage_path) + 32);
-	sprintf (path, "%s/.summary", priv->storage_path);
 
 	mapi_store->summary = camel_mapi_store_summary_new ();
 	camel_store_summary_set_filename ((CamelStoreSummary *)mapi_store->summary, path);
 
 	camel_store_summary_touch ((CamelStoreSummary *)mapi_store->summary);
 	camel_store_summary_load ((CamelStoreSummary *) mapi_store->summary);
-	printf("%s(%d):%s:summary : %s \n", __FILE__, __LINE__, __PRETTY_FUNCTION__, path);
-	printf("%s(%d):%s:summary : %d \n", __FILE__, __LINE__, __PRETTY_FUNCTION__, 
-	       camel_store_summary_count ((CamelStoreSummary *)mapi_store->summary));	
 
 	/*user and profile*/
 	priv->user = g_strdup (url->user);

Modified: branches/EXCHANGE_MAPI_BRANCH/servers/mapi/exchange-mapi-connection.c
==============================================================================
--- branches/EXCHANGE_MAPI_BRANCH/servers/mapi/exchange-mapi-connection.c	(original)
+++ branches/EXCHANGE_MAPI_BRANCH/servers/mapi/exchange-mapi-connection.c	Wed Jan 30 10:45:42 2008
@@ -1482,6 +1482,70 @@
 	return result;
 }
 
+gboolean
+exchange_mapi_set_flags (uint32_t olFolder, mapi_id_t fid, GSList *mid_list, uint32_t flag)
+{
+	enum MAPISTATUS retval;
+	TALLOC_CTX *mem_ctx;
+	mapi_object_t obj_store;
+	mapi_object_t obj_folder;
+	mapi_object_t obj_message;
+	struct SPropValue *props = NULL;
+	gint propslen = 0;
+	gboolean result = FALSE;
+	GSList *l;
+
+	LOCK ();
+
+	mem_ctx = talloc_init("ExchangeMAPI_ModifyItem");
+	mapi_object_init(&obj_store);
+	mapi_object_init(&obj_folder);
+
+	/* Open the message store */
+	retval = OpenMsgStore(&obj_store);
+	if (retval != MAPI_E_SUCCESS) {
+		mapi_errstr("OpenMsgStore", GetLastError());
+		goto cleanup;
+	}
+
+	/* Attempt to open the folder */
+	retval = OpenFolder(&obj_store, fid, &obj_folder);
+	if (retval != MAPI_E_SUCCESS) {
+		mapi_errstr("OpenFolder", GetLastError());
+		goto cleanup;
+	}
+
+	for (l = mid_list; l != NULL; l = g_slist_next (l)) {
+		mapi_object_init(&obj_message);
+		mapi_id_t mid = *((mapi_id_t *)l->data);
+
+		retval = OpenMessage(&obj_folder, fid, mid, &obj_message, MAPI_MODIFY);
+
+		if (retval != MAPI_E_SUCCESS) {
+			mapi_errstr("OpenMessage", GetLastError());
+			goto cleanup;
+		}
+
+		retval = SetReadFlags(&obj_folder, &obj_message, flag);
+		if (retval != MAPI_E_SUCCESS) {
+			mapi_errstr("SetReadFlags", GetLastError());
+			goto cleanup;
+		}
+
+		mapi_object_release(&obj_message);
+	}
+
+	result = TRUE;
+
+cleanup:
+	mapi_object_release(&obj_folder);
+	mapi_object_release(&obj_store);
+	talloc_free(mem_ctx);
+	UNLOCK ();
+
+	return result;
+}
+
 /* FIXME: param olFolder is never used in the routine. Remove it and cleanup at the backends */
 gboolean
 exchange_mapi_remove_items (uint32_t olFolder, mapi_id_t fid, GSList *mids)
@@ -1498,7 +1562,7 @@
 	d(printf("%s(%d): Entering %s \n", __FILE__, __LINE__, __PRETTY_FUNCTION__));
 
 	LOCK ();
-	LOGALL ();
+	//	LOGALL ();
 	mem_ctx = talloc_init("ExchangeMAPI_RemoveItems");
 	mapi_object_init(&obj_store);
 	mapi_object_init(&obj_folder);
@@ -1536,7 +1600,7 @@
 	mapi_object_release(&obj_folder);
 	mapi_object_release(&obj_store);
 	talloc_free(mem_ctx);
-	LOGNONE();
+	//	LOGNONE();
 	UNLOCK ();
 
 	d(printf("%s(%d): Leaving %s \n", __FILE__, __LINE__, __PRETTY_FUNCTION__));

Modified: branches/EXCHANGE_MAPI_BRANCH/servers/mapi/exchange-mapi-connection.h
==============================================================================
--- branches/EXCHANGE_MAPI_BRANCH/servers/mapi/exchange-mapi-connection.h	(original)
+++ branches/EXCHANGE_MAPI_BRANCH/servers/mapi/exchange-mapi-connection.h	Wed Jan 30 10:45:42 2008
@@ -104,6 +104,10 @@
 			   BuildNameID build_name_id, gpointer ni_data, 
 			   BuildProps build_props, gpointer p_data,
 			   GSList *recipients, GSList *attachments);
+
+gboolean
+exchange_mapi_set_flags (uint32_t olFolder, mapi_id_t fid, GSList *mid_list, uint32_t flag);
+
 gboolean
 exchange_mapi_remove_items (uint32_t olFolder, mapi_id_t fid, GSList *mids);
 



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