[evolution-data-server/gnome-2-30] Bug 622719 - Fix lifetime issues with CamelIMAPXServer w.r.t. disconnection (cherry picked from comm



commit 51920efa6ea9a3c82a22827088c618207cd90e02
Author: David Woodhouse <David Woodhouse intel com>
Date:   Sat Jul 31 16:03:08 2010 +0200

    Bug 622719 - Fix lifetime issues with CamelIMAPXServer w.r.t. disconnection
    (cherry picked from commit 6e49273e99bfe8f5e1ed080a454d0e3aeacae4f8)
    
    Note contents of imapx_server_dispose() from HEAD have moved to
    imapx_server_finalize() in gnome-2-30 because CamelObjects don't have a
    separate dispose() method.

 camel/providers/imapx/camel-imapx-folder.c |   60 +++++++++----
 camel/providers/imapx/camel-imapx-server.c |   81 ++++++++++-------
 camel/providers/imapx/camel-imapx-server.h |    2 +-
 camel/providers/imapx/camel-imapx-store.c  |  132 ++++++++++++++++++++++------
 camel/providers/imapx/camel-imapx-store.h  |    1 +
 5 files changed, 197 insertions(+), 79 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c
index 3d9b0c0..bdd398d 100644
--- a/camel/providers/imapx/camel-imapx-folder.c
+++ b/camel/providers/imapx/camel-imapx-folder.c
@@ -129,25 +129,33 @@ static void
 imapx_refresh_info (CamelFolder *folder, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *)folder->parent_store;
+	CamelIMAPXServer *server;
 
 	if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return;
 
 	camel_service_connect((CamelService *)istore, ex);
-	if (istore->server && camel_imapx_server_connect (istore->server, TRUE, ex))
-		camel_imapx_server_refresh_info(istore->server, folder, ex);
+	server = camel_imapx_store_get_server(istore, ex);
+	if (server) {
+		camel_imapx_server_refresh_info(server, folder, ex);
+		camel_object_unref(server);
+	}
 }
 
 static void
 imapx_expunge (CamelFolder *folder, CamelException *ex)
 {
 	CamelIMAPXStore *is = (CamelIMAPXStore *)folder->parent_store;
+	CamelIMAPXServer *server;
 
 	if (CAMEL_OFFLINE_STORE (is)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return;
 
-	if (is->server && camel_imapx_server_connect (is->server, TRUE, ex))
-		camel_imapx_server_expunge(is->server, folder, ex);
+	server = camel_imapx_store_get_server(is, ex);
+	if (server) {
+		camel_imapx_server_expunge(server, folder, ex);
+		camel_object_unref(server);
+	}
 
 }
 
@@ -155,6 +163,7 @@ static void
 imapx_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
 {
 	CamelIMAPXStore *is = (CamelIMAPXStore *)folder->parent_store;
+	CamelIMAPXServer *server;
 	CamelException eex = CAMEL_EXCEPTION_INITIALISER;
 
 	if (CAMEL_OFFLINE_STORE (is)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
@@ -163,17 +172,20 @@ imapx_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
 	if (!ex)
 		ex = &eex;
 
-	if (is->server && camel_imapx_server_connect (is->server, TRUE, ex))
-		camel_imapx_server_sync_changes (is->server, folder, ex);
+	server = camel_imapx_store_get_server(is, ex);
+	if (server)
+		camel_imapx_server_sync_changes (server, folder, ex);
 
 	/* Sync twice - make sure deleted flags are written out,
 	   then sync again incase expunge changed anything */
 	camel_exception_clear(ex);
 
-	if (is->server && expunge) {
-		camel_imapx_server_expunge(is->server, folder, ex);
+	if (server && expunge) {
+		camel_imapx_server_expunge(server, folder, ex);
 		camel_exception_clear(ex);
 	}
+	if (server)
+		camel_object_unref(server);
 }
 
 static CamelMimeMessage *
@@ -183,6 +195,7 @@ imapx_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex)
 	CamelStream *stream = NULL;
 	CamelIMAPXStore *istore = (CamelIMAPXStore *)folder->parent_store;
 	CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) folder;
+	CamelIMAPXServer *server;
 	const gchar *path = NULL;
 	gboolean offline_message = FALSE;
 
@@ -203,9 +216,12 @@ imapx_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex)
 		if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 			return NULL;
 
