[evolution-patches] Exchange offline-online fix



Hi,

Attached patch fixes issues in synchronization
between online and offline modes in exchange.

It fixes #273916, #272986, #311015 and #311020.

Known issues:

* Journal entries are replayed only when the folder which
  has pending operations are refreshed in online mode.

* The journal entries will not get written to the disk file.

* While deleting in offline mode, the mail won't be shown in
  the Delete Items folder until you go online.

I am working on these.

Please review it.

Thanks,
Arunprakash.

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-exchange/ChangeLog,v
retrieving revision 1.356
diff -u -p -r1.356 ChangeLog
--- ChangeLog	20 Jul 2005 06:21:22 -0000	1.356
+++ ChangeLog	21 Jul 2005 11:12:37 -0000
@@ -1,3 +1,44 @@
+2005-07-21  Arunprakash <arunp novell com>
+
+	* camel/camel-exchange-folder.c (refresh_info) : Changed to
+	replay the journal and send refresh command only when in 
+	online mode.
+	(transfer_messages_to) : Changed to make use of the "transfer"
+	journal entry instead of "append" journal entry.
+	* camel/camel-exchange-journal.c (exchange_entry_free)
+	(exchange_entry_load) (exchange_entry_write)
+	(exchange_entry_play) : Updated for
+	the two new journal entry types - "transfer" and "delete".
+	(exchange_entry_play_delete) (exchange_entry_play_transfer) : Added
+	newly for the two new journal entries.
+	(exchange_entry_play_append) : Fixed the copying of the fake message
+	info to the original one. Used camel_exchange_folder_remove_message
+	instead of removing internally.
+	(camel_exchange_journal_transfer) (camel_exchange_journal_delete) :
+	Added newly for creating the journal entries.
+	* camel/camel-exchange-journal.h : Added two new journal entries and
+	the methods for creating them.
+	* camel/camel-exchange-store.c (stub_notification) : Skip the
+	remove message if the message is already removed in offline.
+	* camel/camel-exchange-summary.c (info_set_flags) : Added offline
+	support by creating the journal entry.
+	* mail/mail-stub-exchange.c (linestatus_listener) : Added newly
+	to initialize certain values for the backend in online mode.
+	(folder_update_linestatus) : Newly added, to update the flags
+	for each folder in online mode.
+	(mail_stub_exchange_new) : Modified to hold a reference for the
+	exchange stub and connect to the "linestatus-changed" signal.
+	* mail/mail-stub.c (connection_handler) : Fixed the call to
+	unref without ref for the exchange stub.
+	* shell/e-shell-marshal.list : Added an entry for the new
+	"linestatus-changed" signal.
+	* storage/exchange-component.c (exchange_component_get_offline_listener) :
+	Added newly, to return the offline listener.
+	* storage/exchange-offline-listener.c (online_status_changed) :
+	Modified to emit the new "linestatus-changed" signal.
+	(exchange_offline_listener_class_init) : Modified for
+	registering the new signal "linestatus-changed".
+	
 2005-07-19  Sarfraaz Ahmed <asarfraaz novell com>
 
 	* calendar/e-cal-backend-exchange.c (get_static_capabilities): Removed 
Index: camel/camel-exchange-folder.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-folder.c,v
retrieving revision 1.16
diff -u -p -r1.16 camel-exchange-folder.c
--- camel/camel-exchange-folder.c	16 Mar 2005 07:44:08 -0000	1.16
+++ camel/camel-exchange-folder.c	21 Jul 2005 11:12:38 -0000
@@ -197,12 +197,15 @@ static void
 refresh_info (CamelFolder *folder, CamelException *ex)
 {
 	CamelExchangeFolder *exch = CAMEL_EXCHANGE_FOLDER (folder);
+	CamelOfflineStore *store = CAMEL_OFFLINE_STORE (folder->parent_store);
+
+	if (store->state != CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+		camel_offline_journal_replay (exch->journal, NULL);
 	
-	camel_offline_journal_replay (exch->journal, NULL);
-	
-	camel_stub_send (exch->stub, ex, CAMEL_STUB_CMD_REFRESH_FOLDER,
-			 CAMEL_STUB_ARG_FOLDER, folder->full_name,
-			 CAMEL_STUB_ARG_END);
+		camel_stub_send (exch->stub, ex, CAMEL_STUB_CMD_REFRESH_FOLDER,
+				 CAMEL_STUB_ARG_FOLDER, folder->full_name,
+				 CAMEL_STUB_ARG_END);
+	}
 }
 
 static void
