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