[evolution-kolab/ek-wip-porting] CamelIMAPXExtdServer: added own paths (and implementation) for untagged response handler



commit 98e94567334c0cc9ee312dc41d7bb28755599f29
Author: Christian Hilberg <hilberg kernelconcepts de>
Date:   Mon Jan 23 22:21:30 2012 +0100

    CamelIMAPXExtdServer: added own paths (and implementation) for untagged response handler
    
    * added implementation for untagged response handler
      (modified dupe from CamelIMAPXServer)
    * added own code paths to override the ones leading
      to the execution of CamelIMAPXServer::imapx_untagged(),
      so that our own modified variant of the function
      will be called later on
    * added/changed implementations for connecting and
      authenticating to the IMAP server (since these all
      end in the untagged response handler)
      (this is still WIP, the code paths are not yet used)

 .../providers/imapx/camel-imapx-extd-server.c      | 1331 +++++++++++++++++++-
 .../providers/imapx/camel-imapx-extd-server.h      |   13 +-
 2 files changed, 1320 insertions(+), 24 deletions(-)
---
diff --git a/src/camel/providers/imapx/camel-imapx-extd-server.c b/src/camel/providers/imapx/camel-imapx-extd-server.c
index e5702a7..fd74423 100644
--- a/src/camel/providers/imapx/camel-imapx-extd-server.c
+++ b/src/camel/providers/imapx/camel-imapx-extd-server.c
@@ -29,9 +29,25 @@
 #include <config.h>
 #endif
 
+// fixme, use own type funcs
+#include <ctype.h>
+
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n-lib.h>
+
+#include "camel-imapx-settings.h"
+#include "camel-imapx-utils.h"
+#include "camel-imapx-summary.h"
+
 #include "camel-imapx-extd-folder.h"
 #include "camel-imapx-extd-store.h"
+
 #include "camel-imapx-extd-server.h"
+#include "camel-imapx-server-defs.h"
+#include "camel-imapx-server-friend.h"
 
 /*----------------------------------------------------------------------------*/
 
@@ -45,6 +61,12 @@ struct _CamelIMAPXExtdServerPrivate {
 G_DEFINE_TYPE (CamelIMAPXExtdServer, camel_imapx_extd_server, CAMEL_TYPE_IMAPX_SERVER)
 
 /*----------------------------------------------------------------------------*/
+/* externs / module statics */
+
+extern gint camel_application_is_exiting;
+static guint signals[LAST_SIGNAL];
+
+/*----------------------------------------------------------------------------*/
 /* object init */
 
 static void
@@ -80,8 +102,6 @@ camel_imapx_extd_server_finalize (GObject *object)
 	CamelIMAPXExtdServer *self = NULL;
 	CamelIMAPXExtdServerPrivate *priv = NULL;
 
-	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (object));
-
 	self = CAMEL_IMAPX_EXTD_SERVER (object);
 	priv = CAMEL_IMAPX_EXTD_SERVER_PRIVATE (self);
 
@@ -92,6 +112,1102 @@ camel_imapx_extd_server_finalize (GObject *object)
 }
 
 /*----------------------------------------------------------------------------*/
