[evolution-patches] Exchange, offline-online and other fixes.



Hi,

Attached patch fixes,

* Not entering offline mode problem. (#313637)
* Deleting items in public folder. (#272751)
* Deleting/moving/copying test* folders. (#310726, #310437)
* Folder creation problem. (#313071)
* Offline crash while starting Evolution. (#313797)

Please review it.

Thanks,
Arunprakash.

Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-exchange/ChangeLog,v
retrieving revision 1.379
diff -u -p -r1.379 ChangeLog
--- ChangeLog	18 Aug 2005 04:31:54 -0000	1.379
+++ ChangeLog	18 Aug 2005 09:30:44 -0000
@@ -1,3 +1,34 @@
+2005-08-17  Arunprakash  <arunp novell com>
+
+	* camel/camel-exchange-store.c (camel_exchange_store_connected) :
+	Newly added to ensure that we are connected when the camel session
+	is too online.
+	* camel/camel-exchange-folder.c : Updated to make use of the new 
+	function camel_exchange_store_connected.
+	(camel_exchange_folder_update_message_flags_ex) : Newly added to
+	selectively set and unset message flags.
+	* camel/camel-exchange-store.c : Updated to use 
+	camel_exchange_store_connected.
+	(exchange_folder_subscribed) (exchange_subscribe_folder)
+	(exchange_unsubscribe_folder) : Changed the type of data for folder
+	name from string to folder type while sending to backend. Because the
+	other side expects folder type.
+	(stub_notification) : Modified to include new retval for setting and
+	unsetting specific flags.
+	* mail/mail-stub-exchange.c (folder_from_name) : Try using create
+	permission for shared folders.
+	(get_folder_online) : Newly added by removing the online code from
+	get_folder.
+	(get_folder) : Updated to use get_folder_online. Also set the readonly
+	flag only if it fails for modify and create permissions.
+	(expunge_uids) : Report the error in case of failure.
+	(process_flags) : Do an expunge for mails in non-personal folders.
+	If fails, undo the delete.
+	(get_folder_info) : Ensure the top is exactly equal to the path. Also
+	added some extra checks.
+	(folder_update_linestatus) : Updated to use get_folder_online.
+	Fixes #313637, #272751, #310726, #310437, #313797, #313071.
+
 2005-08-17  Not Zed  <NotZed Ximian com>
 
 	** See bug #312668.
Index: camel/camel-exchange-folder.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-folder.c,v
retrieving revision 1.18
diff -u -p -r1.18 camel-exchange-folder.c
--- camel/camel-exchange-folder.c	25 Jul 2005 11:03:16 -0000	1.18
+++ camel/camel-exchange-folder.c	18 Aug 2005 09:30:45 -0000
@@ -197,9 +197,9 @@ static void
 refresh_info (CamelFolder *folder, CamelException *ex)
 {
 	CamelExchangeFolder *exch = CAMEL_EXCHANGE_FOLDER (folder);
-	CamelOfflineStore *store = CAMEL_OFFLINE_STORE (folder->parent_store);
+	CamelExchangeStore *store = CAMEL_EXCHANGE_STORE (folder->parent_store);
 
-	if (store->state != CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+	if (camel_exchange_store_connected (store, ex)) {
 		camel_offline_journal_replay (exch->journal, NULL);
 	
 		camel_stub_send (exch->stub, ex, CAMEL_STUB_CMD_REFRESH_FOLDER,
@@ -276,9 +276,9 @@ append_message (CamelFolder *folder, Cam
 		CamelException *ex)
 {
 	CamelStream *stream_mem;
-	CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store;
+	CamelExchangeStore *store = CAMEL_EXCHANGE_STORE (folder->parent_store);
 
-	if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+	if (!camel_exchange_store_connected (store, ex)) {
 		camel_exchange_journal_append ((CamelExchangeJournal *) ((CamelExchangeFolder *)folder)->journal, message, info, appended_uid, ex);
 		return;
 	}
@@ -352,7 +352,7 @@ static GByteArray *
 get_message_data (CamelFolder *folder, const char *uid, CamelException *ex)
 {
 	CamelExchangeFolder *exch = CAMEL_EXCHANGE_FOLDER (folder);
-	CamelOfflineStore *offline = (CamelOfflineStore *) folder->parent_store;
+	CamelExchangeStore *store = CAMEL_EXCHANGE_STORE (folder->parent_store);
 	CamelStream *stream, *stream_mem;
 	GByteArray *ba;
 
@@ -369,7 +369,7 @@ get_message_data (CamelFolder *folder, c
 		return ba;
 	}
 
-	if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+	if (!camel_exchange_store_connected (store, ex)) {
 		camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
                                      _("This message is not available in offline mode."));
 		return NULL;
@@ -555,7 +555,7 @@ transfer_messages_the_hard_way (CamelFol
 	}
 
 	if (delete_originals) {
-		camel_stub_send (exch_source->stub, NULL,
+		camel_stub_send (exch_source->stub, ex,
 				 CAMEL_STUB_CMD_EXPUNGE_UIDS,
 				 CAMEL_STUB_ARG_FOLDER, source->full_name,
 				 CAMEL_STUB_ARG_STRINGARRAY, uids,
@@ -601,7 +601,7 @@ transfer_messages_to (CamelFolder *sourc
 {
 	CamelExchangeFolder *exch_source = CAMEL_EXCHANGE_FOLDER (source);
 	CamelExchangeFolder *exch_dest = CAMEL_EXCHANGE_FOLDER (dest);
-	CamelOfflineStore *offline = (CamelOfflineStore *) source->parent_store;
+	CamelExchangeStore *store = CAMEL_EXCHANGE_STORE (source->parent_store);
 	CamelMessageInfo *info;
 	GPtrArray *ret_uids = NULL;
 	int hier_len, i;
@@ -610,7 +610,7 @@ transfer_messages_to (CamelFolder *sourc
 			       _("Copying messages"));
 
 	/* Check for offline operation */
-	if (offline->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+	if (!camel_exchange_store_connected (store, ex)) {
 		CamelExchangeJournal *journal = (CamelExchangeJournal *) exch_dest->journal;
 		CamelMimeMessage *message;
 		
@@ -854,6 +854,47 @@ camel_exchange_folder_update_message_fla
 
 	if (info->flags != flags) {
 		info->flags = flags;
+		camel_folder_summary_touch (folder->summary);
+
+		changes = camel_folder_change_info_new ();
+		camel_folder_change_info_change_uid (changes, uid);
+		camel_object_trigger_event (CAMEL_OBJECT (exch),
+					    "folder_changed", changes);
+		camel_folder_change_info_free (changes);
+	}
+}
+
+/**
+ * camel_exchange_folder_update_message_flags_ex:
+ * @exch: the folder
+ * @uid: the message
+ * @flags: new message flags
+ * @mask: the flag mask
+ *
+ * Update the message flags of @uid in @exch's summary based on @flags and @mask.
+ * Only the bits in the mask %CAMEL_EXCHANGE_SERVER_FLAGS are valid to be set or unset.
+ **/
+void
+camel_exchange_folder_update_message_flags_ex (CamelExchangeFolder *exch,
+					       const char *uid, guint32 flags,
+					       guint32 mask)
+{
+	CamelFolder *folder = CAMEL_FOLDER (exch);
+	CamelMessageInfoBase *info;
+	CamelFolderChangeInfo *changes;
+
+	info = (CamelMessageInfoBase *)camel_folder_summary_uid (folder->summary, uid);
+	if (!info)
+		return;
+
+	mask &= CAMEL_EXCHANGE_SERVER_FLAGS;
+	if (!mask) {
+		return;
+	}
+	
+	if ((info->flags & mask) != (flags & mask)) {
+		info->flags &= ~mask;
+		info->flags |= (flags & mask);
 		camel_folder_summary_touch (folder->summary);
 
 		changes = camel_folder_change_info_new ();
Index: camel/camel-exchange-folder.h
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-folder.h,v
retrieving revision 1.7
diff -u -p -r1.7 camel-exchange-folder.h
--- camel/camel-exchange-folder.h	26 Feb 2005 14:19:15 -0000	1.7
+++ camel/camel-exchange-folder.h	18 Aug 2005 09:30:45 -0000
@@ -70,6 +70,11 @@ void     camel_exchange_folder_update_me
 						     const char *uid,
 						     guint32 flags);
 
+void     camel_exchange_folder_update_message_flags_ex (CamelExchangeFolder *exch,
+							const char *uid,
+							guint32 flags,
+							guint32 mask);
+
 void     camel_exchange_folder_update_message_tag   (CamelExchangeFolder *exch,
 						     const char *uid,
 						     const char *name,
Index: camel/camel-exchange-store.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-store.c,v
retrieving revision 1.21
diff -u -p -r1.21 camel-exchange-store.c
--- camel/camel-exchange-store.c	6 Aug 2005 11:36:50 -0000	1.21
+++ camel/camel-exchange-store.c	18 Aug 2005 09:30:46 -0000
@@ -158,6 +158,28 @@ camel_exchange_store_get_type (void)
 	return camel_exchange_store_type;
 }
 
+/* Use this to ensure that the camel session is online and we are connected
+   too. Also returns the current status of the store */
+gboolean
+camel_exchange_store_connected (CamelExchangeStore *store, CamelException *ex)
+{
+	CamelService *service;
+	CamelSession *session;
+
+	g_return_val_if_fail (CAMEL_IS_EXCHANGE_STORE (store), FALSE);
+
+	service = CAMEL_SERVICE (store);
+	session = service->session;
+
+	if (service->status != CAMEL_SERVICE_CONNECTED &&
+	    camel_session_is_online (session) &&
+	    !camel_service_connect (service, ex)) {
+		return FALSE;
+	}
+
+	return CAMEL_OFFLINE_STORE (store)->state != CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL;
+}
+
 /* This has been now removed from evolution/e-util. So implemented this here.
  * Also note that this is similar to the call in e2k-path.c. The name of the 
  * function has been changed to avoid any conflicts.
@@ -359,8 +381,11 @@ exchange_disconnect (CamelService *servi
 	return TRUE;
 }
 
-#define RETURN_VAL_IF_NOT_CONNECTED(service, ex, val)\
-	if (!exchange_connect((CamelService *)service, ex))\
+/* Even if we are disconnected, we need to exchange_connect
+   to get the offline data */
+#define RETURN_VAL_IF_NOT_CONNECTED(store, ex, val)\
+	if (!camel_exchange_store_connected(store, ex) && \
+	    !exchange_connect (CAMEL_SERVICE (store), ex)) \
 		return val; 
 
 static CamelFolder *
@@ -371,11 +396,11 @@ exchange_get_folder (CamelStore *store, 
 	CamelFolder *folder;
 	char *folder_dir;
 	
-	RETURN_VAL_IF_NOT_CONNECTED(store, ex, NULL);
+	RETURN_VAL_IF_NOT_CONNECTED (exch, ex, NULL);
 
 	folder_dir = exchange_path_to_physical (exch->storage_path, folder_name);
 	
-	if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+	if (!camel_exchange_store_connected (exch, ex)) {
 		if (!folder_dir || access (folder_dir, F_OK) != 0) {
 			g_free (folder_dir);
 			camel_exception_setv (ex, CAMEL_EXCEPTION_STORE_NO_FOLDER,
@@ -430,7 +455,7 @@ exchange_folder_subscribed (CamelStore *
 	}
 
 	if (!camel_stub_send (exch->stub, NULL, CAMEL_STUB_CMD_IS_SUBSCRIBED_FOLDER,
-			      CAMEL_STUB_ARG_STRING, folder_name,
+			      CAMEL_STUB_ARG_FOLDER, folder_name,
 			      CAMEL_STUB_ARG_RETURN,
 			      CAMEL_STUB_ARG_UINT32, &is_subscribed,
 			      CAMEL_STUB_ARG_END)) {
@@ -447,13 +472,13 @@ exchange_subscribe_folder (CamelStore *s
 	d(printf ("subscribe folder : %s\n", folder_name));
 	CamelExchangeStore *exch = CAMEL_EXCHANGE_STORE (store);
 	
-	if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+	if (!camel_exchange_store_connected (exch, ex)) {
 		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot subscribe folder in offline mode."));
 		return;
 	}
 
 	camel_stub_send (exch->stub, ex, CAMEL_STUB_CMD_SUBSCRIBE_FOLDER,
-			      CAMEL_STUB_ARG_STRING, folder_name,
+			      CAMEL_STUB_ARG_FOLDER, folder_name,
 			      CAMEL_STUB_ARG_END);
 }
 
@@ -464,13 +489,13 @@ exchange_unsubscribe_folder (CamelStore 
 	d(printf ("unsubscribe folder : %s\n", folder_name));
 	CamelExchangeStore *exch = CAMEL_EXCHANGE_STORE (store);
 	
-	if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+	if (!camel_exchange_store_connected (exch, ex)) {
 		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot unsubscribe folder in offline mode."));
 		return;
 	}
 
 	camel_stub_send (exch->stub, ex, CAMEL_STUB_CMD_UNSUBSCRIBE_FOLDER,
-			      CAMEL_STUB_ARG_STRING, folder_name,
+			      CAMEL_STUB_ARG_FOLDER, folder_name,
 			      CAMEL_STUB_ARG_END);
 }
 
@@ -480,7 +505,7 @@ get_trash (CamelStore *store, CamelExcep
 {
 	CamelExchangeStore *exch = CAMEL_EXCHANGE_STORE (store);
 	
-	RETURN_VAL_IF_NOT_CONNECTED(store, ex, NULL);
+	RETURN_VAL_IF_NOT_CONNECTED (exch, ex, NULL);
 
 	if (!exch->trash_name) {
 		if (!camel_stub_send (exch->stub, ex, CAMEL_STUB_CMD_GET_TRASH_NAME,
@@ -579,7 +604,7 @@ exchange_get_folder_info (CamelStore *st
 	 * each time auto-send/recv runs.
 	 */
 
-	RETURN_VAL_IF_NOT_CONNECTED(store, ex, NULL);
+	RETURN_VAL_IF_NOT_CONNECTED (exch, ex, NULL);
 
 	if (camel_stub_marshal_eof (exch->stub->cmd))
 		return NULL;
@@ -640,7 +665,7 @@ exchange_create_folder (CamelStore *stor
 	guint32 unread_count, flags;
 	CamelFolderInfo *info;
 	
-	if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+	if (!camel_exchange_store_connected (exch, ex)) {
 		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create folder in offline mode."));
 		return NULL;
 	}
@@ -667,7 +692,7 @@ exchange_delete_folder (CamelStore *stor
 {
 	CamelExchangeStore *exch = CAMEL_EXCHANGE_STORE (store);
 
-	if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+	if (!camel_exchange_store_connected (exch, ex)) {
 		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot delete folder in offline mode."));
 		return;
 	}
@@ -683,7 +708,7 @@ exchange_rename_folder (CamelStore *stor
 {
 	CamelExchangeStore *exch = CAMEL_EXCHANGE_STORE (store);
 
-	if (((CamelOfflineStore *) store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+	if (!camel_exchange_store_connected (exch, ex)) {
 		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot rename folder in offline mode."));
 		return;
 	}
@@ -788,6 +813,31 @@ stub_notification (CamelObject *object, 
 		g_mutex_unlock (exch->folders_lock);
 		if (folder)
 			camel_exchange_folder_update_message_flags (folder, uid, flags);
+
+		g_free (folder_name);
+		g_free (uid);
+		break;
+	}
+
+	case CAMEL_STUB_RETVAL_CHANGED_FLAGS_EX:
+	{
+		CamelExchangeFolder *folder;
+		char *folder_name, *uid;
+		guint32 flags;
+		guint32 mask;
+
+		if (camel_stub_marshal_decode_folder (stub->status, &folder_name) == -1 ||
+		    camel_stub_marshal_decode_string (stub->status, &uid) == -1 ||
+		    camel_stub_marshal_decode_uint32 (stub->status, &flags) == -1 ||
+		    camel_stub_marshal_decode_uint32 (stub->status, &mask) == -1)
+			break;
+
+		g_mutex_lock (exch->folders_lock);
+		folder = g_hash_table_lookup (exch->folders, folder_name);
+		g_mutex_unlock (exch->folders_lock);
+		if (folder)
+			camel_exchange_folder_update_message_flags_ex (folder, uid,
+								       flags, mask);
 
 		g_free (folder_name);
 		g_free (uid);
Index: camel/camel-exchange-store.h
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-exchange-store.h,v
retrieving revision 1.3
diff -u -p -r1.3 camel-exchange-store.h
--- camel/camel-exchange-store.h	11 Jan 2005 07:06:01 -0000	1.3
+++ camel/camel-exchange-store.h	18 Aug 2005 09:30:46 -0000
@@ -42,6 +42,8 @@ typedef struct {
 /* Standard Camel function */
 CamelType camel_exchange_store_get_type (void);
 
+gboolean camel_exchange_store_connected (CamelExchangeStore *store, CamelException *ex);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
Index: camel/camel-stub-constants.h
===================================================================
RCS file: /cvs/gnome/evolution-exchange/camel/camel-stub-constants.h,v
retrieving revision 1.5
diff -u -p -r1.5 camel-stub-constants.h
--- camel/camel-stub-constants.h	28 Jun 2005 09:20:46 -0000	1.5
+++ camel/camel-stub-constants.h	18 Aug 2005 09:30:46 -0000
@@ -55,6 +55,10 @@ typedef enum {
 	CAMEL_STUB_RETVAL_REMOVED_MESSAGE,
 	CAMEL_STUB_RETVAL_CHANGED_MESSAGE,
 	CAMEL_STUB_RETVAL_CHANGED_FLAGS,
+
+	/* This is used to undelete a message for which the operation failed.
+	   But can also be used to specifically set or unset a flag. */
+	CAMEL_STUB_RETVAL_CHANGED_FLAGS_EX,
 	CAMEL_STUB_RETVAL_CHANGED_TAG,
 	CAMEL_STUB_RETVAL_PROGRESS,
 	CAMEL_STUB_RETVAL_FREEZE_FOLDER,
Index: mail/mail-stub-exchange.c
===================================================================
RCS file: /cvs/gnome/evolution-exchange/mail/mail-stub-exchange.c,v
retrieving revision 1.23
diff -u -p -r1.23 mail-stub-exchange.c
--- mail/mail-stub-exchange.c	6 Aug 2005 11:36:50 -0000	1.23
+++ mail/mail-stub-exchange.c	18 Aug 2005 09:30:48 -0000
@@ -133,6 +133,7 @@ static void linestatus_listener (Exchang
 						    gpointer data);
 static void folder_update_linestatus (gpointer key, gpointer value, gpointer data);
 static void free_folder (gpointer value);
+static void get_folder_online (MailStubExchangeFolder *mfld, gboolean background);
 
 static void
 class_init (GObjectClass *object_class)
@@ -267,6 +268,12 @@ folder_from_name (MailStubExchange *mse,
 		sync_deletions (mse, mfld);
 	}
 
+	if ((perms == MAPI_ACCESS_MODIFY || perms == MAPI_ACCESS_DELETE) &&
+	    !(mfld->access & perms)) {
+		/* try with MAPI_ACCESS_CREATE_CONTENTS */
+		perms = MAPI_ACCESS_CREATE_CONTENTS;
+	}
+
 	if (perms && !(mfld->access & perms)) {
 		if (!background)
 			mail_stub_return_error (MAIL_STUB (mse), _("Permission denied"));
@@ -544,15 +551,10 @@ static const char *open_folder_props[] =
 static const int n_open_folder_props = sizeof (open_folder_props) / sizeof (open_folder_props[0]);
 
 static void
-get_folder (MailStub *stub, const char *name, gboolean create,
-	    GPtrArray *uids, GByteArray *flags)
+get_folder_online (MailStubExchangeFolder *mfld, gboolean background)
 {
-	MailStubExchange *mse = MAIL_STUB_EXCHANGE (stub);
-	MailStubExchangeFolder *mfld;
 	MailStubExchangeMessage *mmsg;
-	EFolder *folder;
-	char *path;
-	const char *outlook_class;
+	MailStub *stub = MAIL_STUB (mfld->mse);
 	E2kHTTPStatus status;
 	E2kResult *results;
 	int nresults;
@@ -562,7 +564,177 @@ get_folder (MailStub *stub, const char *
 	E2kResult *result;
 	const char *prop, *uid;
 	guint32 article_num, camel_flags;
-	int i, m, total = -1, mode;
+	int i, m, total = -1;
+
+	mfld->changed_messages = g_ptr_array_new ();
+
+	status = e_folder_exchange_propfind (mfld->folder, NULL,
+					     open_folder_props,
+					     n_open_folder_props,
+					     &results, &nresults);
+	if (status == E2K_HTTP_UNAUTHORIZED) {
+		if (!background) {
+			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);
+		if (!background) {
+			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)) {
+		if (!background) {
+			got_folder_error (mfld, _("Could not open folder: Permission denied"));
+		}
+		return;
+	}
+	readonly = (mfld->access & (MAPI_ACCESS_MODIFY | MAPI_ACCESS_CREATE_CONTENTS)) == 0;
+
+	prop = e2k_properties_get_prop (results[0].props, PR_DELETED_COUNT_TOTAL);
+	if (prop)
+		mfld->deleted_count = atoi (prop);
+
+	rn = e2k_restriction_andv (
+		e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
+					   E2K_RELOP_EQ, FALSE),
+		e2k_restriction_prop_bool (E2K_PR_DAV_IS_HIDDEN,
+					   E2K_RELOP_EQ, FALSE),
+		NULL);
+
+	iter = e_folder_exchange_search_start (mfld->folder, NULL,
+					       open_folder_sync_props,
+					       n_open_folder_sync_props,
+					       rn, E2K_PR_DAV_CREATION_DATE,
+					       TRUE);
+	e2k_restriction_unref (rn);
+
+	m = 0;
+	total = e2k_result_iter_get_total (iter);
+	while ((result = e2k_result_iter_next (iter)) && m < mfld->messages->len) {
+		prop = e2k_properties_get_prop (result->props,
+						PR_INTERNET_ARTICLE_NUMBER);
+		if (!prop)
+			continue;
+		article_num = strtoul (prop, NULL, 10);
+
+		prop = e2k_properties_get_prop (result->props,
+						E2K_PR_REPL_UID);
+		if (!prop)
+			continue;
+		uid = uidstrip (prop);
+
+		camel_flags = mail_util_props_to_camel_flags (result->props,
+							      !readonly);
+
+		mmsg = mfld->messages->pdata[m];
+		while (strcmp (uid, mmsg->uid)) {
+			message_remove_at_index (stub, mfld, m);
+			if (m == mfld->messages->len) {
+				mmsg = NULL;
+				if (article_num < mfld->high_article_num)
+					mfld->high_article_num = article_num - 1;
+				break;
+			}
+			mmsg = mfld->messages->pdata[m];
+		}
+		if (!mmsg)
+			break;
+
+		mmsg->href = g_strdup (result->href);
+		g_hash_table_insert (mfld->messages_by_href, mmsg->href, mmsg);
+		if (article_num > mfld->high_article_num)
+			mfld->high_article_num = article_num;
+		if (mmsg->flags != camel_flags)
+			change_flags (mfld, mmsg, camel_flags);
+
+		prop = e2k_properties_get_prop (result->props, E2K_PR_HTTPMAIL_MESSAGE_FLAG);
+		if (prop)
+			return_tag (mfld, mmsg->uid, "follow-up", prop);
+		prop = e2k_properties_get_prop (result->props, E2K_PR_MAILHEADER_REPLY_BY);
+		if (prop)
+			return_tag (mfld, mmsg->uid, "due-by", prop);
+		prop = e2k_properties_get_prop (result->props, E2K_PR_MAILHEADER_COMPLETED);
+		if (prop)
+			return_tag (mfld, mmsg->uid, "completed-on", prop);
+
+		m++;
+		if (!background) {
+			mail_stub_return_progress (stub, (m * 100) / total);
+		}
+	}
+
+	/* If there are further messages beyond mfld->messages->len,
+	 * then that means camel doesn't know about them yet, and so
+	 * we need to ignore them for a while. But if any of them have
+	 * an article number lower than the highest article number
+	 * we've seen, bump high_article_num down so that that message
+	 * gets caught by refresh_info later too.
+	 */
+	while ((result = e2k_result_iter_next (iter))) {
+		prop = e2k_properties_get_prop (result->props,
+						PR_INTERNET_ARTICLE_NUMBER);
+		if (prop) {
+			article_num = strtoul (prop, NULL, 10);
+			if (article_num < mfld->high_article_num)
+				mfld->high_article_num = article_num - 1;
+		}
+
+		m++;
+		if (!background) {
+			mail_stub_return_progress (stub, (m * 100) / total);
+		}
+	}
+
+	status = e2k_result_iter_free (iter);
+	if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
+		g_warning ("got_folder: %d", status);
+		if (!background) {
+			got_folder_error (mfld, _("Could not open folder"));
+		}
+		return;
+	}
+
+	/* Discard remaining messages that no longer exist. */
+	for (i = 0; i < mfld->messages->len; i++) {
+		mmsg = mfld->messages->pdata[i];
+		if (!mmsg->href)
+			message_remove_at_index (stub, mfld, i--);
+	}
+	e_folder_exchange_subscribe (mfld->folder,
+				     E2K_CONTEXT_OBJECT_ADDED, 30,
+				     notify_cb, mfld);
+	e_folder_exchange_subscribe (mfld->folder,
+				     E2K_CONTEXT_OBJECT_REMOVED, 30,
+				     notify_cb, mfld);
+	e_folder_exchange_subscribe (mfld->folder,
+				     E2K_CONTEXT_OBJECT_MOVED, 30,
+				     notify_cb, mfld);
+}
+
+static void
+get_folder (MailStub *stub, const char *name, gboolean create,
+	    GPtrArray *uids, GByteArray *flags)
+{
+	MailStubExchange *mse = MAIL_STUB_EXCHANGE (stub);
+	MailStubExchangeFolder *mfld;
+	MailStubExchangeMessage *mmsg;
+	EFolder *folder;
+	char *path;
+	const char *outlook_class;
+	guint32 camel_flags;
+	int i, mode;
 	ExchangeHierarchy *hier;
 
 	path = g_strdup_printf ("/%s", name);
@@ -618,150 +790,8 @@ get_folder (MailStub *stub, const char *
 	}
 	exchange_component_is_offline (global_exchange_component, &mode);
 	if (mode == ONLINE_MODE) {
-		mfld->changed_messages = g_ptr_array_new ();
-
-		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;
-		}
-		readonly = (mfld->access & MAPI_ACCESS_MODIFY) == 0;
-
-		prop = e2k_properties_get_prop (results[0].props, PR_DELETED_COUNT_TOTAL);
-		if (prop)
-			mfld->deleted_count = atoi (prop);
-
-		rn = e2k_restriction_andv (
-			e2k_restriction_prop_bool (E2K_PR_DAV_IS_COLLECTION,
-						   E2K_RELOP_EQ, FALSE),
-			e2k_restriction_prop_bool (E2K_PR_DAV_IS_HIDDEN,
-						   E2K_RELOP_EQ, FALSE),
-			NULL);
-
-		iter = e_folder_exchange_search_start (mfld->folder, NULL,
-						       open_folder_sync_props,
-						       n_open_folder_sync_props,
-						       rn, E2K_PR_DAV_CREATION_DATE,
-						       TRUE);
-		e2k_restriction_unref (rn);
-
-		m = 0;
-		total = e2k_result_iter_get_total (iter);
-		while ((result = e2k_result_iter_next (iter)) && m < mfld->messages->len) {
-			prop = e2k_properties_get_prop (result->props,
-							PR_INTERNET_ARTICLE_NUMBER);
-			if (!prop)
-				continue;
-			article_num = strtoul (prop, NULL, 10);
-
-			prop = e2k_properties_get_prop (result->props,
-							E2K_PR_REPL_UID);
-			if (!prop)
-				continue;
-			uid = uidstrip (prop);
-
-			camel_flags = mail_util_props_to_camel_flags (result->props,
-								      !readonly);
-
-			mmsg = mfld->messages->pdata[m];
-			while (strcmp (uid, mmsg->uid)) {
-				message_remove_at_index (stub, mfld, m);
-				if (m == mfld->messages->len) {
-					mmsg = NULL;
-					if (article_num < mfld->high_article_num)
-						mfld->high_article_num = article_num - 1;
-					break;
-				}
-				mmsg = mfld->messages->pdata[m];
-			}
-			if (!mmsg)
-				break;
-
-			mmsg->href = g_strdup (result->href);
-			g_hash_table_insert (mfld->messages_by_href, mmsg->href, mmsg);
-			if (article_num > mfld->high_article_num)
-				mfld->high_article_num = article_num;
-			if (mmsg->flags != camel_flags)
-				change_flags (mfld, mmsg, camel_flags);
-
-			prop = e2k_properties_get_prop (result->props, E2K_PR_HTTPMAIL_MESSAGE_FLAG);
-			if (prop)
-				return_tag (mfld, mmsg->uid, "follow-up", prop);
-			prop = e2k_properties_get_prop (result->props, E2K_PR_MAILHEADER_REPLY_BY);
-			if (prop)
-				return_tag (mfld, mmsg->uid, "due-by", prop);
-			prop = e2k_properties_get_prop (result->props, E2K_PR_MAILHEADER_COMPLETED);
-			if (prop)
-				return_tag (mfld, mmsg->uid, "completed-on", prop);
-
-			m++;
-			mail_stub_return_progress (stub, (m * 100) / total);
-		}
-
-		/* If there are further messages beyond mfld->messages->len,
-		 * then that means camel doesn't know about them yet, and so
-		 * we need to ignore them for a while. But if any of them have
-		 * an article number lower than the highest article number
-		 * we've seen, bump high_article_num down so that that message
-		 * gets caught by refresh_info later too.
-		 */
-		while ((result = e2k_result_iter_next (iter))) {
-			prop = e2k_properties_get_prop (result->props,
-							PR_INTERNET_ARTICLE_NUMBER);
-			if (prop) {
-				article_num = strtoul (prop, NULL, 10);
-				if (article_num < mfld->high_article_num)
-					mfld->high_article_num = article_num - 1;
-			}
-
-			m++;
-			mail_stub_return_progress (stub, (m * 100) / total);
-		}
-
-		status = e2k_result_iter_free (iter);
-		if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
-			g_warning ("got_folder: %d", status);
-			got_folder_error (mfld, _("Could not open folder"));
-			return;
-		}
-
-		/* Discard remaining messages that no longer exist. */
-		for (i = 0; i < mfld->messages->len; i++) {
-			mmsg = mfld->messages->pdata[i];
-			if (!mmsg->href)
-				message_remove_at_index (stub, mfld, i--);
-		}
-	e_folder_exchange_subscribe (mfld->folder,
-				     E2K_CONTEXT_OBJECT_ADDED, 30,
-				     notify_cb, mfld);
-	e_folder_exchange_subscribe (mfld->folder,
-				     E2K_CONTEXT_OBJECT_REMOVED, 30,
-				     notify_cb, mfld);
-	e_folder_exchange_subscribe (mfld->folder,
-				     E2K_CONTEXT_OBJECT_MOVED, 30,
-				     notify_cb, mfld);
-	} // end online work
+		get_folder_online (mfld, FALSE);
+	}
 	g_signal_connect (mfld->folder, "changed",
 			  G_CALLBACK (storage_folder_changed), mfld);
 
@@ -769,7 +799,7 @@ get_folder (MailStub *stub, const char *
 	folder_changed (mfld);
 
 	camel_flags = 0;
-	if ((mfld->access & MAPI_ACCESS_MODIFY) == 0)
+	if ((mfld->access & (MAPI_ACCESS_MODIFY | MAPI_ACCESS_CREATE_CONTENTS)) == 0)
 		camel_flags |= CAMEL_STUB_FOLDER_READONLY;
 	if (mse->account->filter_inbox && (mfld->folder == mse->inbox))
 		camel_flags |= CAMEL_STUB_FOLDER_FILTER;
@@ -1283,6 +1313,7 @@ expunge_uids (MailStub *stub, const char
 	E2kResult *result;
 	E2kHTTPStatus status;
 	int i, ndeleted;
+	gboolean some_error = FALSE;
 
 	if (!uids->len) {
 		mail_stub_return_ok (stub);
@@ -1318,6 +1349,10 @@ expunge_uids (MailStub *stub, const char
 						hrefs->len);
 	ndeleted = 0;
 	while ((result = e2k_result_iter_next (iter))) {
+		if (result->status == E2K_HTTP_UNAUTHORIZED) {
+			some_error = TRUE;
+			continue;
+		}
 		message_removed (stub, mfld, result->href);
 		mfld->deleted_count++;
 		ndeleted++;
@@ -1333,8 +1368,13 @@ expunge_uids (MailStub *stub, const char
 	if (!E2K_HTTP_STATUS_IS_SUCCESSFUL (status)) {
 		g_warning ("expunged: %d", status);
 		mail_stub_return_error (stub, _("Could not empty Deleted Items folder"));
-	} else
+	} else if (some_error) {
+		/* FIXME: should be this, but string freeze freezes me to do so.
+		mail_stub_return_error (stub, _("Permission denied. Could not delete certain mails.")); */
+		mail_stub_return_error (stub, _("Permission denied"));
+	} else {
 		mail_stub_return_ok (stub);
+	}
 
 	g_ptr_array_free (hrefs, TRUE);
 }
@@ -1558,6 +1598,7 @@ process_flags (gpointer user_data)
 	MailStubExchangeMessage *mmsg;
 	GPtrArray *seen = NULL, *unseen = NULL, *deleted = NULL;
 	int i;
+	guint32 hier_type = e_folder_exchange_get_hierarchy (mfld->folder)->type;
 
 	for (i = 0; i < mfld->changed_messages->len; i++) {
 		mmsg = mfld->changed_messages->pdata[i];
@@ -1633,13 +1674,32 @@ process_flags (gpointer user_data)
 				       CAMEL_STUB_ARG_FOLDER, mfld->name,
 				       CAMEL_STUB_ARG_END);
 
-		iter = e_folder_exchange_transfer_start (mfld->folder, NULL,
-							 mse->deleted_items,
-							 deleted, TRUE);
-		g_ptr_array_free (deleted, TRUE);
+		if (hier_type == EXCHANGE_HIERARCHY_PERSONAL) {
+			iter = e_folder_exchange_transfer_start (mfld->folder, NULL,
+								 mse->deleted_items,
+								 deleted, TRUE);
+		} else {
+			iter = e_folder_exchange_bdelete_start (mfld->folder, NULL,
+								(const char **)deleted->pdata,
+								deleted->len);
+		}
+		g_ptr_array_free (deleted, FALSE);
 		while ((result = e2k_result_iter_next (iter))) {
-			if (!e2k_properties_get_prop (result->props, E2K_PR_DAV_LOCATION))
+			if (hier_type == EXCHANGE_HIERARCHY_PERSONAL) {
+				if (!e2k_properties_get_prop (result->props,
+							      E2K_PR_DAV_LOCATION)) {
+					continue;
+				}
+			} else if (result->status == E2K_HTTP_UNAUTHORIZED) {
+				mail_stub_return_data (MAIL_STUB (mfld->mse),
+						       CAMEL_STUB_RETVAL_CHANGED_FLAGS_EX,
+						       CAMEL_STUB_ARG_FOLDER, mfld->name,
+						       CAMEL_STUB_ARG_STRING, mmsg->uid,
+						       CAMEL_STUB_ARG_UINT32, 0,
+						       CAMEL_STUB_ARG_UINT32, MAIL_STUB_MESSAGE_DELETED,
+						       CAMEL_STUB_ARG_END);
 				continue;
+			}
 
 			message_removed (stub, mfld, result->href);
 			mfld->deleted_count++;
@@ -1719,6 +1779,12 @@ set_message_flags (MailStub *stub, const
 	 * hierarchy, we ignore it (which will cause camel to delete
 	 * it the hard way next time it syncs).
 	 */
+
+#if 0
+	/* If we allow camel stub to delete these messages hard way, it may
+	   fail to delete a mail because of permissions, but will append
+	   a mail in deleted items */
+	
 	if (mask & flags & MAIL_STUB_MESSAGE_DELETED) {
 		ExchangeHierarchy *hier;
 
@@ -1726,6 +1792,7 @@ set_message_flags (MailStub *stub, const
 		if (hier->type != EXCHANGE_HIERARCHY_PERSONAL)
 			mask &= ~MAIL_STUB_MESSAGE_DELETED;
 	}
+#endif
 
 	/* If there's nothing left to change, return. */
 	if (!mask)
@@ -2184,7 +2251,7 @@ get_folder_info (MailStub *stub, const c
 	GArray *unread, *flags;	
 	ExchangeHierarchy *hier;
 	EFolder *folder;
-	const char *type, *name, *uri, *path, *inbox_uri;
+	const char *type, *name, *uri, *path, *inbox_uri = NULL;
 	int unread_count, i, toplen = top ? strlen (top) : 0;
 	guint32 folder_flags;
 	gboolean recursive, subscribed, single_folder = FALSE;
@@ -2221,7 +2288,10 @@ get_folder_info (MailStub *stub, const c
 	uris = g_ptr_array_new ();
 	unread = g_array_new (FALSE, FALSE, sizeof (int));
 	flags = g_array_new (FALSE, FALSE, sizeof (int));
-	inbox_uri = e_folder_get_physical_uri (mse->inbox);
+	/* Can be NULL if started in offline mode */
+	if (mse->inbox) {
+		inbox_uri = e_folder_get_physical_uri (mse->inbox);
+	}
 
 	if (folders) {
 		for (i = 0; i < folders->len; i++) {
@@ -2245,7 +2315,8 @@ get_folder_info (MailStub *stub, const c
 
 			if (recursive && toplen) {
 				path = e_folder_exchange_get_path (folder);
-				if (strncmp (path + 1, top, toplen) != 0)
+				if (strncmp (path + 1, top, toplen) != 0 ||
+				    path[toplen + 1] != '\0')
 					continue;
 			}
 return_data:
@@ -2288,7 +2359,7 @@ return_data:
 					break;
 			}
 
-			if (!strcmp (uri, inbox_uri))
+			if (inbox_uri && !strcmp (uri, inbox_uri))
 				folder_flags |= CAMEL_STUB_FOLDER_SYSTEM|CAMEL_STUB_FOLDER_TYPE_INBOX;
 
 			g_ptr_array_add (names, (char *)name);
@@ -2715,44 +2786,10 @@ 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);
+		get_folder_online (mfld, TRUE);
 	}
 	else {
 		/* FIXME: need any undo for offline */ ;


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