-		if (istore->server && camel_imapx_server_connect (istore->server, TRUE, ex)) {
-			stream = camel_imapx_server_get_message(istore->server, folder, uid, ex);
+		server = camel_imapx_store_get_server(istore, ex);
+		if (server) {
+			stream = camel_imapx_server_get_message(server, folder, uid, ex);
+			camel_object_unref(server);
 		} else {
+			/* It should _always_ be set */
 			if (!camel_exception_is_set (ex))
 				camel_exception_setv(ex, 1, "not authenticated");
 			return NULL;
@@ -231,12 +247,16 @@ static void
 imapx_sync_message (CamelFolder *folder, const gchar *uid, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *)folder->parent_store;
+	CamelIMAPXServer *server;
 
 	if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return;
 
-	if (istore->server && camel_imapx_server_connect (istore->server, TRUE, ex))
-		camel_imapx_server_sync_message (istore->server, folder, uid, ex);
+	server = camel_imapx_store_get_server(istore, ex);
+	if (server) {
+		camel_imapx_server_sync_message (server, folder, uid, ex);
+		camel_object_unref(server);
+	}
 }
 
 static void
@@ -245,12 +265,16 @@ imapx_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
 		      gboolean delete_originals, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *) source->parent_store;
+	CamelIMAPXServer *server;
 
 	if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return;
 
-	if (istore->server && camel_imapx_server_connect (istore->server, TRUE, ex))
-		camel_imapx_server_copy_message (istore->server, source, dest, uids, delete_originals, ex);
+	server = camel_imapx_store_get_server(istore, ex);
+	if (server) {
+		camel_imapx_server_copy_message (server, source, dest, uids, delete_originals, ex);
+		camel_object_unref(server);
+	}
 
 	imapx_refresh_info (dest, ex);
 }
@@ -259,6 +283,7 @@ static void
 imapx_append_message(CamelFolder *folder, CamelMimeMessage *message, const CamelMessageInfo *info, gchar **appended_uid, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *)folder->parent_store;
+	CamelIMAPXServer *server;
 
 	if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return;
@@ -266,8 +291,11 @@ imapx_append_message(CamelFolder *folder, CamelMimeMessage *message, const Camel
 	if (appended_uid)
 		*appended_uid = NULL;
 
-	if (istore->server && camel_imapx_server_connect (istore->server, TRUE, ex))
-		camel_imapx_server_append_message(istore->server, folder, message, info, ex);
+	server = camel_imapx_store_get_server(istore, ex);
+	if (server) {
+		camel_imapx_server_append_message(server, folder, message, info, ex);
+		camel_object_unref(server);
+	}
 }
 
 gchar *
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 70f3cea..fd87c67 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -170,6 +170,7 @@ static gboolean imapx_is_command_queue_empty (CamelIMAPXServer *is);
 /* states for the connection? */
 enum {
 	IMAPX_DISCONNECTED,
+	IMAPX_SHUTDOWN,
 	IMAPX_CONNECTED,
 	IMAPX_AUTHENTICATED,
 	IMAPX_INITIALISED,
@@ -1013,6 +1014,15 @@ imapx_command_queue(CamelIMAPXServer *is, CamelIMAPXCommand *ic)
 
 	QUEUE_LOCK(is);
 
+	if (is->state == IMAPX_SHUTDOWN) {
+		c(printf("refuse to queue job on disconnected server\n"));
+		camel_exception_set(ic->ex, 1, "Server disconnected");
+		QUEUE_UNLOCK(is);
+		if (ic->complete)
+			ic->complete(is, ic);
+		return;
+	}
+
 	scan = (CamelIMAPXCommand *)is->queue.head;
 	if (scan->next == NULL)
 		camel_dlist_addtail(&is->queue, (CamelDListNode *)ic);
@@ -1530,7 +1540,8 @@ imapx_untagged(CamelIMAPXServer *imap, CamelException *ex)
 			c(printf("BYE: %s\n", token));
 			camel_exception_setv(ex, 1, "IMAP server said BYE: %s", token);
 		}
