Mercurial > dovecot > original-hg > dovecot-1.2
changeset 9276:13fa572535f0 HEAD
Allow namespace prefix to be opened as mailbox, if it already exists.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 02 Aug 2009 23:01:04 -0400 |
parents | 19d851d93f92 |
children | f41f451984d7 |
files | src/imap/cmd-list.c src/imap/commands-util.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/list/mailbox-list-maildir.c src/lib-storage/mail-namespace.c src/lib-storage/mailbox-list.c src/lib-storage/mailbox-list.h |
diffstat | 7 files changed, 81 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/cmd-list.c Sun Aug 02 13:53:32 2009 -0400 +++ b/src/imap/cmd-list.c Sun Aug 02 23:01:04 2009 -0400 @@ -269,6 +269,8 @@ ctx->inbox_found = TRUE; flags = list_get_inbox_flags(ctx); + } else if (mailbox_list_mailbox(ctx->ns->list, "", &flags) > 0) { + /* mailbox with namespace prefix exists */ } else { flags = MAILBOX_NONEXISTENT; }
--- a/src/imap/commands-util.c Sun Aug 02 13:53:32 2009 -0400 +++ b/src/imap/commands-util.c Sun Aug 02 23:01:04 2009 -0400 @@ -37,8 +37,15 @@ { struct mail_namespace *ns; + if (!client_verify_mailbox_name(cmd, *mailbox, + CLIENT_VERIFY_MAILBOX_NAME)) + return NULL; + ns = client_find_namespace(cmd, mailbox); - return ns == NULL ? NULL : ns->storage; + if (ns == NULL) + return NULL; + + return ns->storage; } bool client_verify_mailbox_name(struct client_command_context *cmd, @@ -56,7 +63,7 @@ return FALSE; /* make sure it even looks valid */ - if (*mailbox == '\0') { + if (*mailbox == '\0' && !(*orig_mailbox != '\0' && ns->list)) { client_send_tagline(cmd, "NO Empty mailbox name."); return FALSE; } @@ -91,8 +98,12 @@ /* check what our storage thinks of it */ list = mail_storage_get_list(ns->storage); - if (mailbox_list_get_mailbox_name_status(list, mailbox, - &mailbox_status) < 0) { + if (mode == CLIENT_VERIFY_MAILBOX_NAME) { + mailbox_status = + mailbox_list_is_valid_existing_name(list, mailbox) ? + MAILBOX_NAME_VALID : MAILBOX_NAME_INVALID; + } else if (mailbox_list_get_mailbox_name_status(list, mailbox, + &mailbox_status) < 0) { client_send_list_error(cmd, list); return FALSE; }
--- a/src/lib-storage/index/maildir/maildir-storage.c Sun Aug 02 13:53:32 2009 -0400 +++ b/src/lib-storage/index/maildir/maildir-storage.c Sun Aug 02 23:01:04 2009 -0400 @@ -536,7 +536,7 @@ return NULL; /* tmp/ directory doesn't exist. does the maildir? */ - if (stat(path, &st) == 0) { + if (*name != '\0' && stat(path, &st) == 0) { /* yes, we'll need to create the missing dirs */ mailbox_list_get_dir_permissions(_storage->list, name, &mode, &gid, &origin); @@ -960,6 +960,7 @@ } else if (errno == ENOENT) { /* doesn't exist - probably a non-existing subscribed mailbox */ *flags |= MAILBOX_NONEXISTENT; + return 0; } else { /* non-selectable. probably either access denied, or symlink destination not found. don't bother logging errors. */
--- a/src/lib-storage/list/mailbox-list-maildir.c Sun Aug 02 13:53:32 2009 -0400 +++ b/src/lib-storage/list/mailbox-list-maildir.c Sun Aug 02 23:01:04 2009 -0400 @@ -59,7 +59,7 @@ maildir_list_get_dirname_path(struct mailbox_list *list, const char *dir, const char *name) { - if (strcmp(list->name, MAILBOX_LIST_NAME_IMAPDIR) == 0) + if (strcmp(list->name, MAILBOX_LIST_NAME_IMAPDIR) == 0 || *name == '\0') return t_strdup_printf("%s/%s", dir, name); return t_strdup_printf("%s/%c%s", dir, list->hierarchy_sep, name); @@ -134,13 +134,6 @@ { size_t len; - if (*name == '\0' && *list->ns->prefix != '\0' && - (list->ns->flags & NAMESPACE_FLAG_INBOX) == 0) { - /* an ugly way to get to Maildir/ root when it's not the - INBOX. */ - return TRUE; - } - if (!maildir_list_is_valid_common(list, name, &len)) return FALSE;
--- a/src/lib-storage/mail-namespace.c Sun Aug 02 13:53:32 2009 -0400 +++ b/src/lib-storage/mail-namespace.c Sun Aug 02 23:01:04 2009 -0400 @@ -370,6 +370,31 @@ return namespaces->sep; } +static bool mail_namespace_is_usable_prefix(struct mail_namespace *ns, + const char *mailbox, bool inbox) +{ + if (strncmp(ns->prefix, mailbox, ns->prefix_len) == 0) { + /* true exact prefix match */ + return TRUE; + } + + if (inbox && strncmp(ns->prefix, "INBOX", 5) == 0 && + strncmp(ns->prefix+5, mailbox+5, ns->prefix_len-5) == 0) { + /* we already checked that mailbox begins with case-insensitive + INBOX. this namespace also begins with INBOX and the rest + of the prefix matches too. */ + return TRUE; + } + + if (strncmp(ns->prefix, mailbox, ns->prefix_len-1) == 0 && + mailbox[ns->prefix_len-1] == '\0' && + ns->prefix[ns->prefix_len-1] == ns->sep) { + /* we're trying to access the namespace prefix itself */ + return TRUE; + } + return FALSE; +} + static struct mail_namespace * mail_namespace_find_mask(struct mail_namespace *namespaces, const char **mailbox, @@ -379,7 +404,7 @@ struct mail_namespace *ns = namespaces; const char *box = *mailbox; struct mail_namespace *best = NULL; - size_t best_len = 0; + unsigned int len, best_len = 0; bool inbox; inbox = strncasecmp(box, "INBOX", 5) == 0; @@ -398,25 +423,22 @@ } for (; ns != NULL; ns = ns->next) { - if (ns->prefix_len >= best_len && - (strncmp(ns->prefix, box, ns->prefix_len) == 0 || - (inbox && strncmp(ns->prefix, "INBOX", 5) == 0 && - strncmp(ns->prefix+5, box+5, ns->prefix_len-5) == 0)) && - (ns->flags & mask) == flags) { + if (ns->prefix_len >= best_len && (ns->flags & mask) == flags && + mail_namespace_is_usable_prefix(ns, box, inbox)) { best = ns; best_len = ns->prefix_len; } } if (best != NULL) { - if (best_len > 0) - *mailbox += best_len; - else if (inbox && (box[5] == best->sep || box[5] == '\0')) + if (best_len > 0) { + len = strlen(*mailbox); + *mailbox += I_MIN(len, best_len); + } else if (inbox && (box[5] == best->sep || box[5] == '\0')) *mailbox = t_strconcat("INBOX", box+5, NULL); *mailbox = mail_namespace_fix_sep(best, *mailbox); } - return best; }
--- a/src/lib-storage/mailbox-list.c Sun Aug 02 13:53:32 2009 -0400 +++ b/src/lib-storage/mailbox-list.c Sun Aug 02 23:01:04 2009 -0400 @@ -433,6 +433,13 @@ bool mailbox_list_is_valid_existing_name(struct mailbox_list *list, const char *name) { + if (*name == '\0' && *list->ns->prefix != '\0' && + (list->ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0) { + /* an ugly way to get to mailbox root (e.g. Maildir/ when + it's not the INBOX) */ + return TRUE; + } + return list->v.is_valid_existing_name(list, name); } @@ -491,7 +498,6 @@ *status = MAILBOX_NAME_INVALID; return 0; } - return list->v.get_mailbox_name_status(list, name, status); } @@ -605,6 +611,22 @@ return ctx->list->v.iter_deinit(ctx); } +int mailbox_list_mailbox(struct mailbox_list *list, const char *name, + enum mailbox_info_flags *flags_r) +{ + struct mailbox_list_iterate_context ctx; + const char *path; + + memset(&ctx, 0, sizeof(ctx)); + ctx.list = list; + + *flags_r = 0; + path = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR); + return list->v.iter_is_mailbox(&ctx, path, "", "", + MAILBOX_LIST_FILE_TYPE_UNKNOWN, + flags_r); +} + int mailbox_list_set_subscribed(struct mailbox_list *list, const char *name, bool set) { @@ -615,7 +637,7 @@ int mailbox_list_delete_mailbox(struct mailbox_list *list, const char *name) { - if (!mailbox_list_is_valid_existing_name(list, name)) { + if (!mailbox_list_is_valid_existing_name(list, name) || *name == '\0') { mailbox_list_set_error(list, MAIL_ERROR_PARAMS, "Invalid mailbox name"); return -1; @@ -633,6 +655,7 @@ const char *oldname, const char *newname) { if (!mailbox_list_is_valid_existing_name(list, oldname) || + *oldname == '\0' || !mailbox_list_is_valid_create_name(list, newname)) { mailbox_list_set_error(list, MAIL_ERROR_PARAMS, "Invalid mailbox name");
--- a/src/lib-storage/mailbox-list.h Sun Aug 02 13:53:32 2009 -0400 +++ b/src/lib-storage/mailbox-list.h Sun Aug 02 23:01:04 2009 -0400 @@ -217,6 +217,10 @@ /* Deinitialize mailbox list request. Returns -1 if some error occurred while listing. */ int mailbox_list_iter_deinit(struct mailbox_list_iterate_context **ctx); +/* List one mailbox. Returns 1 if info returned, 0 if mailbox doesn't exist, + -1 if error. */ +int mailbox_list_mailbox(struct mailbox_list *list, const char *name, + enum mailbox_info_flags *flags_r); /* Subscribe/unsubscribe mailbox. There should be no error when subscribing to already subscribed mailbox. Subscribing to