+/* internal statics */
+
+static gint
+extd_server_untagged (CamelIMAPXServer *self,
+                      GCancellable *cancellable,
+                      GError **err)
+{
+	/* restructured and modified dupe of imapx_untagged */
+
+	CamelIMAPXServer *imap = NULL;
+	CamelService *service = NULL;
+	CamelSettings *settings = NULL;
+	CamelSortType fetch_order;
+	guint id = 0, len = 0;
+	guchar *token = NULL, *p = NULL, c;
+	gint tok = 0;
+	gboolean lsub = FALSE;
+	struct _status_info *sinfo = NULL;
+
+	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
+	/* cancellable may be NULL */
+	g_return_val_if_fail (err == NULL || *err == NULL, -1);
+
+	imap = CAMEL_IMAPX_SERVER (self);
+	service = CAMEL_SERVICE (imap->store);
+	settings = camel_service_get_settings (service);
+
+	fetch_order = \
+		camel_imapx_settings_get_fetch_order (CAMEL_IMAPX_SETTINGS (settings));
+
+	e(imap->tagprefix, "got untagged response\n");
+	id = 0;
+	tok = camel_imapx_stream_token (imap->stream, &token, &len, cancellable, err);
+	if (tok < 0)
+		return -1;
+
+	if (tok == IMAPX_TOK_INT) {
+		id = strtoul ((gchar *) token, NULL, 10);
+		tok = camel_imapx_stream_token (imap->stream, &token, &len, cancellable, err);
+		if (tok < 0)
+			return -1;
+	}
+
+	if (tok == '\n') {
+		g_set_error (err,
+		             CAMEL_IMAPX_ERROR,
+		             1,
+		             "truncated server response");
+		return -1;
+	}
+
+	e(imap->tagprefix, "Have token '%s' id %d\n", token, id);
+	p = token;
+	while ((c = *p))
+		*p++ = toupper((gchar) c);
+
+	switch (imapx_tokenise ((const gchar *) token, len)) {
+	case IMAPX_CAPABILITY:
+		if (imap->cinfo)
+			imapx_free_capability (imap->cinfo);
+		imap->cinfo = imapx_parse_capability (imap->stream, cancellable, err);
+		if (imap->cinfo == NULL)
+			return -1;
+		c(imap->tagprefix, "got capability flags %08x\n", imap->cinfo->capa);
+		return 0;
+	case IMAPX_EXPUNGE: {
+		guint32 expunge = id;
+		struct _CamelIMAPXJob *job = \
+			camel_imapx_server_match_active_job (imap,
+			                                     IMAPX_JOB_EXPUNGE,
+			                                     NULL);
+
+		/* If there is a job running, let it handle the deletion */
+		if (job)
+			break;
+
+		c(imap->tagprefix, "expunged: %d\n", id);
+		if (imap->select_folder) {
+			gchar *uid = NULL;
+
+			uid = camel_imapx_server_get_uid_from_index (imap,
+			                                             imap->select_folder->summary,
+			                                             expunge - 1);
+			if (!uid)
+				break;
+
+			camel_imapx_server_expunge_uid_from_summary (imap, uid, TRUE);
+		}
+
+		break;
+	}
+	case IMAPX_VANISHED: {
+		GPtrArray *uids;
+		gboolean unsolicited = TRUE;
+		gint i;
+		guint len;
+		guchar *token;
+		gint tok;
+
+		tok = camel_imapx_stream_token (imap->stream, &token, &len, cancellable, err);
+		if (tok < 0)
+			return -1;
+		if (tok == '(') {
+			unsolicited = FALSE;
+			while (tok != ')') {
+				/* We expect this to be 'EARLIER' */
+				tok = camel_imapx_stream_token (imap->stream, &token, &len, cancellable, err);
+				if (tok < 0)
+					return -1;
+			}
+		} else
+			camel_imapx_stream_ungettoken (imap->stream, tok, token, len);
+
+		uids = imapx_parse_uids (imap->stream, cancellable, err);
+		if (uids == NULL)
+			return -1;
+		for (i = 0; i < uids->len; i++) {
+			gchar *uid = g_strdup_printf("%u", GPOINTER_TO_UINT(g_ptr_array_index (uids, i)));
+			c(imap->tagprefix, "vanished: %s\n", uid);
+			camel_imapx_server_expunge_uid_from_summary (imap, uid, unsolicited);
+		}
+		g_ptr_array_free (uids, FALSE);
+		break;
+	}
+	case IMAPX_NAMESPACE: {
+		CamelIMAPXNamespaceList *nsl = NULL;
+
+		nsl = imapx_parse_namespace_list (imap->stream, cancellable, err);
+		if (nsl != NULL) {
+			CamelIMAPXStore *imapx_store = (CamelIMAPXStore *) imap->store;
+			CamelIMAPXStoreNamespace *ns;
+
+			imapx_store->summary->namespaces = nsl;
+			camel_store_summary_touch ((CamelStoreSummary *) imapx_store->summary);
+
+			/* TODO Need to remove imapx_store->dir_sep to support multiple namespaces */
+			ns = nsl->personal;
+			if (ns)
+				imapx_store->dir_sep = ns->sep;
+		}
+
+		return 0;
+	}
+	case IMAPX_EXISTS:
+		c(imap->tagprefix, "exists: %d\n", id);
+		imap->exists = id;
+
+		if (imap->select_folder)
+			((CamelIMAPXFolder *) imap->select_folder)->exists_on_server = id;
+
+		if (camel_imapx_server_idle_supported (imap) &&
+		    camel_imapx_server_in_idle (imap)) {
+			if (camel_folder_summary_count (imap->select_folder->summary) < id)
+				camel_imapx_server_stop_idle (imap, err);
+		}
+
+		break;
+	case IMAPX_FLAGS: {
+		guint32 flags;
+
+		imapx_parse_flags (imap->stream, &flags, NULL, cancellable, err);
+
+		c(imap->tagprefix, "flags: %08x\n", flags);
+		break;
+	}
+	case IMAPX_FETCH: {
+		struct _fetch_info *finfo;
+
+		finfo = imapx_parse_fetch (imap->stream, cancellable, err);
+		if (finfo == NULL) {
+			imapx_free_fetch (finfo);
+			return -1;
+		}
+
+		if ((finfo->got & (FETCH_BODY | FETCH_UID)) == (FETCH_BODY | FETCH_UID)) {
+			struct _CamelIMAPXJob *job = \
+				camel_imapx_server_match_active_job (imap,
+				                                     IMAPX_JOB_GET_MESSAGE,
+				                                     finfo->uid);
+
+			/* This must've been a get-message request, fill out the body stream,
+			 * in the right spot */
+
+			if (job && job->error == NULL) {
+				if (job->u.get_message.use_multi_fetch) {
+					job->u.get_message.body_offset = finfo->offset;
+					g_seekable_seek (G_SEEKABLE (job->u.get_message.stream), finfo->offset, G_SEEK_SET, NULL, NULL);
+				}
+
+				job->u.get_message.body_len = camel_stream_write_to_stream (finfo->body, job->u.get_message.stream, job->cancellable, &job->error);
+				if (job->u.get_message.body_len == -1)
+					g_prefix_error (
+					                &job->error,
+					                _("Error writing to cache stream: "));
+			}
+		}
+
+		if ((finfo->got & FETCH_FLAGS) && !(finfo->got & FETCH_HEADER)) {
+			struct _CamelIMAPXJob *job = \
+				camel_imapx_server_match_active_job (imap,
+				                                     IMAPX_JOB_FETCH_NEW_MESSAGES | IMAPX_JOB_REFRESH_INFO,
+				                                     NULL);
+			/* This is either a refresh_info job, check to see if it is and update
+			 * if so, otherwise it must've been an unsolicited response, so update
+			 * the summary to match */
+
+			if (job && (finfo->got & FETCH_UID)) {
+				struct _refresh_info r;
+
+				r.uid = finfo->uid;
+				finfo->uid = NULL;
+				r.server_flags = finfo->flags;
+				r.server_user_flags = finfo->user_flags;
+				finfo->user_flags = NULL;
+				r.exists = FALSE;
+				g_array_append_val (job->u.refresh_info.infos, r);
+			} else if (imap->select_folder) {
+				CamelFolder *folder;
+				CamelMessageInfo *mi = NULL;
+				gboolean changed = FALSE;
+				gchar *uid = NULL;
+
+				g_object_ref (imap->select_folder);
+				folder = imap->select_folder;
+
+				c(imap->tagprefix, "flag changed: %d\n", id);
+
+				if (finfo->got & FETCH_UID) {
+					uid = finfo->uid;
+					finfo->uid = NULL;
+				} else {
+					uid = camel_imapx_server_get_uid_from_index (imap, folder->summary, id - 1);
+				}
+
+				if (uid) {
+					mi = camel_folder_summary_get (folder->summary, uid);
+					if (mi) {
+						/* It's unsolicited _unless_ imap->select_pending (i.e. during
+						 * a QRESYNC SELECT */
+						changed = imapx_update_message_info_flags (mi, finfo->flags, finfo->user_flags, imap->permanentflags, folder, !imap->select_pending);
+					} else {
+						/* This (UID + FLAGS for previously unknown message) might
+						 * happen during a SELECT (QRESYNC). We should use it. */
+						c(imap->tagprefix, "flags changed for unknown uid %s\n.", uid);
+					}
+					finfo->user_flags = NULL;
+				}
+
+				if (changed) {
+					if (imap->changes == NULL)
+						imap->changes = camel_folder_change_info_new ();
+
+					camel_folder_change_info_change_uid (imap->changes, uid);
+					g_free (uid);
+				}
+
+				if (camel_imapx_server_idle_supported (imap) &&
+				    changed &&
+				    camel_imapx_server_in_idle (imap)) {
+					camel_folder_summary_save_to_db (imap->select_folder->summary, NULL);
+					imapx_update_store_summary (imap->select_folder);
+					camel_folder_changed (imap->select_folder, imap->changes);
+					camel_folder_change_info_clear (imap->changes);
+				}
+
+				if (mi)
+					camel_message_info_free (mi);
+				g_object_unref (folder);
+			}
+		}
+
+		if ((finfo->got & (FETCH_HEADER | FETCH_UID)) == (FETCH_HEADER | FETCH_UID)) {
+			struct _CamelIMAPXJob *job = \
+				camel_imapx_server_match_active_job (imap,
+				                                     IMAPX_JOB_FETCH_NEW_MESSAGES | IMAPX_JOB_REFRESH_INFO,
+				                                     NULL);
+
+			/* This must be a refresh info job as well, but it has asked for
+			 * new messages to be added to the index */
+
+			if (job) {
+				CamelMimeParser *mp;
+				CamelMessageInfo *mi;
+
+				/* Do we want to save these headers for later too?  Do we care? */
+
+				mp = camel_mime_parser_new ();
+				camel_mime_parser_init_with_stream (mp, finfo->header, NULL);
+				mi = camel_folder_summary_info_new_from_parser (job->folder->summary, mp);
+				g_object_unref (mp);
+
+				if (mi) {
+					guint32 server_flags;
+					CamelFlag *server_user_flags;
+					CamelMessageInfoBase *binfo;
+					gboolean free_user_flags = FALSE;
+
+					mi->uid = camel_pstring_strdup (finfo->uid);
+
+					if (!(finfo->got & FETCH_FLAGS))
+						{
+							struct _refresh_info *r = NULL;
+							GArray *infos = job->u.refresh_info.infos;
+							gint min = job->u.refresh_info.last_index;
+							gint max = job->u.refresh_info.index, mid;
+							gboolean found = FALSE;
+
+							/* array is sorted, so use a binary search */
+							do {
+								gint cmp = 0;
+
+								mid = (min + max) / 2;
+								r = &g_array_index (infos, struct _refresh_info, mid);
+								cmp = camel_imapx_server_refresh_info_uid_cmp (imap, finfo->uid, r->uid, fetch_order == CAMEL_SORT_ASCENDING);
+
+								if (cmp > 0)
+									min = mid + 1;
+								else if (cmp < 0)
+									max = mid - 1;
+								else
+									found = TRUE;
+
+							} while (!found && min <= max);
+
+							if (!found)
+								g_assert_not_reached ();
+
+							server_flags = r->server_flags;
+							server_user_flags = r->server_user_flags;
+						} else {
+						server_flags = finfo->flags;
+						server_user_flags = finfo->user_flags;
+						/* free user_flags ? */
+						finfo->user_flags = NULL;
+						free_user_flags = TRUE;
+					}
+
+					/* If the message is a really new one -- equal or higher than what
+					 * we know as UIDNEXT for the folder, then it came in since we last
+					 * fetched UIDNEXT and UNREAD count. We'll update UIDNEXT in the
+					 * command completion, but update UNREAD count now according to the
+					 * message SEEN flag */
+					if (!(server_flags & CAMEL_MESSAGE_SEEN)) {
+						CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) job->folder;
+						guint64 uidl = strtoull (mi->uid, NULL, 10);
+
+						if (uidl >= ifolder->uidnext_on_server) {
+							c(imap->tagprefix, "Updating unread count for new message %s\n", mi->uid);
+							((CamelIMAPXFolder *) job->folder)->unread_on_server++;
+						} else {
+							c(imap->tagprefix, "Not updating unread count for new message %s\n", mi->uid);
+						}
+					}
+
+					binfo = (CamelMessageInfoBase *) mi;
+					binfo->size = finfo->size;
+
+					if (!camel_folder_summary_check_uid (job->folder->summary, mi->uid)) {
+						CamelIMAPXFolder *ifolder = (CamelIMAPXFolder *) job->folder;
+						gint cnt;
+
+						camel_folder_summary_add (job->folder->summary, mi);
+						imapx_set_message_info_flags_for_new_message (mi, server_flags, server_user_flags, job->folder);
+						camel_folder_change_info_add_uid (job->u.refresh_info.changes, mi->uid);
+
+						if (!g_hash_table_lookup (ifolder->ignore_recent, mi->uid)) {
+							camel_folder_change_info_recent_uid (job->u.refresh_info.changes, mi->uid);
+							g_hash_table_remove (ifolder->ignore_recent, mi->uid);
+						}
+
+						cnt = (camel_folder_summary_count (job->folder->summary) * 100 ) / ifolder->exists_on_server;
+						camel_operation_progress (job->cancellable, cnt ? cnt : 1);
+					}
+
+					if (free_user_flags && server_user_flags)
+						camel_flag_list_free (&server_user_flags);
+
+				}
+			}
+		}
+
+		imapx_free_fetch (finfo);
+		break;
+	}
+	case IMAPX_LSUB:
+		lsub = TRUE;
+	case IMAPX_LIST: {
+		struct _list_info *linfo = imapx_parse_list (imap->stream, cancellable, err);
+		struct _CamelIMAPXJob *job;
+
+		if (!linfo)
+			break;
+
+		job = camel_imapx_server_match_active_job (imap,
+		                                           IMAPX_JOB_LIST,
+		                                           linfo->name);
+
+		// TODO: we want to make sure the names match?
+
+		if (job->u.list.flags & CAMEL_STORE_FOLDER_INFO_SUBSCRIBED) {
+			c(imap->tagprefix, "lsub: '%s' (%c)\n", linfo->name, linfo->separator);
+
+		} else {
+			c(imap->tagprefix, "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");
+			imapx_free_list (linfo);
+		}
+		break;
+	}
+	case IMAPX_RECENT:
+		c(imap->tagprefix, "recent: %d\n", id);
+		imap->recent = id;
+		break;
+	case IMAPX_STATUS: {
+		struct _state_info *sinfo = imapx_parse_status_info (imap->stream, cancellable, err);
+		if (sinfo) {
+			CamelIMAPXStoreSummary *s = ((CamelIMAPXStore *) imap->store)->summary;
+			CamelIMAPXStoreNamespace *ns;
+			CamelIMAPXFolder *ifolder = NULL;;
+
+			ns = camel_imapx_store_summary_namespace_find_full (s, sinfo->name);
+			if (ns) {
+				gchar *path_name;
+
+				path_name = camel_imapx_store_summary_full_to_path (s, sinfo->name, ns->sep);
+				c(imap->tagprefix, "Got folder path '%s' for full '%s'\n", path_name, sinfo->name);
+				if (path_name) {
+					ifolder = (gpointer) camel_store_get_folder_sync (imap->store, path_name, 0, cancellable, err);
+					g_free (path_name);
+				}
+			}
+			if (ifolder) {
+				CamelFolder *cfolder = CAMEL_FOLDER (ifolder);
+
+				ifolder->unread_on_server = sinfo->unseen;
+				ifolder->exists_on_server = sinfo->messages;
+				ifolder->modseq_on_server = sinfo->highestmodseq;
+				ifolder->uidnext_on_server = sinfo->uidnext;
+				ifolder->uidvalidity_on_server = sinfo->uidvalidity;
+				if (sinfo->uidvalidity && sinfo->uidvalidity != ((CamelIMAPXSummary *) cfolder->summary)->validity)
+					camel_imapx_server_invalidate_local_cache (imap, ifolder, sinfo->uidvalidity);
+			} else {
+				c(imap->tagprefix, "Received STATUS for unknown folder '%s'\n", sinfo->name);
+			}
+
+			g_free (sinfo->name);
+			g_free (sinfo);
+		}
+		break;
+	}
+	case IMAPX_BYE: {
+		guchar *token;
+
+		if (camel_imapx_stream_text (imap->stream, &token, cancellable, NULL)) {
+			c(imap->tagprefix, "BYE: %s\n", token);
+			g_set_error (err, CAMEL_IMAPX_ERROR, 1,
+			             "IMAP server said BYE: %s", token);
+		}
+		imap->state = IMAPX_SHUTDOWN;
+		return -1;
+	}
+	case IMAPX_PREAUTH:
+		c(imap->tagprefix, "preauthenticated\n");
+		if (imap->state < IMAPX_AUTHENTICATED)
+			imap->state = IMAPX_AUTHENTICATED;
+		/* fall through... */
+	case IMAPX_OK: case IMAPX_NO: case IMAPX_BAD:
+		/* TODO: validate which ones of these can happen as unsolicited responses */
+		/* TODO: handle bye/preauth differently */
+		camel_imapx_stream_ungettoken (imap->stream, tok, token, len);
+		sinfo = imapx_parse_status (imap->stream, cancellable, err);
+		if (sinfo == NULL)
+			return -1;
+		switch (sinfo->condition) {
+		case IMAPX_CLOSED:
+			c(imap->tagprefix, "previously selected folder is now closed\n");
+			if (imap->select_pending && !imap->select_folder) {
+				imap->select_folder = imap->select_pending;
+			}
+			break;
+		case IMAPX_READ_WRITE:
+			imap->mode = IMAPX_MODE_READ | IMAPX_MODE_WRITE;
+			c(imap->tagprefix, "folder is read-write\n");
+			break;
+		case IMAPX_READ_ONLY:
+			imap->mode = IMAPX_MODE_READ;
+			c(imap->tagprefix, "folder is read-only\n");
+			break;
+		case IMAPX_UIDVALIDITY:
+			imap->uidvalidity = sinfo->u.uidvalidity;
+			break;
+		case IMAPX_UNSEEN:
+			imap->unseen = sinfo->u.unseen;
+			break;
+		case IMAPX_HIGHESTMODSEQ:
+			imap->highestmodseq = sinfo->u.highestmodseq;
+			break;
+		case IMAPX_PERMANENTFLAGS:
+			imap->permanentflags = sinfo->u.permanentflags;
+			break;
+		case IMAPX_UIDNEXT:
+			imap->uidnext = sinfo->u.uidnext;
+			break;
+		case IMAPX_ALERT:
+			c(imap->tagprefix, "ALERT!: %s\n", sinfo->text);
+			break;
+		case IMAPX_PARSE:
+			c(imap->tagprefix, "PARSE: %s\n", sinfo->text);
+			break;
+		case IMAPX_CAPABILITY:
+			if (sinfo->u.cinfo) {
+				struct _capability_info *cinfo = imap->cinfo;
+				imap->cinfo = sinfo->u.cinfo;
+				sinfo->u.cinfo = NULL;
+				if (cinfo)
+					imapx_free_capability (cinfo);
+				c(imap->tagprefix, "got capability flags %08x\n", imap->cinfo->capa);
+			}
+			break;
+		default:
+			break;
+		}
+		imapx_free_status (sinfo);
+		return 0;
+	default:
+		/* unknown response, just ignore it */
+		c(imap->tagprefix, "unknown token: %s\n", token);
+	}
+
+	return camel_imapx_stream_skip (imap->stream, cancellable, err);
+}
+
+static void
+extd_server_step (CamelIMAPXServer *self,
+                  GCancellable *cancellable,
+                  GError **err)
+{
+	/* modified dupe of imapx_step() */
+	guint len = 0;
+	guchar *token = NULL;
+	gint tok = 0;
+
+	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
+	/* cancellable may be NULL */
+	g_return_if_fail (err == NULL || *err == NULL);
+
+	// poll ?  wait for other stuff? loop?
+	tok = camel_imapx_stream_token (self->stream, &token, &len, cancellable, err);
+	if (tok < 0)
+		return;
+
+	if (tok == '*')
+		/* modified */
+		extd_server_untagged (self, cancellable, err);
+	else if (tok == IMAPX_TOK_TOKEN)
+		camel_imapx_server_completion (self, token, len, cancellable, err);
+	else if (tok == '+')
+		camel_imapx_server_continuation (self, FALSE, cancellable, err);
+	else
+		g_set_error (err,
+		             CAMEL_IMAPX_ERROR,
+		             1,
+		             "unexpected server response:");
+}
+
+/* Used to run 1 command synchronously,
+ * use for capa, login, and namespaces only. */
+static gboolean
+extd_server_command_run (CamelIMAPXServer *self,
+                         CamelIMAPXCommand *ic)
+{
+	/* modified dupe of imapx_command_run() */
+
+	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
+	g_assert (ic != NULL);
+
+	camel_imapx_server_command_close (self, ic);
+
+	QUEUE_LOCK (self);
+	camel_imapx_server_command_start (self, ic);
+	QUEUE_UNLOCK (self);
+
+	while (ic->status == NULL && ic->error == NULL) {
+		/* modified */
+		extd_server_step (self, ic->cancellable, &ic->error);
+	}
+
+	if (self->literal == ic)
+		self->literal = NULL;
+
+	QUEUE_LOCK (self);
+	camel_dlist_remove ((CamelDListNode *) ic);
+	QUEUE_UNLOCK (self);
+
+	return (ic->error == NULL);
+}
+
+static gboolean
+extd_server_connect_to_server (CamelIMAPXServer *self,
+                               GCancellable *cancellable,
+                               GError **err)
+{
+	/* modified dupe of imapx_connect_to_server() */
+
+	CamelNetworkSettings *network_settings = NULL;
+	CamelNetworkSecurityMethod method;
+	CamelStream *tcp_stream = NULL;
+	CamelSockOptData sockopt;
+	CamelSettings *settings = NULL;
+	CamelService *service = NULL;
+	guint len = 0;
+	guchar *token = NULL;
+	gint tok = 0;
+	struct _CamelIMAPXCommand *ic = NULL;
+	gboolean success = TRUE;
+	gchar *host = NULL;
+	GError *tmp_err = NULL;
+
+	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
+	/* cancellable may be NULL */
+	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
+
+#ifndef G_OS_WIN32
+	gboolean use_shell_command = FALSE;
+	gchar *shell_command = NULL;
+#endif
+
+	service = CAMEL_SERVICE (self->store);
+	settings = camel_service_get_settings (service);
+
+	network_settings = CAMEL_NETWORK_SETTINGS (settings);
+	host = camel_network_settings_dup_host (network_settings);
+	method = camel_network_settings_get_security_method (network_settings);
+
+#ifndef G_OS_WIN32
+	use_shell_command = \
+		camel_imapx_settings_get_use_shell_command (CAMEL_IMAPX_SETTINGS (settings));
+
+	if (use_shell_command)
+		shell_command = \
+			camel_imapx_settings_dup_shell_command (CAMEL_IMAPX_SETTINGS (settings));
+
+	if (shell_command != NULL) {
+		gboolean success;
+
+		success = camel_imapx_server_connect_to_server_process (self,
+		                                                        shell_command, &tmp_err);
+
+		g_free (shell_command);
+
+		if (success)
+			goto connected;
+		else
+			goto exit;
+	}
+#endif
+
+	tcp_stream = camel_network_service_connect_sync ( \
+	                                                 CAMEL_NETWORK_SERVICE (self->store), cancellable, err);
+
+	if (tcp_stream == NULL) {
+		success = FALSE;
+		goto exit;
+	}
+
+	self->stream = CAMEL_IMAPX_STREAM (camel_imapx_stream_new (tcp_stream));
+	g_object_unref (tcp_stream);
+
+	/* Disable Nagle - we send a lot of small requests which nagle slows down */
+	sockopt.option = CAMEL_SOCKOPT_NODELAY;
+	sockopt.value.no_delay = TRUE;
+	camel_tcp_stream_setsockopt (CAMEL_TCP_STREAM (tcp_stream), &sockopt);
+
+	/* Set keepalive - needed for some hosts/router configurations, we're idle a lot */
+	sockopt.option = CAMEL_SOCKOPT_KEEPALIVE;
+	sockopt.value.keep_alive = TRUE;
+	camel_tcp_stream_setsockopt (CAMEL_TCP_STREAM (tcp_stream), &sockopt);
+
+ connected:
+	self->stream->tagprefix = self->tagprefix;
+	while (1) {
+		// poll ?  wait for other stuff? loop?
+		if (camel_application_is_exiting || self->parser_quit) {
+			g_set_error (err,
+			             G_IO_ERROR,
+			             G_IO_ERROR_CANCELLED,
+			             "Connection to server cancelled\n");
+			success = FALSE;
+			goto exit;
+		}
+
+		tok = camel_imapx_stream_token (self->stream, &token, &len, cancellable, err);
+		if (tok < 0) {
+			success = FALSE;
+			goto exit;
+		}
+
+		if (tok == '*') {
+			/* modified */
+			extd_server_untagged (self, cancellable, err);
+			break;
+		}
+		camel_imapx_stream_ungettoken (self->stream, tok, token, len);
+		if (camel_imapx_stream_text (self->stream, &token, cancellable, err)) {
+			success = FALSE;
+			goto exit;
+		}
+		e(self->tagprefix, "Got unexpected line before greeting:  '%s'\n", token);
+		g_free (token);
+	}
+
+	if (!self->cinfo) {
+		ic = camel_imapx_server_command_new (self,
+		                                     "CAPABILITY", NULL,
+		                                     cancellable, "CAPABILITY");
+		/* modified */
+		extd_server_command_run (self, ic);
+
+		if (ic->error != NULL || ic->status->result != IMAPX_OK) {
+			if (ic->error == NULL)
+				g_set_error (err,
+				             CAMEL_ERROR,
+				             CAMEL_ERROR_GENERIC,
+				             "%s", ic->status->text);
+			else {
+				g_propagate_error (err, ic->error);
+				ic->error = NULL;
+			}
+
+			camel_imapx_server_command_unref (self, ic);
+			success = FALSE;
+
+			goto exit;
+		}
+		camel_imapx_server_command_unref (self, ic);
+	}
+
+	if (method == CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT) {
+
+		if (!(self->cinfo->capa & IMAPX_CAPABILITY_STARTTLS)) {
+			g_set_error (&tmp_err,
+			             CAMEL_ERROR,
+			             CAMEL_ERROR_GENERIC,
+			             _("Failed to connect to IMAP server %s in secure mode: %s"),
+			             host, _("STARTTLS not supported"));
+			goto exit;
+		}
+
+		ic = camel_imapx_server_command_new (self,
+		                                     "STARTTLS", NULL,
+		                                     cancellable, "STARTTLS");
+		/* modified */
+		extd_server_command_run (self, ic);
+
+		if (ic->error != NULL || ic->status->result != IMAPX_OK) {
+			if (ic->error == NULL)
+				g_set_error (&tmp_err,
+				             CAMEL_ERROR,
+				             CAMEL_ERROR_GENERIC,
+				             "%s", ic->status->text);
+			else {
+				g_propagate_error (&tmp_err, ic->error);
+				ic->error = NULL;
+			}
+
+			camel_imapx_server_command_unref (self, ic);
+			goto exit;
+		}
+
+		/* See if we got new capabilities in the STARTTLS response */
+		imapx_free_capability (self->cinfo);
+		self->cinfo = NULL;
+		if (ic->status->condition == IMAPX_CAPABILITY) {
+			self->cinfo = ic->status->u.cinfo;
+			ic->status->u.cinfo = NULL;
+			c(self->tagprefix, "got capability flags %08x\n", self->cinfo->capa);
+		}
+
+		camel_imapx_server_command_unref (self, ic);
+
+		if (camel_tcp_stream_ssl_enable_ssl (CAMEL_TCP_STREAM_SSL (tcp_stream),
+		                                     cancellable, &tmp_err) == -1) {
+			g_prefix_error (&tmp_err,
+			                _("Failed to connect to IMAP server %s in secure mode: "),
+			                host);
+			goto exit;
+		}
+		/* Get new capabilities if they weren't already given */
+		if (!self->cinfo) {
+			ic = camel_imapx_server_command_new (self,
+			                                     "CAPABILITY", NULL,
+			                                     cancellable, "CAPABILITY");
+			/* modified */
+			if (!extd_server_command_run (self, ic)) {
+				g_propagate_error (&tmp_err, ic->error);
+				ic->error = NULL;
+				camel_imapx_server_command_unref (self, ic);
+				goto exit;
+			}
+
+			camel_imapx_server_command_unref (self, ic);
+		}
+	}
+
+ exit:
+	if (tmp_err != NULL) {
+		e(self->tagprefix, "Unable to connect %d %s \n",
+		  tmp_err->code, tmp_err->message);
+		g_propagate_error (err, tmp_err);
+		tmp_err = NULL;
+		g_object_unref (self->stream);
+		self->stream = NULL;
+
+		if (self->cinfo) {
+			imapx_free_capability (self->cinfo);
+			self->cinfo = NULL;
+		}
+
+		success = FALSE;
+	}
+
+	g_free (host);
+
+	return success;
+}
+
+static gboolean
+extd_server_reconnect (CamelIMAPXServer *self,
+                       GCancellable *cancellable,
+                       GError **err)
+{
+	/* modified dupe of imapx_reconnect() */
+
+	CamelIMAPXCommand *ic = NULL;
+	CamelService *service = NULL;
+	CamelSession *session = NULL;
+	CamelSettings *settings = NULL;
+	gchar *mechanism = NULL;
+	gboolean use_idle = FALSE;
+	gboolean use_qresync = FALSE;
+
+	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
+	/* cancellable may be NULL */
+	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
+
+	service = CAMEL_SERVICE (self->store);
+	session = camel_service_get_session (service);
+	settings = camel_service_get_settings (service);
+
+	mechanism = camel_network_settings_dup_auth_mechanism (
+	                                                       CAMEL_NETWORK_SETTINGS (settings));
+
+	use_idle = camel_imapx_settings_get_use_idle (
+	                                              CAMEL_IMAPX_SETTINGS (settings));
+
+	use_qresync = camel_imapx_settings_get_use_qresync (
+	                                                    CAMEL_IMAPX_SETTINGS (settings));
+
+	/* modified */
+	if (!extd_server_connect_to_server (self, cancellable, err))
+		goto exception;
+
+	if (self->state == IMAPX_AUTHENTICATED)
+		goto preauthed;
+
+	if (!camel_session_authenticate_sync (session, service, mechanism, cancellable, err))
+		goto exception;
+
+	/* After login we re-capa unless the server already told us */
+	if (!self->cinfo) {
+		ic = camel_imapx_server_command_new (self,
+		                                     "CAPABILITY", NULL,
+		                                     cancellable, "CAPABILITY");
+		/* modified */
+		if (!extd_server_command_run (self, ic)) {
+			g_propagate_error (err, ic->error);
+			ic->error = NULL;
+			camel_imapx_server_command_unref (self, ic);
+			goto exception;
+		}
+
+		camel_imapx_server_command_unref (self, ic);
+	}
+
+	self->state = IMAPX_AUTHENTICATED;
+
+ preauthed:
+	self->use_idle = use_idle;
+
+	if (camel_imapx_server_idle_supported (self))
+		camel_imapx_server_init_idle (self);
+
+	/* Fetch namespaces */
+	if (self->cinfo->capa & IMAPX_CAPABILITY_NAMESPACE) {
+		ic = camel_imapx_server_command_new (self,
+		                                     "NAMESPACE", NULL,
+		                                     cancellable, "NAMESPACE");
+		/* modified */
+		if (!extd_server_command_run (self, ic)) {
+			g_propagate_error (err, ic->error);
+			ic->error = NULL;
+			camel_imapx_server_command_unref (self, ic);
+			goto exception;
+		}
+
+		camel_imapx_server_command_unref (self, ic);
+	}
+
+	if (use_qresync && self->cinfo->capa & IMAPX_CAPABILITY_QRESYNC) {
+		ic = camel_imapx_server_command_new (self,
+		                                     "ENABLE", NULL, cancellable,
+		                                     "ENABLE CONDSTORE QRESYNC");
+		if (!extd_server_command_run (self, ic)) {
+			g_propagate_error (err, ic->error);
+			ic->error = NULL;
+			camel_imapx_server_command_unref (self, ic);
+			goto exception;
+		}
+
+		camel_imapx_server_command_unref (self, ic);
+
+		self->use_qresync = TRUE;
+	} else
+		self->use_qresync = FALSE;
+
+	if (CAMEL_IMAPX_STORE (self->store)->summary->namespaces == NULL) {
+		CamelIMAPXNamespaceList *nsl = NULL;
+		CamelIMAPXStoreNamespace *ns = NULL;
+		CamelIMAPXStore *imapx_store = CAMEL_IMAPX_STORE (self->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 ("");
+		ns->sep = '/';
+		nsl->personal = ns;
+		imapx_store->summary->namespaces = nsl;
+		/* FIXME needs to be identified from list response */
+		imapx_store->dir_sep = ns->sep;
+	}
+
+	self->state = IMAPX_INITIALISED;
+
+	g_free (mechanism);
+
+	return TRUE;
+
+ exception:
+
+	camel_imapx_server_disconnect (self);
+
+	if (self->cinfo) {
+		imapx_free_capability (self->cinfo);
+		self->cinfo = NULL;
+	}
+
+	g_free (mechanism);
+
+	return FALSE;
+}
+
+static void
+extd_server_parse_contents (CamelIMAPXServer *self,
+                            GCancellable *cancellable,
+                            GError **err)
+{
+	/* modified dupe of parse_contents() */
+
+	gint buffered = 0;
+	GError *tmp_err = NULL;
+
+	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
+	/* cancellable may be NULL */
+	g_return_if_fail (err == NULL || *err == NULL);
+
+	do {
+		/* modified */
+		extd_server_step (self, cancellable, &tmp_err);
+
+		buffered = camel_imapx_stream_buffered (self->stream);
+
+	} while (buffered && tmp_err == NULL);
+
+	if (tmp_err != NULL)
+		g_propagate_error (err, tmp_err);
+}
+
+/*
+ * The main processing (reading) loop.
+ *
+ * Main area of locking required is command_queue
+ * and command_start_next, the 'literal' command,
+ * the jobs queue, the active queue, the queue
+ * queue. */
+static gpointer
+extd_server_parser_thread (gpointer d)
+{
+	/* modified dupe of imapx_parser_thread() */
+
+	CamelIMAPXServer *self = CAMEL_IMAPX_SERVER (d);
+	GCancellable *cancellable;
+	GError *tmp_err = NULL;
+
+	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
+
+	QUEUE_LOCK (self);
+	cancellable = camel_operation_new ();
+	self->cancellable = g_object_ref (cancellable);
+	QUEUE_UNLOCK (self);
+
+	while (tmp_err == NULL && self->stream) {
+		g_cancellable_reset (cancellable);
+
+#ifndef G_OS_WIN32
+		if (self->is_process_stream)	{
+			GPollFD fds[2] = { {0, 0, 0}, {0, 0, 0} };
+			gint res;
+
+			fds[0].fd = ((CamelStreamProcess *) self->stream->source)->sockfd;
+			fds[0].events = G_IO_IN;
+			fds[1].fd = g_cancellable_get_fd (cancellable);
+			fds[1].events = G_IO_IN;
+			res = g_poll (fds, 2, -1);
+			if (res == -1)
+				g_usleep (1) /* ?? */ ;
+			else if (res == 0)
+				/* timed out */;
+			else if (fds[0].revents & G_IO_IN)
+				/* modified */
+				extd_server_parse_contents (self, cancellable, &tmp_err);
+			g_cancellable_release_fd (cancellable);
+		} else
+#endif
+			{
+				/* modified */
+				extd_server_parse_contents (self, cancellable, &tmp_err);
+			}
+
+		if (self->parser_quit)
+			g_cancellable_cancel (cancellable);
+
+		if (g_cancellable_is_cancelled (cancellable)) {
+			gint is_empty;
+
+			QUEUE_LOCK (self);
+			is_empty = camel_dlist_empty (&self->active);
+			QUEUE_UNLOCK (self);
+
+			if (is_empty ||
+			    (camel_imapx_server_idle_supported (self) && camel_imapx_server_in_idle (self))) {
+				g_cancellable_reset (cancellable);
+				g_clear_error (&tmp_err);
+			} else {
+				/* Cancelled error should be set. */
+				g_warn_if_fail (tmp_err != NULL);
+			}
+		}
+
+		/* Jump out of the loop if an error occurred. */
+		if (tmp_err != NULL)
+			break;
+	}
+
+	QUEUE_LOCK (self);
+	self->state = IMAPX_SHUTDOWN;
+	QUEUE_UNLOCK (self);
+
+	camel_imapx_server_cancel_all_jobs (self, tmp_err);
+
+	g_clear_error (&tmp_err);
+
+	QUEUE_LOCK (self);
+	if (self->cancellable != NULL) {
+		g_object_unref (self->cancellable);
+		self->cancellable = NULL;
+	}
+	g_object_unref (cancellable);
+	QUEUE_UNLOCK (self);
+
+	self->parser_quit = FALSE;
+
+	g_signal_emit (self, signals[SHUTDOWN], 0);
+
+	return NULL;
+}
+
+/*----------------------------------------------------------------------------*/
 /* class functions */
 
 static gboolean
@@ -99,16 +1215,55 @@ imapx_extd_server_connect (CamelIMAPXServer *self,
                            GCancellable *cancellable,
                            GError **err)
 {
-	gboolean ok = FALSE;
+	/* modified dupe of camel_imapx_server_connect() */
+
+	gboolean success = FALSE;
 
 	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
 	/* cancellable may be NULL */
 	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
 
-	ok = camel_imapx_server_connect (self,
-	                                 cancellable,
-	                                 err);
-	return ok;
+	if (self->state == IMAPX_SHUTDOWN) {
+		g_set_error (err,
+		             CAMEL_SERVICE_ERROR,
+		             CAMEL_SERVICE_ERROR_UNAVAILABLE,
+		             "Shutting down");
+		return FALSE;
+	}
+
+	if (self->state >= IMAPX_INITIALISED)
+		return TRUE;
+
+	g_static_rec_mutex_lock (&self->ostream_lock);
+	/* modified */
+	success = extd_server_reconnect (self, cancellable, err);
+	g_static_rec_mutex_unlock (&self->ostream_lock);
+
+	if (!success)
+		return FALSE;
+
+	/* modified */
+	self->parser_thread = \
+		g_thread_create ((GThreadFunc) \
+		                 extd_server_parser_thread,
+		                 self,
+		                 TRUE,
+		                 NULL);
+	return TRUE;
+}
+
+static gboolean
+imapx_extd_server_connect_to_server (CamelIMAPXServer *self,
+                                     GCancellable *cancellable,
+                                     GError **err)
+{
+	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
+	/* cancellable may be NULL */
+	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
+
+	return extd_server_connect_to_server (self,
+	                                      cancellable,
+	                                      err);
 }
 
 static CamelAuthenticationResult
@@ -117,17 +1272,121 @@ imapx_extd_server_authenticate (CamelIMAPXServer *self,
                                 GCancellable *cancellable,
                                 GError **err)
 {
-	CamelAuthenticationResult result = CAMEL_AUTHENTICATION_ERROR;
+	/* modified dupe of camel_imapx_server_authenticate() */
+
+	CamelNetworkSettings *network_settings = NULL;
+	CamelSettings *settings = NULL;
+	CamelAuthenticationResult result = CAMEL_AUTHENTICATION_REJECTED;
+	CamelIMAPXCommand *ic = NULL;
+	CamelService *service = NULL;
+	CamelSasl *sasl = NULL;
+	gchar *host = NULL;
+	gchar *user = NULL;
 
 	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
 	g_assert (mechanism != NULL);
 	/* cancellable may be NULL */
-	g_return_val_if_fail (err == NULL || *err == NULL, CAMEL_AUTHENTICATION_ERROR);
+	g_return_val_if_fail (err == NULL || *err == NULL, CAMEL_AUTHENTICATION_REJECTED);
+
+	service = CAMEL_SERVICE (self->store);
+	settings = camel_service_get_settings (service);
+
+	network_settings = CAMEL_NETWORK_SETTINGS (settings);
+	host = camel_network_settings_dup_host (network_settings);
+	user = camel_network_settings_dup_user (network_settings);
+
+	if (mechanism != NULL) {
+		if (!g_hash_table_lookup (self->cinfo->auth_types, mechanism)) {
+			g_set_error (err,
+			             CAMEL_SERVICE_ERROR,
+			             CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+			             _("IMAP server %s does not support %s "
+			               "authentication"), host, mechanism);
+			result = CAMEL_AUTHENTICATION_ERROR;
+			goto exit;
+		}
+
+		sasl = camel_sasl_new ("imap", mechanism, service);
+		if (sasl != NULL) {
+			g_set_error (err,
+			             CAMEL_SERVICE_ERROR,
+			             CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+			             _("No support for %s authentication"),
+			             mechanism);
+			result = CAMEL_AUTHENTICATION_ERROR;
+			goto exit;
+		}
+	}
+
+	if (sasl != NULL) {
+		ic = camel_imapx_server_command_new (self,
+		                                     "AUTHENTICATE", NULL, cancellable,
+		                                     "AUTHENTICATE %A", sasl);
+	} else {
+		const gchar *password = NULL;
+
+		password = camel_service_get_password (service);
+
+		if (user == NULL) {
+			g_set_error_literal (err,
+			                     CAMEL_SERVICE_ERROR,
+			                     CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+			                     _("Cannot authenticate without a username"));
+			result = CAMEL_AUTHENTICATION_ERROR;
+			goto exit;
+		}
+
+		if (password == NULL) {
+			g_set_error_literal (err,
+			                     CAMEL_SERVICE_ERROR,
+			                     CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+			                     _("Authentication password not available"));
+			result = CAMEL_AUTHENTICATION_ERROR;
+			goto exit;
+		}
+
+		ic = camel_imapx_server_command_new (self,
+		                                     "LOGIN", NULL, cancellable,
+		                                     "LOGIN %s %s", user, password);
+	}
+
+	/* modified */
+	extd_server_command_run (self, ic);
+
+	if (ic->error == NULL) {
+		if (ic->status->result == IMAPX_OK)
+			result = CAMEL_AUTHENTICATION_ACCEPTED;
+		else
+			result = CAMEL_AUTHENTICATION_REJECTED;
+	} else {
+		g_propagate_error (err, ic->error);
+		ic->error = NULL;
+		result = CAMEL_AUTHENTICATION_ERROR;
+	}
+
+	/* Forget old capabilities after login. */
+	if (result == CAMEL_AUTHENTICATION_ACCEPTED) {
+		if (self->cinfo) {
+			imapx_free_capability (self->cinfo);
+			self->cinfo = NULL;
+		}
+
+		if (ic->status->condition == IMAPX_CAPABILITY) {
+			self->cinfo = ic->status->u.cinfo;
+			ic->status->u.cinfo = NULL;
+			c(self->tagprefix, "got capability flags %08x\n", self->cinfo->capa);
+		}
+	}
+
+	camel_imapx_server_command_unref (self, ic);
+
+	if (sasl != NULL)
+		g_object_unref (sasl);
+
+ exit:
+	g_free (host);
+	g_free (user);
 
-	result = camel_imapx_server_authenticate (self,
-	                                          mechanism,
-	                                          cancellable,
-	                                          err);
 	return result;
 }
 
@@ -185,7 +1444,7 @@ imapx_extd_server_sync_changes (CamelIMAPXServer *self,
 	gboolean ok = FALSE;
 
 	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
-	g_assert (CAMEL_IS_FOLDER (folder));
+	g_assert (CAMEL_IS_IMAPX_EXTD_FOLDER (folder));
 	/* cancellable may be NULL */
 	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
 
@@ -205,7 +1464,7 @@ imapx_extd_server_expunge (CamelIMAPXServer *self,
 	gboolean ok = FALSE;
 
 	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
-	g_assert (CAMEL_IS_FOLDER (folder));
+	g_assert (CAMEL_IS_IMAPX_EXTD_FOLDER (folder));
 	/* cancellable may be NULL */
 	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
 
@@ -225,7 +1484,7 @@ imapx_extd_server_noop (CamelIMAPXServer *self,
 	gboolean ok = FALSE;
 
 	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
-	g_assert (CAMEL_IS_FOLDER (folder));
+	g_assert (CAMEL_IS_IMAPX_EXTD_FOLDER (folder));
 	/* cancellable may be NULL */
 	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
 
@@ -246,7 +1505,7 @@ imapx_extd_server_get_message (CamelIMAPXServer *self,
 	CamelStream *stream = NULL;
 
 	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
-	g_assert (CAMEL_IS_FOLDER (folder));
+	g_assert (CAMEL_IS_IMAPX_EXTD_FOLDER (folder));
 	g_assert (uid != NULL); /* FIXME correct? */
 	/* cancellable may be NULL */
 	g_return_val_if_fail (err == NULL || *err == NULL, NULL);
@@ -299,7 +1558,7 @@ imapx_extd_server_append_message (CamelIMAPXServer *self,
 	gboolean ok = FALSE;
 
 	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
-	g_assert (CAMEL_IS_FOLDER (folder));
+	g_assert (CAMEL_IS_IMAPX_EXTD_FOLDER (folder));
 	g_assert (CAMEL_IS_MIME_MESSAGE (message));
 	g_assert (mi != NULL); /* FIXME correct? */
 	/* cancellable may be NULL */
@@ -324,7 +1583,7 @@ imapx_extd_server_sync_message (CamelIMAPXServer *self,
 	gboolean ok = FALSE;
 
 	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
-	g_assert (CAMEL_IS_FOLDER (folder));
+	g_assert (CAMEL_IS_IMAPX_EXTD_FOLDER (folder));
 	g_assert (uid != NULL); /* FIXME correct? */
 	/* cancellable may be NULL */
 	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
@@ -346,7 +1605,7 @@ imapx_extd_server_manage_subscription (CamelIMAPXServer *self,
 {
 	gboolean ok = FALSE;
 
-	g_assert (CAMEL_IS_IMAPX_EXTD_FOLDER (self));
+	g_assert (CAMEL_IS_IMAPX_EXTD_SERVER (self));
 	g_assert (foldername != NULL); /* FIXME correct? */
 	/* cancellable may be NULL */
 	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
@@ -516,6 +1775,7 @@ camel_imapx_extd_server_class_init (CamelIMAPXExtdServerClass *klass)
 
 	/* parent class functions (not yet virtualized in parent) */
 	klass->connect = imapx_extd_server_connect;
+	klass->connect_to_server = imapx_extd_server_connect_to_server;
 	klass->authenticate = imapx_extd_server_authenticate;
 	klass->list = imapx_extd_server_list;
 	klass->refresh_info = imapx_extd_server_refresh_info;
@@ -571,22 +1831,49 @@ camel_imapx_extd_server_connect (CamelIMAPXServer *self,
 	return ok;
 }
 
+gboolean
+camel_imapx_extd_server_connect_to_server (CamelIMAPXServer *self,
+                                           GCancellable *cancellable,
+                                           GError **err)
+{
+	CamelIMAPXExtdServerClass *klass = NULL;
+	gboolean ok = FALSE;
+
+	g_return_val_if_fail (CAMEL_IS_IMAPX_EXTD_SERVER (self), FALSE);
+
+	klass = CAMEL_IMAPX_EXTD_SERVER_GET_CLASS (self);
+	ok = klass->connect_to_server (self,
+	                               cancellable,
+	                               err);
+	return ok;
+}
+
 CamelAuthenticationResult
 camel_imapx_extd_server_authenticate (CamelIMAPXServer *self,
                                       const gchar *mechanism,
                                       GCancellable *cancellable,
                                       GError **err)
 {
-	CamelIMAPXExtdServerClass *klass = NULL;
+	CamelIMAPXExtdServerClass *klass = NULL; /* FIXME */
 	CamelAuthenticationResult result = CAMEL_AUTHENTICATION_ERROR;
 
-	g_return_val_if_fail (CAMEL_IS_IMAPX_EXTD_SERVER (self), CAMEL_AUTHENTICATION_ERROR);
+	/* FIXME */
+	g_warning ("%s: FIXME getting CamelIMAPXServer, expected CamelIMAPXExtdServer",
+	           __func__);
+#if 0 /* FIXME */
+	g_return_val_if_fail (CAMEL_IS_IMAPX_EXTD_SERVER (self), CAMEL_AUTHENTICATION_REJECTED);
 
 	klass = CAMEL_IMAPX_EXTD_SERVER_GET_CLASS (self);
 	result = klass->authenticate (self,
 	                              mechanism,
 	                              cancellable,
 	                              err);
+#endif
+	/* FIXME */
+	result = camel_imapx_server_authenticate (self,
+	                                          mechanism,
+	                                          cancellable,
+	                                          err);
 	return result;
 }
 
diff --git a/src/camel/providers/imapx/camel-imapx-extd-server.h b/src/camel/providers/imapx/camel-imapx-extd-server.h
index a27e5e1..cd72a8a 100644
--- a/src/camel/providers/imapx/camel-imapx-extd-server.h
+++ b/src/camel/providers/imapx/camel-imapx-extd-server.h
@@ -78,6 +78,10 @@ struct _CamelIMAPXExtdServerClass {
 	                     GCancellable *cancellable,
 	                     GError **err);
 
+	gboolean (*connect_to_server) (CamelIMAPXServer *self,
+	                               GCancellable *cancellable,
+	                               GError **err);
+
 	CamelAuthenticationResult (*authenticate) (CamelIMAPXServer *self,
 	                                           const gchar *mechanism,
 	                                           GCancellable *cancellable,
@@ -153,7 +157,7 @@ struct _CamelIMAPXExtdServerClass {
 	                           GCancellable *cancellable,
 	                           GError **err);
 
-	gboolean (*rename_folder) (CamelIMAPXServer *is,
+	gboolean (*rename_folder) (CamelIMAPXServer *self,
 	                           const gchar *oldname,
 	                           const gchar *newname,
 	                           GCancellable *cancellable,
@@ -184,6 +188,11 @@ camel_imapx_extd_server_connect (CamelIMAPXServer *self,
                                  GCancellable *cancellable,
                                  GError **err);
 
+gboolean
+camel_imapx_extd_server_connect_to_server (CamelIMAPXServer *self,
+                                           GCancellable *cancellable,
+                                           GError **err);
+
 CamelAuthenticationResult
 camel_imapx_extd_server_authenticate (CamelIMAPXServer *self,
                                       const gchar *mechanism,
@@ -272,7 +281,7 @@ camel_imapx_extd_server_delete_folder (CamelIMAPXServer *self,
                                        GError **err);
 
 gboolean
-camel_imapx_extd_server_rename_folder (CamelIMAPXServer *is,
+camel_imapx_extd_server_rename_folder (CamelIMAPXServer *self,
                                        const gchar *oldname,
                                        const gchar *newname,
                                        GCancellable *cancellable,



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