-		break;
+		imap->state = IMAPX_SHUTDOWN;
+		return -1;
 	}
 	case IMAPX_PREAUTH:
 		c(printf("preauthenticated\n"));
@@ -4301,7 +4312,7 @@ imapx_parser_thread (gpointer d)
 				errno = EINTR;
 		}
 
-		if (camel_application_is_exiting || is->parser_quit) {
+		if (is->parser_quit) {
 			camel_exception_setv (&ex, CAMEL_EXCEPTION_USER_CANCEL, "Operation Cancelled: %s", g_strerror(errno));
 			break;
 		}
@@ -4320,11 +4331,11 @@ imapx_parser_thread (gpointer d)
 		}
 	}
 
-	imapx_disconnect (is);
-	cancel_all_jobs (is, &ex);
+	QUEUE_LOCK(is);
+	is->state = IMAPX_SHUTDOWN;
+	QUEUE_UNLOCK(is);
 
-	if (imapx_idle_supported (is))
-		imapx_exit_idle (is);
+	cancel_all_jobs (is, &ex);
 
 	camel_exception_clear (&ex);
 
@@ -4378,11 +4389,29 @@ imapx_server_init(CamelIMAPXServer *is, CamelIMAPXServerClass *isclass)
 static void
 imapx_server_finalise(CamelIMAPXServer *is, CamelIMAPXServerClass *isclass)
 {
+	e(printf("imapx_server_finalise\n"));
+
+	QUEUE_LOCK(is);
+	is->state = IMAPX_SHUTDOWN;
+	QUEUE_UNLOCK(is);
+
+	is->parser_quit = TRUE;
+	camel_operation_cancel (is->op);
+
+	if (is->parser_thread)
+		g_thread_join (is->parser_thread);
+
+	if (imapx_idle_supported (is))
+		imapx_exit_idle (is);
+
+	imapx_disconnect (is);
+
 	g_static_rec_mutex_free(&is->queue_lock);
 	g_static_rec_mutex_free (&is->ostream_lock);
 	g_hash_table_destroy (is->uid_eflags);
 
 	camel_folder_change_info_free (is->changes);
+
 }
 
 CamelType
@@ -4463,39 +4492,23 @@ imapx_disconnect (CamelIMAPXServer *is)
 
 /* Client commands */
 gboolean
-camel_imapx_server_connect (CamelIMAPXServer *is, gboolean connect, CamelException *ex)
+camel_imapx_server_connect (CamelIMAPXServer *is, CamelException *ex)
 {
-	gboolean ret = FALSE;
-
-	CAMEL_SERVICE_REC_LOCK (is->store, connect_lock);
-	if (connect) {
-		if (is->state >= IMAPX_INITIALISED) {
-			ret = TRUE;
-			goto exit;
-		}
+	if (is->state == IMAPX_SHUTDOWN)
+		return FALSE;
 
-		g_static_rec_mutex_lock (&is->ostream_lock);
-		imapx_reconnect (is, ex);
-		g_static_rec_mutex_unlock (&is->ostream_lock);
+	if (is->state >= IMAPX_INITIALISED)
+		return TRUE;
 
-		if (camel_exception_is_set (ex)) {
-			ret = FALSE;
-			goto exit;
-		}
+	g_static_rec_mutex_lock (&is->ostream_lock);
+	imapx_reconnect (is, ex);
+	g_static_rec_mutex_unlock (&is->ostream_lock);
 
-		is->parser_thread = g_thread_create((GThreadFunc) imapx_parser_thread, is, TRUE, NULL);
-		ret = TRUE;
-	} else {
-		is->parser_quit = TRUE;
-		camel_operation_cancel (is->op);
-		if (is->parser_thread)
-			g_thread_join (is->parser_thread);
-		ret = TRUE;
-	}
+	if (camel_exception_is_set (ex))
+		return FALSE;
 
-exit:
-	CAMEL_SERVICE_REC_UNLOCK (is->store, connect_lock);
-	return ret;
+	is->parser_thread = g_thread_create((GThreadFunc) imapx_parser_thread, is, TRUE, NULL);
+	return TRUE;
 }
 
 static CamelStream *
