dovecot-2.2: imapc: If imapc isn't the inbox=yes namespace, do t...

dovecot at dovecot.org dovecot at dovecot.org
Thu Jun 6 10:52:26 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/cdb0e127f010
changeset: 16466:cdb0e127f010
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Jun 06 10:52:14 2013 +0300
description:
imapc: If imapc isn't the inbox=yes namespace, do the login and initial LIST in background.

diffstat:

 src/lib-storage/index/imapc/imapc-list.c    |  61 ++++++++++++------
 src/lib-storage/index/imapc/imapc-list.h    |   1 -
 src/lib-storage/index/imapc/imapc-storage.c |  94 +++++++++++++++++++---------
 src/lib-storage/index/imapc/imapc-storage.h |   3 +
 4 files changed, 106 insertions(+), 53 deletions(-)

diffs (truncated from 332 to 300 lines):

diff -r 55624c42bfb8 -r cdb0e127f010 src/lib-storage/index/imapc/imapc-list.c
--- a/src/lib-storage/index/imapc/imapc-list.c	Thu Jun 06 09:47:39 2013 +0300
+++ b/src/lib-storage/index/imapc/imapc-list.c	Thu Jun 06 10:52:14 2013 +0300
@@ -140,7 +140,7 @@
 	const struct imap_arg *args = reply->args;
 	const char *sep, *name;
 
-	if (list->sep == '\0') {
+	if (storage->root_sep == '\0') {
 		/* we haven't asked for the separator yet.
 		   lets see if this is the reply for its request. */
 		if (args[0].type == IMAP_ARG_EOL ||
@@ -149,8 +149,8 @@
 			return;
 
 		/* we can't handle NIL separator yet */
-		list->sep = sep == NULL ? '/' : sep[0];
-		mailbox_tree_set_separator(list->mailboxes, list->sep);
+		storage->root_sep = sep == NULL ? '/' : sep[0];
+		mailbox_tree_set_separator(list->mailboxes, storage->root_sep);
 	} else {
 		(void)imapc_list_update_tree(list, list->mailboxes, args);
 	}
@@ -163,7 +163,7 @@
 	const struct imap_arg *args = reply->args;
 	struct mailbox_node *node;
 
-	if (list->sep == '\0') {
+	if (storage->root_sep == '\0') {
 		/* we haven't asked for the separator yet */
 		return;
 	}
@@ -192,11 +192,14 @@
 static char imapc_list_get_hierarchy_sep(struct mailbox_list *_list)
 {
 	struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list;
+	char sep;
 
-	/* storage should have looked this up when it was created */
-	i_assert(list->sep != '\0');
-
-	return list->sep;
+	if (imapc_storage_try_get_root_sep(list->storage, &sep) < 0) {
+		/* we can't really fail here. just return a common separator
+		   and keep failing all list commands until it succeeds. */
+		return '/';
+	}
+	return sep;
 }
 
 static const char *
@@ -209,7 +212,9 @@
 	storage_name = mailbox_list_default_get_storage_name(_list, vname);
 	if (*prefix != '\0' && strcasecmp(storage_name, "INBOX") != 0) {
 		storage_name = storage_name[0] == '\0' ? prefix :
-			t_strdup_printf("%s%c%s", prefix, list->sep, storage_name);
+			t_strdup_printf("%s%c%s", prefix,
+			mailbox_list_get_hierarchy_sep(_list),
+			storage_name);
 	}
 	return storage_name;
 }
@@ -230,7 +235,8 @@
 		if (storage_name[0] == '\0') {
 			/* we're looking up the prefix itself */
 		} else {
-			i_assert(storage_name[0] == list->sep);
+			i_assert(storage_name[0] ==
+				 mailbox_list_get_hierarchy_sep(_list));
 			storage_name++;
 		}
 	}
@@ -408,8 +414,12 @@
 	struct imapc_simple_context ctx;
 	struct mailbox_node *node;
 	const char *pattern;
+	char sep;
 
-	i_assert(list->sep != '\0');
+	if (imapc_storage_try_get_root_sep(list->storage, &sep) < 0) {
+		mailbox_list_set_internal_error(&list->list);
+		return -1;
+	}
 
 	if (list->refreshed_mailboxes)
 		return 0;
@@ -427,7 +437,7 @@
 	cmd = imapc_list_simple_context_init(&ctx, list);
 	imapc_command_sendf(cmd, "LIST \"\" %s", pattern);
 	mailbox_tree_deinit(&list->mailboxes);
-	list->mailboxes = mailbox_tree_init(list->sep);
+	list->mailboxes = mailbox_tree_init(sep);
 	mailbox_tree_set_parents_nonexistent(list->mailboxes);
 	imapc_simple_run(&ctx);
 
@@ -505,7 +515,10 @@
 		return _ctx;
 	}
 
