[evolution-data-server] Bug 622719 - Fix lifetime issues with CamelIMAPXServer w.r.t. disconnection



commit 6e49273e99bfe8f5e1ed080a454d0e3aeacae4f8
Author: David Woodhouse <David Woodhouse intel com>
Date:   Sat Jun 26 14:47:25 2010 +0100

    Bug 622719 - Fix lifetime issues with CamelIMAPXServer w.r.t. disconnection

 camel/providers/imapx/camel-imapx-folder.c |   61 +++++++++----
 camel/providers/imapx/camel-imapx-server.c |   87 +++++++++++-------
 camel/providers/imapx/camel-imapx-server.h |    1 -
 camel/providers/imapx/camel-imapx-store.c  |  137 +++++++++++++++++++++-------
 camel/providers/imapx/camel-imapx-store.h  |    1 +
 5 files changed, 202 insertions(+), 85 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-folder.c b/camel/providers/imapx/camel-imapx-folder.c
index 5b32cdc..53c647e 100644
--- a/camel/providers/imapx/camel-imapx-folder.c
+++ b/camel/providers/imapx/camel-imapx-folder.c
@@ -152,6 +152,7 @@ imapx_refresh_info (CamelFolder *folder, CamelException *ex)
 {
 	CamelStore *parent_store;
 	CamelIMAPXStore *istore;
+	CamelIMAPXServer *server;
 
 	parent_store = camel_folder_get_parent_store (folder);
 	istore = CAMEL_IMAPX_STORE (parent_store);
@@ -160,8 +161,11 @@ imapx_refresh_info (CamelFolder *folder, CamelException *ex)
 		return TRUE;
 
 	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);
+		g_object_unref(server);
+	}
 
 	return !camel_exception_is_set (ex);
 }
@@ -171,6 +175,7 @@ imapx_expunge (CamelFolder *folder, CamelException *ex)
 {
 	CamelStore *parent_store;
 	CamelIMAPXStore *is;
+	CamelIMAPXServer *server;
 
 	parent_store = camel_folder_get_parent_store (folder);
 	is = CAMEL_IMAPX_STORE (parent_store);
@@ -178,8 +183,11 @@ imapx_expunge (CamelFolder *folder, CamelException *ex)
 	if (CAMEL_OFFLINE_STORE (is)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return TRUE;
 
-	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);
+		g_object_unref(server);
+	}
 
 	return !camel_exception_is_set (ex);
 }
@@ -189,6 +197,7 @@ imapx_sync (CamelFolder *folder, gboolean expunge, CamelException *ex)
 {
 	CamelStore *parent_store;
 	CamelIMAPXStore *is;
+	CamelIMAPXServer *server;
 	CamelException eex = CAMEL_EXCEPTION_INITIALISER;
 
 	parent_store = camel_folder_get_parent_store (folder);
@@ -200,17 +209,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)
+		g_object_unref(server);
 
 	return !camel_exception_is_set (ex);
 }
@@ -223,6 +235,7 @@ imapx_get_message (CamelFolder *folder, const gchar *uid, CamelException *ex)
 	CamelStore *parent_store;
 	CamelIMAPXStore *istore;
 	CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) folder;
+	CamelIMAPXServer *server;
 	const gchar *path = NULL;
 	gboolean offline_message = FALSE;
 
@@ -246,9 +259,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);
+			g_object_unref(server);
 		} else {
+			/* It should _always_ be set */
 			if (!camel_exception_is_set (ex))
 				camel_exception_setv(ex, 1, "not authenticated");
 			return NULL;
@@ -275,6 +291,7 @@ imapx_sync_message (CamelFolder *folder, const gchar *uid, CamelException *ex)
 {
 	CamelStore *parent_store;
 	CamelIMAPXStore *istore;
+	CamelIMAPXServer *server;
 
 	parent_store = camel_folder_get_parent_store (folder);
 	istore = CAMEL_IMAPX_STORE (parent_store);
@@ -282,9 +299,11 @@ imapx_sync_message (CamelFolder *folder, const gchar *uid, CamelException *ex)
 	if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return TRUE;
 
-	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);
+		g_object_unref(server);
+	}
 	return !camel_exception_is_set (ex);
 }
 