@@ -619,15 +622,14 @@ transfer_messages_to (CamelFolder *sourc
 			if (!(message = get_message (source, camel_message_info_uid (info), ex)))
 				break;
 			
-			camel_exchange_journal_append (journal, message, info, NULL, ex);
+			camel_exchange_journal_transfer (journal, exch_source, message, 
+							 info, uids->pdata[i], NULL,
+							 delete_originals, ex);
+							 
 			camel_object_unref (message);
 
 			if (camel_exception_is_set (ex))
 				break;
-			
-			if (delete_originals)
-				camel_folder_set_message_flags (source, camel_message_info_uid (info),
-								CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_DELETED);
 		}
 		goto end;
  	}
Index: camel/camel-exchange-journal.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-journal.c,v
retrieving revision 1.3
diff -u -p -r1.3 camel-exchange-journal.c
--- camel/camel-exchange-journal.c	16 Mar 2005 07:44:08 -0000	1.3
+++ camel/camel-exchange-journal.c	21 Jul 2005 11:12:38 -0000
@@ -109,6 +109,8 @@ exchange_entry_free (CamelOfflineJournal
 	CamelExchangeJournalEntry *exchange_entry = (CamelExchangeJournalEntry *) entry;
 	
 	g_free (exchange_entry->uid);
+	g_free (exchange_entry->original_uid);
+	g_free (exchange_entry->folder_name);
 	g_free (exchange_entry);
 }
 