diff --git a/camel/providers/imapx/camel-imapx-server.h b/camel/providers/imapx/camel-imapx-server.h
index 502769d..e72a245 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -116,7 +116,7 @@ struct _CamelIMAPXServerClass {
 CamelType               camel_imapx_server_get_type     (void);
 CamelIMAPXServer *camel_imapx_server_new(struct _CamelStore *store, struct _CamelURL *url);
 
-gboolean camel_imapx_server_connect(CamelIMAPXServer *is, gint state, CamelException *ex);
+gboolean camel_imapx_server_connect(CamelIMAPXServer *is, CamelException *ex);
 gboolean imapx_connect_to_server (CamelIMAPXServer *is, CamelException *ex);
 
 GPtrArray *camel_imapx_server_list(CamelIMAPXServer *is, const gchar *top, guint32 flags, const gchar *ext, CamelException *ex);
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index 5d12bd2..90b4780 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -204,16 +204,48 @@ imapx_get_name (CamelService *service, gboolean brief)
 					service->url->user, service->url->host);
 }
 
+CamelIMAPXServer *
+camel_imapx_store_get_server(CamelIMAPXStore *store, CamelException *ex)
+{
+	CamelIMAPXServer *server = NULL;
+
+	CAMEL_SERVICE_REC_LOCK (store, connect_lock);
+
+	if (store->server && camel_imapx_server_connect(store->server, ex)) {
+		camel_object_ref(store->server);
+		server = store->server;
+	} else {
+		if (store->server) {
+			camel_object_unref(store->server);
+			store->server = NULL;
+		}
+
+		server = camel_imapx_server_new(CAMEL_STORE(store), CAMEL_SERVICE(store)->url);
+		if (camel_imapx_server_connect(server, ex)) {
+			store->server = server;
+			camel_object_ref(server);
+		} else {
+			camel_object_unref(server);
+			server = NULL;
+		}
+	}
+	CAMEL_SERVICE_REC_UNLOCK (store, connect_lock);
+	return server;
+}
+
 static gboolean
 imapx_connect (CamelService *service, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *)service;
+	CamelIMAPXServer *server;
 
-	/* We never really are 'connected' or 'disconnected' */
-	if (istore->server == NULL)
-		istore->server = camel_imapx_server_new((CamelStore *)istore, service->url);
+	server = camel_imapx_store_get_server(istore, ex);
+	if (server) {
+		camel_object_unref(server);
+		return TRUE;
+	}
 
-	return camel_imapx_server_connect (istore->server, TRUE, ex);
+	return FALSE;
 }
 
 static gboolean
@@ -223,8 +255,14 @@ imapx_disconnect (CamelService *service, gboolean clean, CamelException *ex)
 
 	CAMEL_SERVICE_CLASS (parent_class)->disconnect (service, clean, ex);
 
-	if (istore->server)
-		camel_imapx_server_connect(istore->server, FALSE, ex);
+	CAMEL_SERVICE_REC_LOCK (service, connect_lock);
+
+	if (istore->server) {
+		camel_object_unref(istore->server);
+		istore->server = NULL;
+	}
+
+	CAMEL_SERVICE_REC_UNLOCK (service, connect_lock);
 
 	return TRUE;
 }
