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