@@ -295,6 +314,7 @@ imapx_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
 {
 	CamelStore *parent_store;
 	CamelIMAPXStore *istore;
+	CamelIMAPXServer *server;
 
 	parent_store = camel_folder_get_parent_store (source);
 	istore = CAMEL_IMAPX_STORE (parent_store);
@@ -302,8 +322,11 @@ imapx_transfer_messages_to (CamelFolder *source, GPtrArray *uids,
 	if (CAMEL_OFFLINE_STORE (istore)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return TRUE;
 
-	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);
+		g_object_unref(server);
+	}
 
 	imapx_refresh_info (dest, ex);
 
@@ -315,6 +338,7 @@ imapx_append_message(CamelFolder *folder, CamelMimeMessage *message, const Camel
 {
 	CamelStore *parent_store;
 	CamelIMAPXStore *istore;
+	CamelIMAPXServer *server;
 
 	parent_store = camel_folder_get_parent_store (folder);
 	istore = CAMEL_IMAPX_STORE (parent_store);
@@ -325,8 +349,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);
+		g_object_unref(server);
+	}
 
 	return !camel_exception_is_set (ex);
 }
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 060825e..c17c5c8 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -148,6 +148,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,
@@ -1002,6 +1003,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);
@@ -1527,7 +1537,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"));
@@ -4368,7 +4379,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;
 		}
@@ -4387,11 +4398,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);
 
@@ -4435,6 +4446,29 @@ imapx_server_constructed (GObject *object)
 	if (class->tagprefix > 'Z')
 		class->tagprefix = 'A';
 }
+static void
+imapx_server_dispose (GObject *object)
+{
+	CamelIMAPXServer *server = CAMEL_IMAPX_SERVER (object);
+
+	QUEUE_LOCK(server);
+	server->state = IMAPX_SHUTDOWN;
+	QUEUE_UNLOCK(server);
+
+	server->parser_quit = TRUE;
+	camel_operation_cancel (server->op);
+
+	if (server->parser_thread)
+		g_thread_join (server->parser_thread);
+
+	if (imapx_idle_supported (server))
+		imapx_exit_idle (server);
+
+	imapx_disconnect (server);
+
+	/* Chain up to parent's dispose() method. */
+	G_OBJECT_CLASS (camel_imapx_server_parent_class)->dispose (object);
+}
 
 static void
 camel_imapx_server_class_init(CamelIMAPXServerClass *class)
@@ -4444,6 +4478,7 @@ camel_imapx_server_class_init(CamelIMAPXServerClass *class)
 	object_class = G_OBJECT_CLASS (class);
 	object_class->finalize = imapx_server_finalize;
 	object_class->constructed = imapx_server_constructed;
+	object_class->dispose = imapx_server_dispose;
 
 	class->tagprefix = 'A';
 }
@@ -4529,39 +4564,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_lock (CAMEL_SERVICE (is->store), CAMEL_SERVICE_REC_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_unlock (CAMEL_SERVICE (is->store), CAMEL_SERVICE_REC_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 0f63d94..82e82ad 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -135,7 +135,6 @@ CamelIMAPXServer *
 		camel_imapx_server_new		(CamelStore *store,
 						 CamelURL *url);
 gboolean	camel_imapx_server_connect	(CamelIMAPXServer *is,
-						 gint state,
 						 CamelException *ex);
 gboolean	imapx_connect_to_server		(CamelIMAPXServer *is,
 						 CamelException *ex);
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index af619b5..ba5fff8 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -209,16 +209,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_lock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_CONNECT_LOCK);
+
+	if (store->server && camel_imapx_server_connect(store->server, ex)) {
+		g_object_ref(store->server);
+		server = store->server;
+	} else {
+		if (store->server) {
+			g_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;
+			g_object_ref(server);
+		} else {
+			g_object_unref(server);
+			server = NULL;
+		}
+	}
+	camel_service_unlock (CAMEL_SERVICE (store), CAMEL_SERVICE_REC_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) {
+		g_object_unref(server);
+		return TRUE;
+	}
 
-	return camel_imapx_server_connect (istore->server, TRUE, ex);
+	return FALSE;
 }
 
 static gboolean
