[evolution-data-server] Fetches the folderinfo from multiple namespaces - imapx.



commit 02f2bbd4e6caed34f439e53ba9558c5103ea4968
Author: Chenthill Palanisamy <pchenthill novell com>
Date:   Tue Nov 24 20:37:30 2009 +0530

    Fetches the folderinfo from multiple namespaces - imapx.

 camel/camel-msgport.h                      |    2 +
 camel/camel-tcp-stream-ssl.c               |    6 +
 camel/camel-tcp-stream-ssl.h               |    3 +
 camel/providers/imapx/camel-imapx-server.c |   75 +++++--
 camel/providers/imapx/camel-imapx-server.h |    2 +-
 camel/providers/imapx/camel-imapx-store.c  |  308 ++++++++++++++++++++++++----
 camel/providers/imapx/camel-imapx-store.h  |    5 +-
 camel/providers/imapx/camel-imapx-utils.c  |   14 +-
 8 files changed, 348 insertions(+), 67 deletions(-)
---
diff --git a/camel/camel-msgport.h b/camel/camel-msgport.h
index da89c73..30f1891 100644
--- a/camel/camel-msgport.h
+++ b/camel/camel-msgport.h
@@ -22,6 +22,7 @@
 #define CAMEL_MSGPORT_H
 
 #include <glib.h>
+#include "camel-list-utils.h"
 
 G_BEGIN_DECLS
 
@@ -29,6 +30,7 @@ typedef struct _CamelMsg CamelMsg;
 typedef struct _CamelMsgPort CamelMsgPort;
 
 struct _CamelMsg {
+	CamelDListNode ln;
 	CamelMsgPort *reply_port;
 	gint flags;
 };
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index e2af703..dfe126d 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -1312,4 +1312,10 @@ stream_get_remote_address (CamelTcpStream *stream, socklen_t *len)
 	return sockaddr_from_praddr(&addr, len);
 }
 
+PRFileDesc *
+camel_tcp_stream_ssl_sockfd (CamelTcpStreamSSL *stream)
+{
+	return stream->priv->sockfd;	
+}
+
 #endif /* HAVE_NSS */
diff --git a/camel/camel-tcp-stream-ssl.h b/camel/camel-tcp-stream-ssl.h
index d8f5861..f4060a3 100644
--- a/camel/camel-tcp-stream-ssl.h
+++ b/camel/camel-tcp-stream-ssl.h
@@ -24,6 +24,7 @@
 #define CAMEL_TCP_STREAM_SSL_H
 
 #include <camel/camel-tcp-stream.h>
+#include <prio.h>
 
 #define CAMEL_TCP_STREAM_SSL_TYPE     (camel_tcp_stream_ssl_get_type ())
 #define CAMEL_TCP_STREAM_SSL(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_TCP_STREAM_SSL_TYPE, CamelTcpStreamSSL))
