dovecot-1.2: Allow namespace prefix to be opened as mailbox, if ...
dovecot at dovecot.org
dovecot at dovecot.org
Mon Aug 3 06:22:45 EEST 2009
details: http://hg.dovecot.org/dovecot-1.2/rev/13fa572535f0
changeset: 9276:13fa572535f0
user: Timo Sirainen <tss at iki.fi>
date: Sun Aug 02 23:01:04 2009 -0400
description:
Allow namespace prefix to be opened as mailbox, if it already exists.
diffstat:
7 files changed, 81 insertions(+), 25 deletions(-)
src/imap/cmd-list.c | 2 +
src/imap/commands-util.c | 19 ++++++++--
src/lib-storage/index/maildir/maildir-storage.c | 3 +
src/lib-storage/list/mailbox-list-maildir.c | 9 ----
src/lib-storage/mail-namespace.c | 42 +++++++++++++++++------
src/lib-storage/mailbox-list.c | 27 +++++++++++++-
src/lib-storage/mailbox-list.h | 4 ++
diffs (257 lines):
diff -r 19d851d93f92 -r 13fa572535f0 src/imap/cmd-list.c
--- 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 @@ list_namespace_send_prefix(struct cmd_li
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;
}
diff -r 19d851d93f92 -r 13fa572535f0 src/imap/commands-util.c
--- 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 @@ client_find_storage(struct client_comman
{
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 @@ bool client_verify_mailbox_name(struct c
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 @@ bool client_verify_mailbox_name(struct c
/* 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;
}
diff -r 19d851d93f92 -r 13fa572535f0 src/lib-storage/index/maildir/maildir-storage.c
--- 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 @@ maildir_mailbox_open(struct mail_storage
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 @@ maildir_list_iter_is_mailbox(struct mail
} 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. */
diff -r 19d851d93f92 -r 13fa572535f0 src/lib-storage/list/mailbox-list-maildir.c
--- 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 mai
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);
@@ -133,13 +133,6 @@ maildir_is_valid_existing_name(struct ma
maildir_is_valid_existing_name(struct mailbox_list *list, const char *name)
{
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;
diff -r 19d851d93f92 -r 13fa572535f0 src/lib-storage/mail-namespace.c
--- 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 @@ char mail_namespace_get_root_sep(const s
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 @@ mail_namespace_find_mask(struct mail_nam
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 @@ mail_namespace_find_mask(struct mail_nam
}
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;
}
diff -r 19d851d93f92 -r 13fa572535f0 src/lib-storage/mailbox-list.c
--- 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
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 @@ int mailbox_list_get_mailbox_name_status
*status = MAILBOX_NAME_INVALID;
return 0;
}
-
return list->v.get_mailbox_name_status(list, name, status);
}
@@ -605,6 +611,22 @@ int mailbox_list_iter_deinit(struct mail
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_set_subscribed(struct m
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 @@ int mailbox_list_rename_mailbox(struct m
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");
diff -r 19d851d93f92 -r 13fa572535f0 src/lib-storage/mailbox-list.h
--- 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 @@ mailbox_list_iter_next(struct mailbox_li
/* 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
More information about the dovecot-cvs
mailing list