@@ -230,8 +262,14 @@ imapx_disconnect (CamelService *service, gboolean clean, CamelException *ex)
 	service_class = CAMEL_SERVICE_CLASS (camel_imapx_store_parent_class);
 	service_class->disconnect (service, clean, ex);
 
-	if (istore->server)
-		camel_imapx_server_connect(istore->server, FALSE, ex);
+	camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
+
+	if (istore->server) {
+		g_object_unref(istore->server);
+		istore->server = NULL;
+	}
+
+	camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
 
 	return TRUE;
 }
@@ -284,17 +322,16 @@ static gboolean
 imapx_noop (CamelStore *store, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *) store;
+	CamelIMAPXServer *server;
 
 	if (CAMEL_OFFLINE_STORE(store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL)
 		return TRUE;
 
-	if (istore->server) {
-		if (!camel_imapx_server_connect (istore->server, TRUE, ex))
-			return FALSE;
-
-		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);
+		g_object_unref(server);
 	}
-
 	return TRUE;
 }
 
@@ -551,12 +588,17 @@ static gboolean
 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 TRUE;
 
-	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 FALSE;
+
+	camel_imapx_server_manage_subscription (server, folder_name, TRUE, ex);
+	g_object_unref(server);
 
 	if (!camel_exception_is_set (ex)) {
 		imapx_mark_folder_subscribed (istore, folder_name, emit_signal, ex);
@@ -570,12 +612,17 @@ static gboolean
 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 TRUE;
 
-	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 FALSE;
+
+	camel_imapx_server_manage_subscription (server, folder_name, FALSE, ex);
+	g_object_unref(server);
 
 	if (!camel_exception_is_set (ex)) {
 		imapx_unmark_folder_subscribed (istore, folder_name, emit_signal, ex);
@@ -645,15 +692,19 @@ static gboolean
 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 FALSE;
 	}
+	server = camel_imapx_store_get_server(istore, ex);
+	if (!server)
+		return FALSE;
 
-	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);
+	g_object_unref(server);
 
 	if (!camel_exception_is_set (ex)) {
 		imapx_delete_folder_from_cache (istore, folder_name, ex);
@@ -700,6 +751,7 @@ static gboolean
 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) {
@@ -711,8 +763,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);
+		g_object_unref(server);
+	}
 
 	if (camel_exception_is_set (ex)) {
 		imapx_subscribe_folder (store, old, FALSE, ex);
@@ -748,6 +803,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;
@@ -758,7 +814,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)
@@ -774,6 +831,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);
+		g_object_unref(server);
 		return NULL;
 	}
 
@@ -781,6 +839,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);
+		g_object_unref(server);
 		return NULL;
 	}
 
@@ -788,6 +847,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"));
+		g_object_unref(server);
 		return NULL;
 	}
 
@@ -798,7 +858,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);
+	g_object_unref(server);
 
 	if (!camel_exception_is_set (ex)) {
 		CamelIMAPXStoreInfo *si;
@@ -923,7 +984,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;
 
@@ -946,13 +1007,15 @@ 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) {
+			g_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);
 
-		if (!(istore->server->cinfo->capa & IMAPX_CAPABILITY_NAMESPACE))
+		if (!(server->cinfo->capa & IMAPX_CAPABILITY_NAMESPACE))
 			istore->dir_sep = li->separator;
 
 		if (si->info.flags != new_flags) {
@@ -1006,15 +1069,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);
@@ -1041,9 +1105,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);
 
@@ -1067,11 +1136,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;
@@ -1080,7 +1149,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;
@@ -1089,15 +1158,17 @@ fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, gbo
 			g_free (pat);
 
 			if (pattern)
-				return folders;
+				goto out;
 
 			ns = ns->next;
 		}
 	}
-
+ out:
+	g_object_unref(server);
 	return folders;
 
 exception:
+	g_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 77f39c9..8ae1ffe 100644
--- a/camel/providers/imapx/camel-imapx-store.h
+++ b/camel/providers/imapx/camel-imapx-store.h
@@ -91,6 +91,7 @@ struct _CamelIMAPXStoreClass {
 };
 
 GType		camel_imapx_store_get_type (void);
+CamelIMAPXServer *camel_imapx_store_get_server(CamelIMAPXStore *store, CamelException *ex);
 
 G_END_DECLS
 



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