@@ -61,6 +62,8 @@ CamelStream *camel_tcp_stream_ssl_new_raw (struct _CamelSession *session, const
 
 gint camel_tcp_stream_ssl_enable_ssl (CamelTcpStreamSSL *ssl);
 
+PRFileDesc * camel_tcp_stream_ssl_sockfd (CamelTcpStreamSSL *stream);
+
 G_END_DECLS
 
 #endif /* CAMEL_TCP_STREAM_SSL_H */
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 1f29807..77ab12f 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -17,6 +17,8 @@
 #include <prerr.h>
 #endif
 
+#include <poll.h>
+
 #include <camel/camel-list-utils.h>
 #include <camel/camel-msgport.h>
 #include <camel/camel-object.h>
@@ -870,7 +872,7 @@ imapx_find_job(CamelIMAPXServer *imap, gint type, const gchar *uid)
 
 	QUEUE_LOCK(imap);
 
-	for (node = imap->jobs.head;node->next;node = node->next) {
+	for (node = imap->jobs.head;node->next;node = job->msg.ln.next) {
 		job = (CamelIMAPXJob *) node;
 		if (job->type != type)
 			continue;
@@ -942,6 +944,7 @@ imapx_untagged(CamelIMAPXServer *imap, CamelException *ex)
 	guint id, len;
 	guchar *token, *p, c;
 	gint tok;
+	gboolean lsub = FALSE;
 	struct _status_info *sinfo;
 
 	e(printf("got untagged response\n"));
@@ -1091,7 +1094,9 @@ imapx_untagged(CamelIMAPXServer *imap, CamelException *ex)
 		imap_free_fetch(finfo);
 		break;
 	}
-	case IMAP_LIST: case IMAP_LSUB: {
+	case IMAP_LSUB: 
+		lsub = TRUE;
+	case IMAP_LIST: {
 		struct _list_info *linfo = imap_parse_list(imap->stream, ex);
 		CamelIMAPXJob *job = imapx_find_job(imap, IMAPX_JOB_LIST, linfo->name);
 
@@ -1099,6 +1104,8 @@ imapx_untagged(CamelIMAPXServer *imap, CamelException *ex)
 
 		printf("list: '%s' (%c)\n", linfo->name, linfo->separator);
 		if (job && g_hash_table_lookup(job->u.list.folders, linfo->name) == NULL) {
+			if (lsub)
+				linfo->flags |= CAMEL_FOLDER_SUBSCRIBED;
 			g_hash_table_insert(job->u.list.folders, linfo->name, linfo);
 		} else {
 			g_warning("got list response but no current listing job happening?\n");
@@ -1613,6 +1620,21 @@ retry:
 			ic = camel_imapx_command_new ("NAMESPACE", NULL, "NAMESPACE");
 			imapx_command_run (is, ic, ex);
 			camel_imapx_command_free (ic);
+		} else {
+			CamelIMAPXNamespaceList *nsl = NULL;
+			CamelIMAPXStoreNamespace *ns = NULL;
+			CamelIMAPXStore *imapx_store = (CamelIMAPXStore *) is->store;
+		
+			/* set a default namespace */	
+			nsl = g_malloc0(sizeof(CamelIMAPXNamespaceList));
+			ns = g_new0 (CamelIMAPXStoreNamespace, 1);
+			ns->next = NULL;
+			ns->path = g_strdup ("");
+			ns->full_name = g_strdup ("");
+			/* FIXME needs to be identified from list response */
+			ns->sep = '/';
+			nsl->personal = ns;
+			imapx_store->summary->namespaces = nsl;
 		}
 }
 
@@ -1628,7 +1650,7 @@ imapx_job_done(CamelIMAPXServer *is, CamelIMAPXCommand *ic)
 		camel_exception_clear(job->ex);
 		g_free(job);
 	} else
-		camel_msgport_reply(job->msg.reply_port);
+		camel_msgport_reply((CamelMsg *) job);
 }
 
 /* ********************************************************************** */
@@ -2204,18 +2226,18 @@ imapx_server_loop(gpointer d)
 			break;
 		}
 
-		job = (CamelIMAPXJob *)camel_msgport_try_pop (is->port);
+/*		job = (CamelIMAPXJob *)camel_msgport_try_pop (is->port);
 		if (job) {
 			camel_dlist_addtail(&is->jobs, (CamelDListNode *)job);
 			job->start(is, job);
-		}
+		} */
 
-		if (!camel_dlist_empty(&is->active)
+/*		if (!camel_dlist_empty(&is->active)
 				|| camel_imapx_stream_buffered(is->stream))
 			imapx_step(is, &ex);
 		else
-			camel_msgport_pop (is->port);
-#if 0
+			camel_msgport_pop (is->port); */
+#if 1
 		/* TODO:
 		   This poll stuff wont work - we might block
 		   waiting for results inside loops etc.
@@ -2232,6 +2254,7 @@ imapx_server_loop(gpointer d)
 
 		/* if ssl stream ... */
 #ifdef HAVE_SSL
+		if (CAMEL_IS_TCP_STREAM_SSL (is->stream->source))
 		{
 			PRPollDesc pollfds[2] = { };
 			gint res;
@@ -2242,6 +2265,7 @@ imapx_server_loop(gpointer d)
 			pollfds[0].in_flags = PR_POLL_READ;
 			pollfds[1].fd = camel_msgport_prfd(is->port);
 			pollfds[1].in_flags = PR_POLL_READ;
+#include <prio.h>
 
 			res = PR_Poll(pollfds, 2, PR_TicksPerSecond() / 10);
 			if (res == -1)
@@ -2252,36 +2276,36 @@ imapx_server_loop(gpointer d)
 					/* This is quite shitty, it will often block on each
 					   part of the decode, causing significant
 					   processing delays. */
-					imapx_step(is);
+					imapx_step(is, &ex);
 				} while (camel_imapx_stream_buffered(is->stream));
 			} else if (pollfds[1].out_flags & PR_POLL_READ) {
 				printf(" * woken * have new job\n");
 				/* job is handled in main loop */
 			}
 		}