@@ -116,6 +118,7 @@ static EDListNode *
 exchange_entry_load (CamelOfflineJournal *journal, FILE *in)
 {
 	CamelExchangeJournalEntry *entry;
+	char *tmp;
 	
 	entry = g_malloc0 (sizeof (CamelExchangeJournalEntry));
 	
@@ -128,6 +131,33 @@ exchange_entry_load (CamelOfflineJournal
 			goto exception;
 		
 		break;
+	case CAMEL_EXCHANGE_JOURNAL_ENTRY_TRANSFER:
+		if (camel_file_util_decode_string (in, &entry->uid) == -1)
+			goto exception;
+		if (camel_file_util_decode_string (in, &entry->original_uid) == -1)
+			goto exception;
+		if (camel_file_util_decode_string (in, &entry->folder_name) == -1)
+			goto exception;
+		if (camel_file_util_decode_string (in, &tmp) == -1)
+			goto exception;
+		if (g_ascii_strcasecmp (tmp, "True") == 0)
+			entry->delete_original = TRUE;
+		else
+			entry->delete_original = FALSE;
+		g_free (tmp);
+		break;
+	case CAMEL_EXCHANGE_JOURNAL_ENTRY_DELETE:
+		if (camel_file_util_decode_string (in, &entry->uid) == -1)
+			goto exception;
+		if (camel_file_util_decode_string (in, &tmp) == -1)
+			goto exception;
+		entry->flags = atoi (tmp);
+		g_free (tmp);
+		if (camel_file_util_decode_string (in, &tmp) == -1)
+			goto exception;
+		entry->set = atoi (tmp);
+		g_free (tmp);
+		break;
 	default:
 		goto exception;
 	}
@@ -136,6 +166,8 @@ exchange_entry_load (CamelOfflineJournal
 	
  exception:
 	
+	g_free (entry->folder_name);
+	g_free (entry->original_uid);
 	g_free (entry->uid);
 	g_free (entry);
 	
@@ -146,6 +178,7 @@ static int
 exchange_entry_write (CamelOfflineJournal *journal, EDListNode *entry, FILE *out)
 {
 	CamelExchangeJournalEntry *exchange_entry = (CamelExchangeJournalEntry *) entry;
+	char *tmp;
 	
 	if (camel_file_util_encode_uint32 (out, exchange_entry->type) == -1)
 		return -1;
@@ -155,6 +188,29 @@ exchange_entry_write (CamelOfflineJourna
 		if (camel_file_util_encode_string (out, exchange_entry->uid))
 			return -1;
 		break;
+	case CAMEL_EXCHANGE_JOURNAL_ENTRY_TRANSFER:
+		if (camel_file_util_encode_string (out, exchange_entry->uid))
+			return -1;
+		if (camel_file_util_encode_string (out, exchange_entry->original_uid))
+			return -1;
+		if (camel_file_util_encode_string (out, exchange_entry->folder_name))
+			return -1;
+		tmp = exchange_entry->delete_original ? "True" : "False";
+		if (camel_file_util_encode_string (out, tmp))
+			return -1;
+		break;
+	case CAMEL_EXCHANGE_JOURNAL_ENTRY_DELETE:
+		if (camel_file_util_encode_string (out, exchange_entry->uid))
+			return -1;
+		tmp = g_strdup_printf ("%u", exchange_entry->flags);
+		if (camel_file_util_encode_string (out, tmp))
+			return -1;
+		g_free (tmp);
+		tmp = g_strdup_printf ("%u", exchange_entry->set);
+		if (camel_file_util_encode_string (out, tmp))
+			return -1;
+		g_free (tmp);
+		break;
 	default:
 		g_assert_not_reached ();
 	}
@@ -174,6 +230,26 @@ exchange_message_info_dup_to (CamelMessa
 }
 
 static int
+exchange_entry_play_delete (CamelOfflineJournal *journal, CamelExchangeJournalEntry *entry, CamelException *ex)
+{
+	CamelExchangeFolder *exchange_folder = (CamelExchangeFolder *) journal->folder;
+
+	camel_stub_send_oneway (exchange_folder->stub,
+				CAMEL_STUB_CMD_SET_MESSAGE_FLAGS,
+				CAMEL_STUB_ARG_FOLDER,
+				((CamelFolder *)exchange_folder)->full_name,
+				CAMEL_STUB_ARG_STRING,
+				entry->uid,
+				CAMEL_STUB_ARG_UINT32,
+				entry->set,
+				CAMEL_STUB_ARG_UINT32,
+				entry->flags,
+				CAMEL_STUB_ARG_END);
+
+	return 0;
+}
+				
+static int
 exchange_entry_play_append (CamelOfflineJournal *journal, CamelExchangeJournalEntry *entry, CamelException *ex)
 {
 	CamelExchangeFolder *exchange_folder = (CamelExchangeFolder *) journal->folder;
@@ -204,28 +280,112 @@ exchange_entry_play_append (CamelOffline
 	
 	camel_exception_init (&lex);
 	camel_folder_append_message (folder, message, info, &uid, &lex);
-	camel_object_unref (message);
 	
 	if (camel_exception_is_set (&lex)) {
 		camel_exception_xfer (ex, &lex);
 		return -1;
 	}
 
-	if (uid != NULL && (real = camel_folder_summary_uid (folder->summary, uid))) {
-			
+	real = camel_folder_summary_info_new_from_message (folder->summary, message);
+	camel_object_unref (message);
+
+	if (uid != NULL && real) {
+		real->uid = g_strdup (uid);
 		exchange_message_info_dup_to ((CamelMessageInfoBase *) real, (CamelMessageInfoBase *) info);
+		camel_folder_summary_add (folder->summary, real);
+		/* FIXME: should a folder_changed event be triggered? */
 	}
 	camel_message_info_free (info);
 	g_free (uid);
 	
  done:
 	
-	camel_folder_summary_remove_uid (folder->summary, entry->uid);
-	camel_data_cache_remove (exchange_folder->cache, "cache", entry->uid, NULL);
+	camel_exchange_folder_remove_message (exchange_folder, entry->uid);
 	
 	return 0;
 }
 
+static int 
+exchange_entry_play_transfer (CamelOfflineJournal *journal, CamelExchangeJournalEntry *entry, CamelException *ex)
+{
+	CamelExchangeFolder *exchange_folder = (CamelExchangeFolder *) journal->folder;
+	CamelFolder *folder = journal->folder;
+	CamelMessageInfo *info, *real;
+	GPtrArray *xuids, *uids;
+	CamelException lex;
+	CamelFolder *src;
+	CamelExchangeStore *store;
+	CamelStream *stream;
+	CamelMimeMessage *message;
+
+	if (!exchange_folder->cache || !(stream = camel_data_cache_get (exchange_folder->cache, "cache", entry->uid, ex)))
+		goto done;
+	
+	message = camel_mime_message_new ();
+	if (camel_data_wrapper_construct_from_stream ((CamelDataWrapper *) message, stream) == -1) {
+		camel_object_unref (message);
+		camel_object_unref (stream);
+		goto done;
+	}
+	
+	camel_object_unref (stream);
+
+	if (!(info = camel_folder_summary_uid (folder->summary, entry->uid))) {
+		/* Note: this should never happen, but rather than crash lets make a new info */
+		info = camel_message_info_new (NULL);
+	}
+
+	if (!entry->folder_name) {
+		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("No folder name found\n"));
+		goto exception;
+	}
+	
+	store = (CamelExchangeStore *) folder->parent_store;
+	g_mutex_lock (store->folders_lock);
+	src = (CamelFolder *) g_hash_table_lookup (store->folders, entry->folder_name);
+	g_mutex_unlock (store->folders_lock);
+	
+	if (src) {
+		uids = g_ptr_array_sized_new (1);
+		g_ptr_array_add (uids, entry->original_uid);
+
+		camel_exception_init (&lex);
+		camel_folder_transfer_messages_to (src, uids, folder, &xuids, entry->delete_original, &lex);
+		if (!camel_exception_is_set (&lex)) {
+			real = camel_folder_summary_info_new_from_message (folder->summary, message);
+			camel_object_unref (message);
+			real->uid = g_strdup ((char *)xuids->pdata[0]);
+			/* Transfer flags */
+			exchange_message_info_dup_to ((CamelMessageInfoBase *) real, (CamelMessageInfoBase *) info);
+			camel_folder_summary_add (folder->summary, real);
+			/* FIXME: should a folder_changed event be triggered? */
+		} else {
+			camel_exception_xfer (ex, &lex);
+			goto exception;
+		}
+
+		g_ptr_array_free (xuids, TRUE);
+		g_ptr_array_free (uids, TRUE);
+		/* camel_object_unref (src); FIXME: should we? */ 
+	} 
+	else {
+		camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, _("Folder doesn't exist"));
+		goto exception;
+	}
+
+	camel_message_info_free (info);
+done:
+	camel_exchange_folder_remove_message (exchange_folder, entry->uid);
+
+	return 0;
+
+exception:
+	
+	camel_message_info_free (info);
+
+	return -1;
+}
+
 static int
 exchange_entry_play (CamelOfflineJournal *journal, EDListNode *entry, CamelException *ex)
 {
@@ -234,6 +394,10 @@ exchange_entry_play (CamelOfflineJournal
 	switch (exchange_entry->type) {
 	case CAMEL_EXCHANGE_JOURNAL_ENTRY_APPEND:
 		return exchange_entry_play_append (journal, exchange_entry, ex);
+ 	case CAMEL_EXCHANGE_JOURNAL_ENTRY_TRANSFER:
+ 		return exchange_entry_play_transfer (journal, exchange_entry, ex);
+	case CAMEL_EXCHANGE_JOURNAL_ENTRY_DELETE:
+		return exchange_entry_play_delete (journal, exchange_entry, ex);
 	default:
 		g_assert_not_reached ();
 		return -1;
@@ -332,3 +496,54 @@ camel_exchange_journal_append (CamelExch
 		*appended_uid = g_strdup (uid);
 
 }
+
+void 
+camel_exchange_journal_transfer (CamelExchangeJournal *exchange_journal, CamelExchangeFolder *source_folder,
+				CamelMimeMessage *message, const CamelMessageInfo *mi,
+				const char *original_uid, char **transferred_uid, gboolean delete_original,
+				CamelException *ex)
+{
+	CamelOfflineJournal *journal = (CamelOfflineJournal *) exchange_journal;
+	CamelExchangeJournalEntry *entry;
+	char *uid;
+	
+	if (!update_cache (exchange_journal, message, mi, &uid, ex))
+		return;
+
+	if(delete_original)
+		camel_exchange_folder_remove_message (source_folder, original_uid);
+
+	entry = g_new (CamelExchangeJournalEntry, 1);
+	entry->type = CAMEL_EXCHANGE_JOURNAL_ENTRY_TRANSFER;
+	entry->uid = uid;
+	entry->original_uid = g_strdup (original_uid);
+	entry->folder_name = g_strdup (((CamelFolder *)source_folder)->full_name);
+	entry->delete_original = delete_original;
+
+	e_dlist_addtail (&journal->queue, (EDListNode *) entry);
+	
+	if (transferred_uid)
+		*transferred_uid = g_strdup (uid);	
+}
+
+void
+camel_exchange_journal_delete (CamelExchangeJournal *exchange_journal,
+			       const char *uid, guint32 flags, guint32 set,
+			       CamelException *ex)
+{
+	CamelOfflineJournal *journal = (CamelOfflineJournal *) exchange_journal;
+	CamelExchangeFolder *exchange_folder = (CamelExchangeFolder *) journal->folder;
+	CamelExchangeJournalEntry *entry;
+
+	if (set & flags & CAMEL_MESSAGE_DELETED)
+		camel_exchange_folder_remove_message (exchange_folder, uid);
+
+	entry = g_new0 (CamelExchangeJournalEntry, 1);
+	entry->type = CAMEL_EXCHANGE_JOURNAL_ENTRY_DELETE;
+	entry->uid = g_strdup (uid);
+	entry->flags = flags;
+	entry->set = set;
+
+	e_dlist_addtail (&journal->queue, (EDListNode *) entry);
+}
+
Index: camel/camel-exchange-journal.h
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-journal.h,v
retrieving revision 1.3
diff -u -p -r1.3 camel-exchange-journal.h
--- camel/camel-exchange-journal.h	16 Mar 2005 07:44:08 -0000	1.3
+++ camel/camel-exchange-journal.h	21 Jul 2005 11:12:38 -0000
@@ -50,6 +50,8 @@ typedef struct _CamelExchangeJournalEntr
 
 enum {
 	CAMEL_EXCHANGE_JOURNAL_ENTRY_APPEND,
+ 	CAMEL_EXCHANGE_JOURNAL_ENTRY_TRANSFER,
+	CAMEL_EXCHANGE_JOURNAL_ENTRY_DELETE
 };
 
 struct _CamelExchangeJournalEntry {
@@ -58,6 +60,11 @@ struct _CamelExchangeJournalEntry {
 	int type;
 
 	char *uid;
+	char *original_uid;
+	char *folder_name;
+	gboolean delete_original;
+	guint32 flags;
+	guint32 set;
 };
 
 struct _CamelExchangeJournal {
@@ -79,6 +86,14 @@ CamelOfflineJournal *camel_exchange_jour
 void camel_exchange_journal_append (CamelExchangeJournal *journal, CamelMimeMessage *message, 
 				    const CamelMessageInfo *mi, char **appended_uid, CamelException *ex);
 
+void camel_exchange_journal_transfer (CamelExchangeJournal *journal, CamelExchangeFolder *source_folder, 
+				      CamelMimeMessage *message, const CamelMessageInfo *mi, 
+				      const char *original_uid, char **transferred_uid, 
+				      gboolean delete_original, CamelException *ex);
+
+void camel_exchange_journal_delete (CamelExchangeJournal *journal, const char *uid, 
+				    guint32 flags, guint32 set, CamelException *ex);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
Index: camel/camel-exchange-store.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-store.c,v
retrieving revision 1.17
diff -u -p -r1.17 camel-exchange-store.c
--- camel/camel-exchange-store.c	28 Jun 2005 10:46:34 -0000	1.17
+++ camel/camel-exchange-store.c	21 Jul 2005 11:12:38 -0000
@@ -709,6 +709,7 @@ stub_notification (CamelObject *object, 
 	{
 		CamelExchangeFolder *folder;
 		char *folder_name, *uid;
+		CamelMessageInfo *info;
 
 		if (camel_stub_marshal_decode_folder (stub->status, &folder_name) == -1 ||
 		    camel_stub_marshal_decode_string (stub->status, &uid) == -1)
@@ -717,8 +718,10 @@ stub_notification (CamelObject *object, 
 		g_mutex_lock (exch->folders_lock);
 		folder = g_hash_table_lookup (exch->folders, folder_name);
 		g_mutex_unlock (exch->folders_lock);
-		if (folder)
+		if (folder && (info = camel_folder_summary_uid (((CamelFolder *)folder)->summary, uid))) {
+			camel_message_info_free (info);
 			camel_exchange_folder_remove_message (folder, uid);
+		}
 
 		g_free (folder_name);
 		g_free (uid);
Index: camel/camel-exchange-summary.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-summary.c,v
retrieving revision 1.3
diff -u -p -r1.3 camel-exchange-summary.c
--- camel/camel-exchange-summary.c	12 Nov 2004 05:56:19 -0000	1.3
+++ camel/camel-exchange-summary.c	21 Jul 2005 11:12:38 -0000
@@ -30,9 +30,11 @@
 
 #include <camel/camel-exchange-summary.h>
 #include <camel/camel-file-utils.h>
+#include <camel/camel-offline-store.h>
 
 #include "camel-stub.h"
 #include "camel-exchange-folder.h"
+#include "camel-exchange-journal.h"
 
 #define CAMEL_EXCHANGE_SUMMARY_VERSION (1)
 
@@ -222,21 +224,34 @@ static gboolean
 info_set_flags(CamelMessageInfo *info, guint32 flags, guint32 set)
 {
 	int res;
+	CamelFolder *folder = (CamelFolder *) info->summary->folder;
+	CamelOfflineStore *store = (CamelOfflineStore *) folder->parent_store;
 
 	if (CAMEL_EXCHANGE_SUMMARY (info->summary)->readonly)
 		return FALSE;
 
-	res = CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->info_set_flags(info, flags, set);
-	if (res && info->summary->folder && info->uid) {
-		camel_stub_send_oneway (((CamelExchangeFolder *)info->summary->folder)->stub,
-					CAMEL_STUB_CMD_SET_MESSAGE_FLAGS,
-					CAMEL_STUB_ARG_FOLDER, info->summary->folder->full_name,
-					CAMEL_STUB_ARG_STRING, info->uid,
-					CAMEL_STUB_ARG_UINT32, set,
-					CAMEL_STUB_ARG_UINT32, flags,
-					CAMEL_STUB_ARG_END);
+	if (store->state != CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+		res = CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->info_set_flags(info, flags, set);
+		if (res && info->summary->folder && info->uid) {
+			camel_stub_send_oneway (((CamelExchangeFolder *)info->summary->folder)->stub,
+						CAMEL_STUB_CMD_SET_MESSAGE_FLAGS,
+						CAMEL_STUB_ARG_FOLDER, info->summary->folder->full_name,
+						CAMEL_STUB_ARG_STRING, info->uid,
+						CAMEL_STUB_ARG_UINT32, set,
+						CAMEL_STUB_ARG_UINT32, flags,
+						CAMEL_STUB_ARG_END);
+		}
+	}
+	else {
+		res = CAMEL_FOLDER_SUMMARY_CLASS (parent_class)->info_set_flags(info, flags, set);
+		if(res && info->summary->folder && info->uid) {
+			CamelExchangeFolder *exchange_folder = (CamelExchangeFolder *) info->summary->folder;
+			CamelExchangeJournal *journal = (CamelExchangeJournal *) exchange_folder->journal;
+			camel_exchange_journal_delete (journal, info->uid, flags, set, NULL);
+		}
+		else
+			return FALSE;
 	}
-
 	return res;
 }
 
Index: mail/mail-stub-exchange.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/mail/mail-stub-exchange.c,v
retrieving revision 1.16
diff -u -p -r1.16 mail-stub-exchange.c
--- mail/mail-stub-exchange.c	28 Jun 2005 09:20:46 -0000	1.16
+++ mail/mail-stub-exchange.c	21 Jul 2005 11:12:39 -0000
@@ -125,6 +125,12 @@ static gboolean process_flags (gpointer 
 
 static void storage_folder_changed (EFolder *folder, gpointer user_data);
 
+static void linestatus_listener (ExchangeOfflineListener *listener,
+						    gint linestatus,
+						    gpointer data);
+static void folder_update_linestatus (gpointer key, gpointer value, gpointer data);
+
+
 static void
 class_init (GObjectClass *object_class)
 {
@@ -2622,6 +2628,78 @@ stub_connect (MailStub *stub)
 	mail_stub_return_ok (stub);
 }
 
+static void 
+linestatus_listener (ExchangeOfflineListener *listener,
+					gint linestatus,
+					gpointer data)
+{
+	MailStubExchange *mse = MAIL_STUB_EXCHANGE (data);
+	ExchangeAccount *account = mse->account;
+	const char *uri;
+	
+	if (linestatus == ONLINE_MODE) {
+		mse->ctx = exchange_account_get_context (account);
+		g_object_ref (mse->ctx);
+
+		mse->mail_submission_uri = exchange_account_get_standard_uri (account, "sendmsg");
+		uri = exchange_account_get_standard_uri (account, "inbox");
+		mse->inbox = exchange_account_get_folder (account, uri);
+		uri = exchange_account_get_standard_uri (account, "deleteditems");
+		mse->deleted_items = exchange_account_get_folder (account, uri);
+		g_hash_table_foreach (mse->folders_by_name,
+				      (GHFunc) folder_update_linestatus,
+				      GINT_TO_POINTER (linestatus));
+	}
+}
+
+static void
+folder_update_linestatus (gpointer key, gpointer value, gpointer data)
+{
+	MailStubExchangeFolder *mfld = (MailStubExchangeFolder *) value;
+	E2kResult *results;
+	int nresults = 0;
+	E2kHTTPStatus status;
+	const char *prop;
+	gint linestatus = GPOINTER_TO_INT (data);
+	
+	if (linestatus == ONLINE_MODE) {
+		status = e_folder_exchange_propfind (mfld->folder, NULL,
+						     open_folder_props,
+						     n_open_folder_props,
+						     &results, &nresults);
+		
+		if (status == E2K_HTTP_UNAUTHORIZED) {
+			got_folder_error (mfld, _("Could not open folder: Permission denied"));
+			return;
+		} else if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
+			g_warning ("got_folder_props: %d", status);
+			got_folder_error (mfld, _("Could not open folder"));
+			return;
+		}
+
+		if (nresults) {
+			prop = e2k_properties_get_prop (results[0].props, PR_ACCESS);
+			if (prop)
+				mfld->access = atoi (prop);
+			else
+				mfld->access = ~0;
+		} else
+			mfld->access = ~0;
+
+		if (!(mfld->access & MAPI_ACCESS_READ)) {
+			got_folder_error (mfld, _("Could not open folder: Permission denied"));
+			return;
+		}
+
+		prop = e2k_properties_get_prop (results[0].props, PR_DELETED_COUNT_TOTAL);
+		if (prop)
+			mfld->deleted_count = atoi (prop);
+	}
+	else {
+		/* FIXME: need any undo for offline */ ;
+	}
+}
+
 /**
  * mail_stub_exchange_new:
  * @account: the #ExchangeAccount this stub is for
@@ -2640,8 +2718,10 @@ mail_stub_exchange_new (ExchangeAccount 
 	MailStub *stub;
 	const char *uri;
 	int mode;
+	ExchangeOfflineListener *listener;
 
 	stub = g_object_new (MAIL_TYPE_STUB_EXCHANGE, NULL);
+	g_object_ref (stub);
 	mail_stub_construct (stub, cmd_fd, status_fd);
 	exchange_component_is_offline (global_exchange_component, &mode);
 
@@ -2657,5 +2737,11 @@ mail_stub_exchange_new (ExchangeAccount 
 		uri = exchange_account_get_standard_uri (account, "deleteditems");
 		mse->deleted_items = exchange_account_get_folder (account, uri);
 	}
+	
+	listener = exchange_component_get_offline_listener (global_exchange_component);
+	g_signal_connect (G_OBJECT (listener), "linestatus-changed",
+			  G_CALLBACK (linestatus_listener), mse);
+
 	return stub;
 }
+
Index: mail/mail-stub.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/mail/mail-stub.c,v
retrieving revision 1.7
diff -u -p -r1.7 mail-stub.c
--- mail/mail-stub.c	28 Jun 2005 09:20:46 -0000	1.7
+++ mail/mail-stub.c	21 Jul 2005 11:12:39 -0000
@@ -86,10 +86,10 @@ connection_handler (GIOChannel *source, 
 	guint32 command;
 
 	if (condition == G_IO_ERR || condition == G_IO_HUP)
-		goto comm_fail;
+		return FALSE;
 
 	if (camel_stub_marshal_decode_uint32 (stub->cmd, &command) == -1)
-		goto comm_fail;
+		return FALSE;
 
 	switch (command) {
 	case CAMEL_STUB_CMD_CONNECT:
Index: shell/e-shell-marshal.list
===================================================================
RCS file: /cvs/gnome/evolution-exchange/shell/e-shell-marshal.list,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 e-shell-marshal.list
--- shell/e-shell-marshal.list	11 May 2004 15:15:58 -0000	1.1.1.1
+++ shell/e-shell-marshal.list	21 Jul 2005 11:12:39 -0000
@@ -5,3 +5,4 @@ NONE:BOXED,OBJECT
 NONE:STRING
 NONE:STRING,POINTER,POINTER
 NONE:STRING,STRING
+NONE:INT
Index: storage/exchange-component.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/storage/exchange-component.c,v
retrieving revision 1.10
diff -u -p -r1.10 exchange-component.c
--- storage/exchange-component.c	12 Jul 2005 06:32:21 -0000	1.10
+++ storage/exchange-component.c	21 Jul 2005 11:12:39 -0000
@@ -381,3 +381,10 @@ exchange_component_is_interactive (Excha
 {
 	return component->priv->xid != 0;
 }
+
+ExchangeOfflineListener *
+exchange_component_get_offline_listener (ExchangeComponent *component)
+{
+	return component->priv->offline_listener;
+}
+
Index: storage/exchange-component.h
===================================================================
RCS file: /cvs/gnome/evolution-exchange/storage/exchange-component.h,v
retrieving revision 1.7
diff -u -p -r1.7 exchange-component.h
--- storage/exchange-component.h	10 Jun 2005 11:35:34 -0000	1.7
+++ storage/exchange-component.h	21 Jul 2005 11:12:39 -0000
@@ -49,6 +49,8 @@ void           exchange_component_is_off
 void exchange_component_set_offline_listener (ExchangeComponent *component, 
 						ExchangeOfflineListener *listener);
 
+ExchangeOfflineListener *exchange_component_get_offline_listener (ExchangeComponent *component);
+
 #define EXCHANGE_COMPONENT_FACTORY_IID  "OAFIID:GNOME_Evolution_Exchange_Component_Factory:" BASE_VERSION
 #define EXCHANGE_COMPONENT_IID		"OAFIID:GNOME_Evolution_Exchange_Component:" BASE_VERSION
 #define EXCHANGE_CALENDAR_FACTORY_ID	"OAFIID:GNOME_Evolution_Exchange_Connector_CalFactory:" BASE_VERSION
Index: storage/exchange-offline-listener.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/storage/exchange-offline-listener.c,v
retrieving revision 1.8
diff -u -p -r1.8 exchange-offline-listener.c
--- storage/exchange-offline-listener.c	10 Jun 2005 11:35:34 -0000	1.8
+++ storage/exchange-offline-listener.c	21 Jul 2005 11:12:40 -0000
@@ -30,9 +30,12 @@
 #include <libedata-book/e-data-book-factory.h>
 #include <libedata-cal/e-data-cal-factory.h>
 #include <gconf/gconf-client.h>
+#include <e-shell-marshal.h>
 
 static GObjectClass *parent_class = NULL;
 
+static guint linestatus_signal_id;
+
 struct _ExchangeOfflineListenerPrivate 
 {
 	GConfClient *default_client;
@@ -75,6 +78,9 @@ online_status_changed (GConfClient *clie
 		offline = gconf_value_get_bool (value);
 	if (priv->offline != offline)
 		set_online_status (ex_offline_listener ,offline);
+
+	g_signal_emit (ex_offline_listener, linestatus_signal_id,
+		       0, offline ? OFFLINE_MODE : ONLINE_MODE);
 }
 
 static void 
@@ -170,7 +176,7 @@ exchange_offline_listener_init (Exchange
 }
 
 static void
-exchange_offline_listener_class_init (ExchangeOfflineListener *klass)
+exchange_offline_listener_class_init (ExchangeOfflineListenerClass *klass)
 {
 	GObjectClass *object_class;
 
@@ -179,6 +185,18 @@ exchange_offline_listener_class_init (Ex
 	object_class = G_OBJECT_CLASS (klass);
 	object_class->dispose = exchange_offline_listener_dispose;
 	object_class->finalize = exchange_offline_listener_finalize;
+
+	linestatus_signal_id = 
+		g_signal_new ("linestatus-changed",
+			       G_TYPE_FROM_CLASS (klass),
+			       G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+			       G_STRUCT_OFFSET (ExchangeOfflineListenerClass, linestatus_notify),
+			       NULL,
+			       NULL,
+			       e_shell_marshal_VOID__INT,
+			       G_TYPE_NONE,
+			       1,
+			       G_TYPE_INT);
 }
 
 GType
Index: storage/exchange-offline-listener.h
===================================================================
RCS file: /cvs/gnome/evolution-exchange/storage/exchange-offline-listener.h,v
retrieving revision 1.4
diff -u -p -r1.4 exchange-offline-listener.h
--- storage/exchange-offline-listener.h	10 Jun 2005 11:35:34 -0000	1.4
+++ storage/exchange-offline-listener.h	21 Jul 2005 11:12:40 -0000
@@ -59,6 +59,9 @@ struct _ExchangeOfflineListener {
 
 struct _ExchangeOfflineListenerClass {
 	GObjectClass  parent_class;
+
+	/* signal default handlers */
+	void (*linestatus_notify) (ExchangeOfflineListener *listener, guint status);
 };
 
 


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