@@ -267,12 +305,16 @@ static void
 imapx_noop (CamelStore *store, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
+	CamelIMAPXServer *server;
 
 	if (CAMEL_OFFLINE_STORE(store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return;
 
-	if (istore->server && camel_imapx_server_connect (istore->server, TRUE, ex))
-		camel_imapx_server_noop (istore->server, NULL, ex);
+	server = camel_imapx_store_get_server(istore, ex);
+	if (server) {
+		camel_imapx_server_noop (server, NULL, ex);
+		camel_object_unref(server);
+	}
 }
 
 static guint
@@ -528,12 +570,17 @@ static void
 imapx_subscribe_folder (CamelStore *store, const gchar *folder_name, gboolean emit_signal, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
+	CamelIMAPXServer *server;
 
 	if (CAMEL_OFFLINE_STORE(store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return;
 
-	if (istore->server && camel_imapx_server_connect (istore->server, TRUE, ex))
-		camel_imapx_server_manage_subscription (istore->server, folder_name, TRUE, ex);
+	server = camel_imapx_store_get_server(istore, ex);
+	if (!server)
+		return;
+
+	camel_imapx_server_manage_subscription (server, folder_name, TRUE, ex);
+	camel_object_unref(server);
 
 	if (!camel_exception_is_set (ex))
 		imapx_mark_folder_subscribed (istore, folder_name, emit_signal, ex);
@@ -543,12 +590,17 @@ static void
 imapx_unsubscribe_folder (CamelStore *store, const gchar *folder_name, gboolean emit_signal, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
+	CamelIMAPXServer *server;
 
 	if (CAMEL_OFFLINE_STORE(store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return;
 
-	if (istore->server && camel_imapx_server_connect (istore->server, TRUE, ex))
-		camel_imapx_server_manage_subscription (istore->server, folder_name, FALSE, ex);
+	server = camel_imapx_store_get_server(istore, ex);
+	if (!server)
+		return;
+
+	camel_imapx_server_manage_subscription (server, folder_name, FALSE, ex);
+	camel_object_unref(server);
 
 	if (!camel_exception_is_set (ex))
 		imapx_unmark_folder_subscribed (istore, folder_name, emit_signal, ex);
@@ -614,15 +666,19 @@ static void
 imapx_delete_folder (CamelStore *store, const gchar *folder_name, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
+	CamelIMAPXServer *server;
 
 	if (CAMEL_OFFLINE_STORE (store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
 		camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
 				     _("You must be working online to complete this operation"));
 		return;
 	}
+	server = camel_imapx_store_get_server(istore, ex);
+	if (!server)
+		return;
 
-	if (istore->server && camel_imapx_server_connect (istore->server, TRUE, ex))
-		camel_imapx_server_delete_folder (istore->server, folder_name, ex);
+	camel_imapx_server_delete_folder (server, folder_name, ex);
+	camel_object_unref(server);
 
 	if (!camel_exception_is_set (ex))
 		imapx_delete_folder_from_cache (istore, folder_name, ex);
@@ -665,6 +721,7 @@ static void
 imapx_rename_folder (CamelStore *store, const gchar *old, const gchar *new, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
+	CamelIMAPXServer *server;
 	gchar *oldpath, *newpath, *storage_path;
 
 	if (CAMEL_OFFLINE_STORE (store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
@@ -676,8 +733,11 @@ imapx_rename_folder (CamelStore *store, const gchar *old, const gchar *new, Came
 	if (istore->rec_options & IMAPX_SUBSCRIPTIONS)
 		imapx_unsubscribe_folder (store, old, FALSE, ex);
 
-	if (istore->server && camel_imapx_server_connect (istore->server, TRUE, ex))
-		camel_imapx_server_rename_folder (istore->server, old, new, ex);
+	server = camel_imapx_store_get_server(istore, ex);
+	if (server) {
+		camel_imapx_server_rename_folder (server, old, new, ex);
+		camel_object_unref(server);
+	}
 
 	if (camel_exception_is_set (ex)) {
 		imapx_subscribe_folder (store, old, FALSE, ex);
@@ -711,6 +771,7 @@ imapx_create_folder (CamelStore *store, const gchar *parent_name, const gchar *f
 	CamelStoreInfo *si;
 	CamelIMAPXStoreNamespace *ns;
 	CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
+	CamelIMAPXServer *server;
 	gchar *real_name, *full_name, *parent_real;
 	CamelFolderInfo *fi = NULL;
 	gchar dir_sep;
@@ -721,7 +782,8 @@ imapx_create_folder (CamelStore *store, const gchar *parent_name, const gchar *f
 		return NULL;
 	}
 
-	if (!(istore->server && camel_imapx_server_connect (istore->server, TRUE, ex)))
+	server = camel_imapx_store_get_server(istore, ex);
+	if (!server)
 		return NULL;
 
 	if (!parent_name)
@@ -737,6 +799,7 @@ imapx_create_folder (CamelStore *store, const gchar *parent_name, const gchar *f
 		camel_exception_setv (ex, CAMEL_EXCEPTION_FOLDER_INVALID_PATH,
 				      _("The folder name \"%s\" is invalid because it contains the character \"%c\""),
 				      folder_name, dir_sep);
+		camel_object_unref(server);
 		return NULL;
 	}
 
@@ -744,6 +807,7 @@ imapx_create_folder (CamelStore *store, const gchar *parent_name, const gchar *f
 	if (parent_real == NULL) {
 		camel_exception_setv(ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE,
 				     _("Unknown parent folder: %s"), parent_name);
+		camel_object_unref(server);
 		return NULL;
 	}
 
@@ -751,6 +815,7 @@ imapx_create_folder (CamelStore *store, const gchar *parent_name, const gchar *f
 	if (si && si->flags & CAMEL_STORE_INFO_FOLDER_NOINFERIORS) {
 		camel_exception_set (ex, CAMEL_EXCEPTION_FOLDER_INVALID_STATE,
 				_("The parent folder is not allowed to contain subfolders"));
+		camel_object_unref(server);
 		return NULL;
 	}
 
@@ -761,7 +826,8 @@ imapx_create_folder (CamelStore *store, const gchar *parent_name, const gchar *f
 	full_name = imapx_concat (istore, parent_real, real_name);
 	g_free(real_name);
 
-	camel_imapx_server_create_folder (istore->server, full_name, ex);
+	camel_imapx_server_create_folder (server, full_name, ex);
+	camel_object_unref(server);
 
 	if (!camel_exception_is_set (ex)) {
 		CamelIMAPXStoreInfo *si;
@@ -886,7 +952,7 @@ get_folder_info_offline (CamelStore *store, const gchar *top,
 }
 
 static void
-add_folders_to_summary (CamelIMAPXStore *istore, GPtrArray *folders, GHashTable *table, gboolean subscribed)
+add_folders_to_summary (CamelIMAPXStore *istore, CamelIMAPXServer *server, GPtrArray *folders, GHashTable *table, gboolean subscribed)
 {
 	gint i = 0;
 
@@ -909,8 +975,10 @@ add_folders_to_summary (CamelIMAPXStore *istore, GPtrArray *folders, GHashTable
 		}
 
 		si = camel_imapx_store_summary_add_from_full (istore->summary, li->name, li->separator);
-		if (!si)
+		if (!si) {
+			camel_object_unref(server);
 			continue;
+		}
 
 		new_flags = (si->info.flags & (CAMEL_STORE_INFO_FOLDER_SUBSCRIBED | CAMEL_STORE_INFO_FOLDER_CHECK_FOR_NEW)) |
 						(li->flags & ~CAMEL_STORE_INFO_FOLDER_SUBSCRIBED);
@@ -969,15 +1037,16 @@ imapx_get_folders_free(gpointer k, gpointer v, gpointer d)
 }
 
 static void
-fetch_folders_for_pattern (CamelIMAPXStore *istore, const gchar *pattern, guint32 flags, const gchar *ext, GHashTable *table, CamelException *ex)
+fetch_folders_for_pattern (CamelIMAPXStore *istore, CamelIMAPXServer *server, const gchar *pattern, guint32 flags,
+			   const gchar *ext, GHashTable *table, CamelException *ex)
 {
 	GPtrArray *folders = NULL;
 
-	folders = camel_imapx_server_list (istore->server, pattern, flags, ext, ex);
+	folders = camel_imapx_server_list (server, pattern, flags, ext, ex);
 	if (camel_exception_is_set (ex))
 		return;
 
-	add_folders_to_summary (istore, folders, table, (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED));
+	add_folders_to_summary (istore, server, folders, table, (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED));
 
 	g_ptr_array_foreach (folders, free_list, folders);
 	g_ptr_array_free (folders, TRUE);
@@ -1004,9 +1073,14 @@ get_namespaces (CamelIMAPXStore *istore)
 static GHashTable *
 fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, gboolean sync, CamelException *ex)
 {
+	CamelIMAPXServer *server;
 	GHashTable *folders = NULL;
 	GSList *namespaces = NULL, *l;
 
+	server = camel_imapx_store_get_server(istore, ex);
+	if (!server)
+		return NULL;
+
 	folders = g_hash_table_new (folder_hash, folder_eq);
 	namespaces = get_namespaces (istore);
 
@@ -1030,11 +1104,11 @@ fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, gbo
 			if (sync)
 				flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST;
 
-			if (istore->server->cinfo->capa & IMAPX_CAPABILITY_LIST_EXTENDED)
+			if (server->cinfo->capa & IMAPX_CAPABILITY_LIST_EXTENDED)
 				list_ext = "RETURN (SUBSCRIBED)";
 
 			flags |= CAMEL_STORE_FOLDER_INFO_RECURSIVE;
-			fetch_folders_for_pattern (istore, pat, flags, list_ext, folders, ex);
+			fetch_folders_for_pattern (istore, server, pat, flags, list_ext, folders, ex);
 			if (camel_exception_is_set (ex)) {
 				g_free (pat);
 				goto exception;
@@ -1043,7 +1117,7 @@ fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, gbo
 				/* If the server doesn't support LIST-EXTENDED then we have to
 				   issue LSUB to list the subscribed folders separately */
 				flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
-				fetch_folders_for_pattern (istore, pat, flags, NULL, folders, ex);
+				fetch_folders_for_pattern (istore, server, pat, flags, NULL, folders, ex);
 				if (camel_exception_is_set (ex)) {
 					g_free (pat);
 					goto exception;
@@ -1052,15 +1126,17 @@ fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, gbo
 			g_free (pat);
 
 			if (pattern)
-				return folders;
+				goto out;
 
 			ns = ns->next;
 		}
 	}
-
+ out:
+	camel_object_unref(server);
 	return folders;
 
 exception:
+	camel_object_unref(server);
 	g_hash_table_destroy (folders);
 	return NULL;
 }
diff --git a/camel/providers/imapx/camel-imapx-store.h b/camel/providers/imapx/camel-imapx-store.h
index fa08ab9..3cb1227 100644
--- a/camel/providers/imapx/camel-imapx-store.h
+++ b/camel/providers/imapx/camel-imapx-store.h
@@ -79,6 +79,7 @@ typedef struct {
 
 /* Standard Camel function */
 CamelType camel_imapx_store_get_type (void);
+struct _CamelIMAPXServer *camel_imapx_store_get_server(CamelIMAPXStore *store, CamelException *ex);
 
 #ifdef __cplusplus
 }



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