-	sep = mailbox_list_get_hierarchy_sep(_list);
+	if (imapc_storage_try_get_root_sep(list->storage, &sep) < 0) {
+		mailbox_list_set_internal_error(_list);
+		ret = -1;
+	}
 
 	pool = pool_alloconly_create("mailbox list imapc iter", 1024);
 	ctx = p_new(pool, struct imapc_mailbox_list_iterate_context, 1);
@@ -623,23 +636,25 @@
 	struct imapc_simple_context ctx;
 	struct imapc_command *cmd;
 	const char *pattern;
-	char sep;
+	char src_sep, dest_sep;
 
 	i_assert(src_list->tmp_subscriptions == NULL);
 
 	if (src_list->refreshed_subscriptions) {
 		if (dest_list->subscriptions == NULL) {
-			sep = mailbox_list_get_hierarchy_sep(dest_list);
+			dest_sep = mailbox_list_get_hierarchy_sep(dest_list);
 			dest_list->subscriptions =
-				mailbox_tree_init(sep);
+				mailbox_tree_init(dest_sep);
 		}
 		return 0;
 	}
 
-	if (src_list->sep == '\0')
-		(void)mailbox_list_get_hierarchy_sep(_src_list);
+	if (imapc_storage_try_get_root_sep(src_list->storage, &src_sep) < 0) {
+		mailbox_list_set_internal_error(dest_list);
+		return -1;
+	}
 
-	src_list->tmp_subscriptions = mailbox_tree_init(src_list->sep);
+	src_list->tmp_subscriptions = mailbox_tree_init(src_sep);
 
 	cmd = imapc_list_simple_context_init(&ctx, src_list);
 	if (*src_list->storage->set->imapc_list_prefix == '\0')
@@ -647,7 +662,7 @@
 	else {
 		pattern = t_strdup_printf("%s%c*",
 				src_list->storage->set->imapc_list_prefix,
-				src_list->sep);
+				src_sep);
 	}
 	imapc_command_sendf(cmd, "LSUB \"\" %s", pattern);
 	imapc_simple_run(&ctx);
@@ -763,8 +778,12 @@
 	struct imapc_simple_context sctx;
 	struct mailbox_node *node;
 	const char *vname;
+	char sep;
 
-	i_assert(list->sep != '\0');
+	if (imapc_storage_try_get_root_sep(list->storage, &sep) < 0) {
+		mailbox_list_set_internal_error(_list);
+		return -1;
+	}
 
 	vname = mailbox_list_get_vname(_list, name);
 	if (!list->refreshed_mailboxes) {
diff -r 55624c42bfb8 -r cdb0e127f010 src/lib-storage/index/imapc/imapc-list.h
--- a/src/lib-storage/index/imapc/imapc-list.h	Thu Jun 06 09:47:39 2013 +0300
+++ b/src/lib-storage/index/imapc/imapc-list.h	Thu Jun 06 10:52:14 2013 +0300
@@ -13,7 +13,6 @@
 	struct mailbox_list *index_list;
 
 	struct mailbox_tree_context *mailboxes, *tmp_subscriptions;
-	char sep;
 
 	unsigned int iter_count;
 
diff -r 55624c42bfb8 -r cdb0e127f010 src/lib-storage/index/imapc/imapc-storage.c
--- a/src/lib-storage/index/imapc/imapc-storage.c	Thu Jun 06 09:47:39 2013 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.c	Thu Jun 06 10:52:14 2013 +0300
@@ -180,36 +180,61 @@
 	}
 }
 