-#else
+#endif
+		if (CAMEL_IS_TCP_STREAM (is->stream->source))
 		{
-			struct pollfd[2] = { 0 };
+			struct pollfd fds[2] = { 0 };
 			gint res;
 
-			pollfd[0].fd = ((CamelTcpStreamRaw *)is->stream->source)->sockfd;
-			pollfd[0].events = POLLIN;
-			pollfd[1].fd = camel_msgport_fd(is->port);
-			pollfd[1].events = POLLIN;
+			fds[0].fd = ((CamelTcpStreamRaw *)is->stream->source)->sockfd;
+			fds[0].events = POLLIN;
+			fds[1].fd = camel_msgport_fd(is->port);
+			fds[1].events = POLLIN;
 
-			res = poll(pollfd, 2, 1000*30);
+			res = poll(fds, 2, 1000*30);
 			if (res == -1)
 				sleep(1) /* ?? */ ;
 			else if (res == 0)
 				/* timed out */;
-			else if (pollfds[0].revents & POLLIN) {
+			else if (fds[0].revents & POLLIN) {
 				do {
-					imapx_step(is);
+					imapx_step(is, &ex);
 				} while (camel_imapx_stream_buffered(is->stream));
 			}
 		}
 #endif
-#endif
 		if (camel_exception_is_set (&ex)) {
 			printf("######### Got main loop exception: %s\n", ex.desc);
 			sleep(1);
@@ -2368,15 +2392,24 @@ camel_imapx_server_new(CamelStore *store, CamelURL *url)
 
 /* Client commands */
 
-void
+gboolean
 camel_imapx_server_connect(CamelIMAPXServer *is, gint state)
 {
 	if (state) {
 		pthread_t id;
+		CamelException ex = {0, NULL};
+
+		imapx_reconnect (is, &ex);
+		if (camel_exception_is_set (&ex))
+			return FALSE;
 
 		pthread_create(&id, NULL, imapx_server_loop, is);
+
+		return TRUE;
 	} else {
 		/* tell processing thread to die, and wait till it does? */
+
+		return TRUE;
 	}
 }
 
@@ -2392,7 +2425,7 @@ imapx_run_job(CamelIMAPXServer *is, CamelIMAPXJob *job)
 
 	/* Umm, so all these jobs 'select' first, which means reading(!)
 	   we can't read from this thread ... hrm ... */
-	if (FALSE /*is->state >= IMAPX_AUTHENTICATED*/) {
+	if (is->state >= IMAPX_AUTHENTICATED) {
 		/* NB: Must catch exceptions, cleanup/etc if we fail here? */
 		QUEUE_LOCK(is);
 		camel_dlist_addhead(&is->jobs, (CamelDListNode *)job);
diff --git a/camel/providers/imapx/camel-imapx-server.h b/camel/providers/imapx/camel-imapx-server.h
index a8e5f24..daafb98 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -94,7 +94,7 @@ struct _CamelIMAPXServerClass {
 CamelType               camel_imapx_server_get_type     (void);
 CamelIMAPXServer *camel_imapx_server_new(struct _CamelStore *store, struct _CamelURL *url);
 
-void camel_imapx_server_connect(CamelIMAPXServer *is, gint state);
+gboolean camel_imapx_server_connect(CamelIMAPXServer *is, gint state);
 
 GPtrArray *camel_imapx_server_list(CamelIMAPXServer *is, const gchar *top, guint32 flags, CamelException *ex);
 
diff --git a/camel/providers/imapx/camel-imapx-store.c b/camel/providers/imapx/camel-imapx-store.c
index c2a3304..d5a4cd1 100644
--- a/camel/providers/imapx/camel-imapx-store.c
+++ b/camel/providers/imapx/camel-imapx-store.c
@@ -86,7 +86,7 @@ imapx_name_equal(gconstpointer a, gconstpointer b)
 
 static void imap_construct(CamelService *service, CamelSession *session, CamelProvider *provider, CamelURL *url, CamelException *ex)
 {
-	gchar *base, *summary;
+	gchar *summary;
 	CamelIMAPXStore *store = (CamelIMAPXStore *)service;
 
 	CAMEL_SERVICE_CLASS (parent_class)->construct (service, session, provider, url, ex);
@@ -102,6 +102,10 @@ static void imap_construct(CamelService *service, CamelSession *session, CamelPr
 		camel_store_summary_set_uri_base((CamelStoreSummary *)store->summary, service->url);
 		camel_store_summary_load((CamelStoreSummary *)store->summary);
 	}
+
+	store->base_url = camel_url_to_string (service->url, (CAMEL_URL_HIDE_PASSWORD |
+								   CAMEL_URL_HIDE_PARAMS |
+								   CAMEL_URL_HIDE_AUTH));
 }
 
 extern CamelServiceAuthType camel_imapx_password_authtype;
@@ -249,7 +253,6 @@ get_folder_offline (CamelStore *store, const gchar *folder_name,
 static CamelFolder *
 imap_get_folder (CamelStore *store, const gchar *folder_name, guint32 flags, CamelException *ex)
 {
-	CamelIMAPXStore *istore = (CamelIMAPXStore *)store;
 	CamelFolder *folder;
 
 	folder = get_folder_offline(store, folder_name, flags, ex);
@@ -480,11 +483,40 @@ fill_fi(CamelStore *store, CamelFolderInfo *fi, guint32 flags)
 	}
 }
 
-static gint
-imap_match_pattern(gchar dir_sep, const gchar *pattern, const gchar *name)
+/* imap needs to treat inbox case insensitive */
+/* we'll assume the names are normalised already */
+static guint folder_hash(gconstpointer ap)
+{
+	const gchar *a = ap;
+
+	if (g_ascii_strcasecmp(a, "INBOX") == 0)
+		a = "INBOX";
+
+	return g_str_hash(a);
+}
+
+static gint folder_eq(gconstpointer ap, gconstpointer bp)
 {
-	gchar p, n;
+	const gchar *a = ap;
+	const gchar *b = bp;
+
+	if (g_ascii_strcasecmp(a, "INBOX") == 0)
+		a = "INBOX";
+	if (g_ascii_strcasecmp(b, "INBOX") == 0)
+		b = "INBOX";
 
+	return g_str_equal(a, b);
+}
+
+static gboolean 
+imap_match_pattern(CamelIMAPXStoreNamespace *ns, const gchar *pattern, const gchar *name)
+{
+	gchar p, n, dir_sep;
+
+	if (!ns)
+		return TRUE;
+
+	dir_sep = ns->sep;
 	p = *pattern++;
 	n = *name++;
 	while (n && p) {
@@ -517,7 +549,6 @@ get_folder_info_offline (CamelStore *store, const gchar *top,
 	gchar *pattern, *name;
 	gint i;
 
-//	if (camel_debug("imap:folder_info"))
 	printf("get folder info offline\n");
 
 	/* FIXME: obey other flags */
@@ -552,6 +583,8 @@ get_folder_info_offline (CamelStore *store, const gchar *top,
 	for (i=0;i<camel_store_summary_count((CamelStoreSummary *)imapx_store->summary);i++) {
 		CamelStoreInfo *si = camel_store_summary_index((CamelStoreSummary *)imapx_store->summary, i);
 		const gchar *full_name;
+		CamelIMAPXStoreNamespace *ns;
+		
 
 		if (si == NULL)
 			continue;
@@ -562,13 +595,16 @@ get_folder_info_offline (CamelStore *store, const gchar *top,
 			continue;
 		}
 
-		if ((!strcmp(name, full_name)
-		     || imap_match_pattern(imapx_store->dir_sep, pattern, full_name)
-		     || (include_inbox && !g_ascii_strcasecmp (full_name, "INBOX")))
-//		    && ((imapx_store->parameters & IMAP_PARAM_SUBSCRIPTIONS) == 0
-			&&((flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) == 0
-			|| (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED))) {
+		ns = camel_imapx_store_summary_namespace_find_full (imapx_store->summary, full_name);
 
+		/* Modify the checks to see match the namespaces from preferences */
+		if ((g_str_equal (name, full_name)
+		     || imap_match_pattern (ns, pattern, full_name)
+		     || (include_inbox && !g_ascii_strcasecmp (full_name, "INBOX")))
+		    && ( TRUE
+			|| (si->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)
+			|| (flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIPTION_LIST) != 0)) {
+			
 			fi = imapx_build_folder_info(imapx_store, camel_store_info_path((CamelStoreSummary *)imapx_store->summary, si));
 			fi->unread = si->unread;
 			fi->total = si->total;
@@ -608,8 +644,210 @@ get_folder_info_offline (CamelStore *store, const gchar *top,
 	return fi;
 }
 
+static void
+add_folders_to_summary (CamelIMAPXStore *istore, GPtrArray *folders, GHashTable **table)
+{
+	gint i = 0;
+
+	for (i = 0; i < folders->len; i++) {
+		struct _list_info *li = folders->pdata[i];
+		CamelIMAPXStoreInfo *si;
+		guint32 new_flags;
+		CamelFolderInfo *fi, *hfi;
+		gchar *path;
+		CamelURL *url;
+
+		si = camel_imapx_store_summary_add_from_full (istore->summary, li->name, li->separator);
+		if (!si)
+			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 (si->info.flags != new_flags) {
+			si->info.flags = new_flags;
+			camel_store_summary_touch ((CamelStoreSummary *) istore->summary);
+		}
+		
+		if (!table)
+			continue;
+
+		fi = camel_folder_info_new ();
+		fi->full_name = g_strdup(camel_store_info_path(istore->summary, si));
+		if (!g_ascii_strcasecmp(fi->full_name, "inbox")) {
+			li->flags |= CAMEL_FOLDER_SYSTEM|CAMEL_FOLDER_TYPE_INBOX;
+			fi->name = g_strdup (_("Inbox"));
+		} else
+			fi->name = g_strdup(camel_store_info_name(istore->summary, si));
+
+		/* HACK: some servers report noinferiors for all folders (uw-imapd)
+		   We just translate this into nochildren, and let the imap layer enforce
+		   it.  See create folder */
+		if (li->flags & CAMEL_FOLDER_NOINFERIORS)
+			li->flags = (li->flags & ~CAMEL_FOLDER_NOINFERIORS) | CAMEL_FOLDER_NOCHILDREN;
+		fi->flags = li->flags;
+
+		url = camel_url_new (istore->base_url, NULL);
+		path = alloca(strlen(fi->full_name)+2);
+		sprintf(path, "/%s", fi->full_name);
+		camel_url_set_path(url, path);
+
+		if (li->flags & CAMEL_FOLDER_NOSELECT || fi->name[0] == 0)
+			camel_url_set_param (url, "noselect", "yes");
+		fi->uri = camel_url_to_string (url, 0);
+		camel_url_free (url);
+
+		fi->total = -1;
+		fi->unread = -1;
+
+		hfi = g_hash_table_lookup (*table, fi->name);
+		if (hfi == NULL)
+			g_hash_table_insert (*table, fi->name, fi);
+		else if ((hfi->flags & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED) ^ (fi->flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED))
+			hfi->flags |= CAMEL_STORE_INFO_FOLDER_SUBSCRIBED;
+	}
+}
+
+static void
+free_list (gpointer data, gpointer user_data)
+{
+	struct _list_info *li = data;
+	imap_free_list (li);
+}
+
+static void
+fetch_folders_for_pattern (CamelIMAPXStore *istore, const gchar *pattern, guint32 flags, GHashTable **table, CamelException *ex)
+{
+	GPtrArray *folders = NULL;
+	
+	folders = camel_imapx_server_list (istore->server, pattern, flags, ex);
+	add_folders_to_summary (istore, folders, table);
+	
+	g_ptr_array_foreach (folders, free_list, folders);
+	g_ptr_array_free (folders, TRUE);
+}
+
+static GSList *
+get_namespaces (CamelIMAPXStore *istore)
+{
+	GSList *namespaces = NULL;
+	CamelIMAPXNamespaceList *nsl = NULL;
+
+	/* Add code to return the namespaces from preference else all of them */
+	nsl = istore->summary->namespaces;
+	if (nsl->personal)
+		namespaces = g_slist_append (namespaces, nsl->personal);
+	if (nsl->other)
+		namespaces = g_slist_append (namespaces, nsl->other);
+	if (nsl->shared)
+		namespaces = g_slist_append (namespaces, nsl->shared);
+
+	return namespaces;
+}
+
+static GHashTable *
+fetch_folders_for_namespaces (CamelIMAPXStore *istore, const gchar *pattern, CamelException *ex)
+{
+	GHashTable *folders = NULL;
+	GSList *namespaces = NULL, *l;
+	
+	folders = g_hash_table_new (folder_hash, folder_eq);
+	namespaces = get_namespaces (istore);
+
+	for (l = namespaces; l != NULL; l = g_slist_next (l))
+	{
+		CamelIMAPXStoreNamespace *ns = l->data;	
+
+		while (ns) {
+			guint32 flags = 0;
+			gchar *pat = NULL;
+			
+			if (!pattern) {
+				if (!*ns->path)
+					pat = g_strdup ("");
+				else
+					pat = g_strdup_printf ("%s%c", ns->path, ns->sep);
+			} else
+				pat = g_strdup (pattern);
+
+			flags |= CAMEL_STORE_FOLDER_INFO_RECURSIVE;
+			fetch_folders_for_pattern (istore, pat, flags, &folders, ex);
+			flags |= CAMEL_STORE_FOLDER_INFO_SUBSCRIBED;
+			fetch_folders_for_pattern (istore, pat, flags, &folders, ex);
+
+			g_free (pat);
+		
+			if (pattern)	
+				return folders;
+
+			ns = ns->next;
+		}
+	}
+
+	return folders;
+}
+
+static void
+sync_folders (CamelIMAPXStore *istore, const gchar *pattern, CamelException *ex)
+{
+	struct _list_info *li = NULL;
+	guint32 flags = 0;
+	GHashTable *folders_from_server;
+	gint i, total;
+
+	folders_from_server = fetch_folders_for_namespaces (istore, pattern, ex);
+
+	total = camel_store_summary_count ((CamelStoreSummary *) istore->summary);
+	for (i = 0; i < total; i++) {
+		CamelStoreInfo *si;
+		const gchar *full_name;
+		CamelFolderInfo *fi;
+		
+		si = camel_store_summary_index ((CamelStoreSummary *) istore->summary, i);
+		if (!si)
+			continue;
+		
+		full_name = camel_imapx_store_info_full_name (istore->summary, si);
+		if (!full_name || !*full_name) {
+			camel_store_summary_info_free ((CamelStoreSummary *)istore->summary, si);
+			continue;
+		}
+
+		if (!pattern || imap_match_pattern (camel_imapx_store_summary_namespace_find_full (istore->summary, full_name), pattern, full_name)) {
+			if ((fi = g_hash_table_lookup(folders_from_server, camel_store_info_path(istore->summary, si))) != NULL) {
+				if (((fi->flags ^ si->flags) & CAMEL_STORE_INFO_FOLDER_SUBSCRIBED)) {
+					si->flags = (si->flags & ~CAMEL_FOLDER_SUBSCRIBED) | (fi->flags & CAMEL_FOLDER_SUBSCRIBED);
+					camel_store_summary_touch((CamelStoreSummary *)istore->summary);
+
+					camel_object_trigger_event (CAMEL_OBJECT (istore), "folder_created", fi);
+					camel_object_trigger_event (CAMEL_OBJECT (istore), "folder_subscribed", fi);
+				}
+			} else {
+				gchar *dup_folder_name = g_strdup (camel_store_info_path (istore->summary, si));
+
+				if (dup_folder_name) {
+					CamelException eex;
+
+					camel_exception_init (&eex);
+					
+					/* Delete the folder from cache */
+
+					g_free (dup_folder_name);
+					camel_exception_clear (&eex);
+				} else {
+					camel_store_summary_remove ((CamelStoreSummary *)istore->summary, si);
+				}
+
+				total--;
+				i--;
+			}
+		}
+		camel_store_summary_info_free((CamelStoreSummary *)istore->summary, si);
+	}
+}
+
 static CamelFolderInfo *
-imap_get_folder_info(CamelStore *store, const gchar *top, guint32 flags, CamelException *ex)
+imapx_get_folder_info(CamelStore *store, const gchar *top, guint32 flags, CamelException *ex)
 {
 	CamelIMAPXStore *istore = (CamelIMAPXStore *)store;
 	CamelFolderInfo * fi= NULL;
@@ -618,35 +856,26 @@ imap_get_folder_info(CamelStore *store, const gchar *top, guint32 flags, CamelEx
 	CamelIterator *iter;
 	gint i;
 
+	if (top == NULL)
+		top = "";
+
+	if (CAMEL_OFFLINE_STORE(store)->state == CAMEL_OFFLINE_STORE_NETWORK_UNAVAIL) {
+		fi = get_folder_info_offline (store, top, flags, ex);
+		return fi;
+	}
+	
 	if (istore->server == NULL) {
 		camel_service_connect((CamelService *)store, ex);
 		if (camel_exception_is_set(ex))
 			return NULL;
 	}
-
-	if (top == NULL)
-		top = "";
-
-	if (folders == NULL) {
-		folders = camel_imapx_server_list(istore->server, "", flags, ex);
-		for (i=0;!camel_exception_is_set(ex) && i<folders->len;i++) {
-			struct _list_info *li = folders->pdata[i];
-			gchar *name;
-
-			name = imapx_list_get_path(li);
-			g_free(name);
-		}
+	
+	if (camel_store_summary_count (istore->summary) == 0) {
+		sync_folders (istore, top, ex);
+		camel_store_summary_save((CamelStoreSummary *)istore->summary);
 	}
-
-	i = 0;
-	base = camel_url_copy(((CamelService *)store)->url);
-	fi = folders_build_rec(base, folders, &i, NULL, NULL);
-	camel_url_free(base);
-
-	g_ptr_array_free(folders, TRUE);
-
-	// FIXME: temporary
-	folder_info_fill(store, fi);
+	
+	fi = get_folder_info_offline (store, top, flags, ex);
 
 	return fi;
 }
@@ -916,7 +1145,7 @@ camel_imapx_store_class_init(CamelIMAPXStoreClass *klass)
 	camel_store_class->create_folder = imap_create_folder;
 	camel_store_class->rename_folder = imap_rename_folder;
 	camel_store_class->delete_folder = imap_delete_folder;
-	camel_store_class->get_folder_info = imap_get_folder_info;
+	camel_store_class->get_folder_info = imapx_get_folder_info;
 
 	((CamelStoreClass *)klass)->hash_folder_name = imapx_name_hash;
 	((CamelStoreClass *)klass)->compare_folder_name = imapx_name_equal;
@@ -937,6 +1166,9 @@ imapx_store_finalise(CamelObject *object)
 	/* SIGH */
 
 	camel_service_disconnect((CamelService *)imap_store, TRUE, NULL);
+
+	if (imap_store->base_url)
+		g_free (imap_store->base_url);
 }
 
 CamelType
@@ -945,7 +1177,7 @@ camel_imapx_store_get_type (void)
 	static CamelType camel_imapx_store_type = CAMEL_INVALID_TYPE;
 
 	if (!camel_imapx_store_type) {
-		camel_imapx_store_type = camel_type_register(CAMEL_STORE_TYPE,
+		camel_imapx_store_type = camel_type_register(camel_offline_store_get_type (),
 							    "CamelIMAPXStore",
 							    sizeof (CamelIMAPXStore),
 							    sizeof (CamelIMAPXStoreClass),
diff --git a/camel/providers/imapx/camel-imapx-store.h b/camel/providers/imapx/camel-imapx-store.h
index 03d117f..773e5a0 100644
--- a/camel/providers/imapx/camel-imapx-store.h
+++ b/camel/providers/imapx/camel-imapx-store.h
@@ -32,6 +32,7 @@ extern "C" {
 #include <camel/camel-types.h>
 #include <camel/camel-store.h>
 #include "camel-imapx-store-summary.h"
+#include <camel/camel-offline-store.h>
 
 #define CAMEL_IMAPX_STORE_TYPE     (camel_imapx_store_get_type ())
 #define CAMEL_IMAPX_STORE(obj)     (CAMEL_CHECK_CAST((obj), CAMEL_IMAPX_STORE_TYPE, CamelIMAPXStore))
@@ -46,7 +47,7 @@ struct _pending_fetch {
 };
 
 typedef struct {
-	CamelStore parent_object;
+	CamelOfflineStore parent_object;
 
 	struct _CamelIMAPXServer *server;
 
@@ -60,7 +61,7 @@ typedef struct {
 } CamelIMAPXStore;
 
 typedef struct {
-	CamelStoreClass parent_class;
+	CamelOfflineStoreClass parent_class;
 
 } CamelIMAPXStoreClass;
 
diff --git a/camel/providers/imapx/camel-imapx-utils.c b/camel/providers/imapx/camel-imapx-utils.c
index 7273a15..0868530 100644
--- a/camel/providers/imapx/camel-imapx-utils.c
+++ b/camel/providers/imapx/camel-imapx-utils.c
@@ -157,7 +157,7 @@ imap_parse_capability(CamelIMAPXStream *stream, CamelException *ex)
 	gint tok, len, i;
 	guchar *token, *p, c, *temp;
 	gboolean free_token = FALSE;
-	struct _capability_info * volatile cinfo;
+	struct _capability_info * cinfo;
 
 	cinfo = g_malloc0(sizeof(*cinfo));
 
@@ -175,7 +175,7 @@ imap_parse_capability(CamelIMAPXStream *stream, CamelException *ex)
 			case IMAP_TOK_INT:
 				printf(" cap: '%s'\n", token);
 				for (i = 0; i < G_N_ELEMENTS (capa_table); i++)
-					if (strcmp(token, capa_table[i].name))
+					if (!strcmp(token, capa_table[i].name))
 						cinfo->capa |= capa_table[i].flag;
 				if (free_token) {
 					g_free (token);
@@ -233,6 +233,7 @@ imap_parse_namespace_list (CamelIMAPXStream *stream, CamelException *ex)
 
 				node = g_new0 (CamelIMAPXStoreNamespace, 1);
 				node->next = NULL;
+				node->full_name = g_strdup (token);
 				node->path = g_strdup (token);
 				g_message ("namespace: Node path is %s \n", node->path);
 
@@ -1335,8 +1336,8 @@ static struct {
 } list_flag_table[] = {
 	{ "\\NOINFERIORS", CAMEL_FOLDER_NOINFERIORS },
 	{ "\\NOSELECT", CAMEL_FOLDER_NOSELECT },
-	{ "\\MARKED", 1<<8 },
-	{ "\\UNMARKED", 1<<9 },
+	{ "\\MARKED", 1<< 16},
+	{ "\\UNMARKED", 1<< 17},
 };
 
 struct _list_info *
@@ -1345,7 +1346,7 @@ imap_parse_list(CamelIMAPXStream *is, CamelException *ex)
 {
 	gint tok, len, i;
 	guchar *token, *p, c;
-	struct _list_info * volatile linfo;
+	struct _list_info * linfo;
 
 	linfo = g_malloc0(sizeof(*linfo));
 
@@ -1582,6 +1583,9 @@ imapx_namespace_clear (CamelIMAPXStoreNamespace **ns)
 void
 camel_imapx_namespace_list_clear (struct _CamelIMAPXNamespaceList *nsl)
 {
+	if (!nsl)
+		return;
+	
 	imapx_namespace_clear (&nsl->personal);
 	imapx_namespace_clear (&nsl->shared);
 	imapx_namespace_clear (&nsl->other);



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