-static int
-imapc_storage_get_hierarchy_sep(struct imapc_storage *storage,
-				const char **error_r)
+static void imapc_storage_sep_verify(struct imapc_storage *storage)
+{
+	const char *imapc_list_prefix = storage->set->imapc_list_prefix;
+
+	if (storage->root_sep == '\0') {
+		mail_storage_set_critical(&storage->storage,
+			"imapc: LIST didn't return hierarchy separator");
+	} else if (imapc_list_prefix[0] != '\0' &&
+		   imapc_list_prefix[strlen(imapc_list_prefix)-1] == storage->root_sep) {
+		mail_storage_set_critical(&storage->storage,
+			"imapc_list_prefix must not end with hierarchy separator");
+	}
+}
+
+static void imapc_storage_sep_callback(const struct imapc_command_reply *reply,
+				       void *context)
+{
+	struct imapc_storage *storage = context;
+
+	storage->root_sep_pending = FALSE;
+	if (reply->state == IMAPC_COMMAND_STATE_OK)
+		imapc_storage_sep_verify(storage);
+	else if (reply->state == IMAPC_COMMAND_STATE_NO)
+		imapc_copy_error_from_reply(storage, MAIL_ERROR_PARAMS, reply);
+	else {
+		mail_storage_set_critical(&storage->storage,
+			"imapc: Command failed: %s", reply->text_full);
+	}
+	imapc_client_stop(storage->client);
+}
+
+static void imapc_storage_send_hierarcy_sep_lookup(struct imapc_storage *storage)
 {
 	struct imapc_command *cmd;
-	struct imapc_simple_context sctx;
-	const char *imapc_list_prefix = storage->set->imapc_list_prefix;
 
-	imapc_simple_context_init(&sctx, storage);
-	cmd = imapc_client_cmd(storage->client, imapc_simple_callback, &sctx);
+	if (storage->root_sep_pending)
+		return;
+	storage->root_sep_pending = TRUE;
+
+	cmd = imapc_client_cmd(storage->client,
+			       imapc_storage_sep_callback, storage);
 	imapc_command_send(cmd, "LIST \"\" \"\"");
-	imapc_simple_run(&sctx);
+}
 
-	if (sctx.ret < 0) {
-		*error_r = t_strdup_printf("LIST failed: %s",
-			mail_storage_get_last_error(&storage->storage, NULL));
-		return -1;
+int imapc_storage_try_get_root_sep(struct imapc_storage *storage, char *sep_r)
+{
+	if (storage->root_sep == '\0') {
+		imapc_storage_send_hierarcy_sep_lookup(storage);
+		while (storage->root_sep_pending)
+			imapc_client_run(storage->client);
+		if (storage->root_sep == '\0')
+			return -1;
 	}
-
-	if (storage->list->sep == '\0') {
-		*error_r = "LIST didn't return hierarchy separator";
-		return -1;
-	}
-
-	if (imapc_list_prefix[0] != '\0' &&
-	    imapc_list_prefix[strlen(imapc_list_prefix)-1] == storage->list->sep) {
-		*error_r = "imapc_list_prefix must not end with hierarchy separator";
-		return -1;
-	}
-	return sctx.ret;
+	*sep_r = storage->root_sep;
+	return 0;
 }
 
 static int
@@ -220,6 +245,7 @@
 	struct imapc_storage *storage = (struct imapc_storage *)_storage;
 	struct imapc_client_settings set;
 	string_t *str;
+	char sep;
 
 	storage->set = mail_storage_get_driver_settings(_storage);
 
@@ -279,10 +305,19 @@
 					imapc_untagged_status);
 	imapc_storage_register_untagged(storage, "NAMESPACE",
 					imapc_untagged_namespace);
-	/* connect to imap server and get the hierarchy separator. */
-	if (imapc_storage_get_hierarchy_sep(storage, error_r) < 0) {
-		imapc_client_deinit(&storage->client);
-		return -1;
+	/* start connecting to imap server and get the hierarchy separator. */
+	imapc_client_login(storage->client, NULL, NULL);
+	imapc_storage_send_hierarcy_sep_lookup(storage);
+	if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
+		/* we're using imapc for the INBOX namespace. wait and make
+		   sure we can successfully access the IMAP server (so if the
+		   username is invalid we don't just keep failing every
+		   command). */
+		if (imapc_storage_try_get_root_sep(storage, &sep) < 0) {
+			imapc_client_deinit(&storage->client);
+			*error_r = "Failed to access imapc backend";
+			return -1;
+		}
 	}
 	return 0;
 }
@@ -302,10 +337,7 @@
 	struct imapc_mailbox_list *list = (struct imapc_mailbox_list *)_list;
 
 	i_assert(storage->list != NULL);
-	i_assert(storage->list->sep != '\0');
-


More information about the dovecot-cvs mailing list