changeset 2350:1371d41c375f HEAD

Moved namespace and hierarchy separator handling to imap-specific code. LIST now shows non-hidden namespaces in the LIST reply.
author Timo Sirainen <tss@iki.fi>
date Fri, 23 Jul 2004 00:20:00 +0300
parents b65456de1b49
children 080ac35855d5
files src/imap/cmd-append.c src/imap/cmd-copy.c src/imap/cmd-create.c src/imap/cmd-delete.c src/imap/cmd-list.c src/imap/cmd-namespace.c src/imap/cmd-rename.c src/imap/cmd-select.c src/imap/cmd-status.c src/imap/cmd-subscribe.c src/imap/commands-util.c src/imap/commands-util.h src/imap/namespace.c src/imap/namespace.h src/lib-storage/index/index-storage.c src/lib-storage/index/maildir/maildir-list.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/maildir/maildir-storage.h src/lib-storage/index/mbox/mbox-list.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/index/mbox/mbox-storage.h src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.c src/lib-storage/mail-storage.h src/lib-storage/proxy-mail-storage.c src/pop3/main.c
diffstat 26 files changed, 409 insertions(+), 465 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/cmd-append.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/cmd-append.c	Fri Jul 23 00:20:00 2004 +0300
@@ -69,7 +69,7 @@
 	if (!client_verify_mailbox_name(client, mailbox, TRUE, FALSE))
 		return TRUE;
 
-	storage = client_find_storage(client, mailbox);
+	storage = client_find_storage(client, &mailbox);
 	if (storage == NULL)
 		return TRUE;
 
--- a/src/imap/cmd-copy.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/cmd-copy.c	Fri Jul 23 00:20:00 2004 +0300
@@ -75,7 +75,7 @@
 	if (search_arg == NULL)
 		return TRUE;
 
-	storage = client_find_storage(client, mailbox);
+	storage = client_find_storage(client, &mailbox);
 	if (storage == NULL)
 		return TRUE;
 
--- a/src/imap/cmd-create.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/cmd-create.c	Fri Jul 23 00:20:00 2004 +0300
@@ -14,7 +14,7 @@
 	if (!client_read_string_args(client, 1, &mailbox))
 		return FALSE;
 
-	storage = client_find_storage(client, mailbox);
+	storage = client_find_storage(client, &mailbox);
 	if (storage == NULL)
 		return TRUE;
 
--- a/src/imap/cmd-delete.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/cmd-delete.c	Fri Jul 23 00:20:00 2004 +0300
@@ -28,7 +28,7 @@
 		if (mailbox_close(mailbox) < 0)
 			client_send_untagged_storage_error(client, storage);
 	} else {
-		storage = client_find_storage(client, name);
+		storage = client_find_storage(client, &name);
 		if (storage == NULL)
 			return TRUE;
 	}
--- a/src/imap/cmd-list.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/cmd-list.c	Fri Jul 23 00:20:00 2004 +0300
@@ -48,34 +48,6 @@
 	return *str == '\0' ? "" : str+1;
 }
 
-static int mailbox_list(struct client *client, struct mail_storage *storage,
-			const char *mask, const char *sep, const char *reply,
-			enum mailbox_list_flags list_flags)
-{
-	struct mailbox_list_context *ctx;
-	struct mailbox_list *list;
-	string_t *str;
-
-	ctx = mail_storage_mailbox_list_init(storage, mask, list_flags);
-	if (ctx == NULL)
-		return FALSE;
-
-	str = t_str_new(256);
-	while ((list = mail_storage_mailbox_list_next(ctx)) != NULL) {
-		str_truncate(str, 0);
-		str_printfa(str, "* %s (%s) \"%s\" ", reply,
-			    mailbox_flags2str(list->flags, list_flags),
-			    sep);
-		if (strcasecmp(list->name, "INBOX") == 0)
-			str_append(str, "INBOX");
-		else
-			imap_quote_append_string(str, list->name, FALSE);
-		client_send_line(client, str_c(str));
-	}
-
-	return mail_storage_mailbox_list_deinit(ctx);
-}
-
 static int parse_list_flags(struct client *client, struct imap_arg *args,
 			    enum mailbox_list_flags *list_flags)
 {
@@ -104,15 +76,204 @@
 	return TRUE;
 }
 
+static int
+list_namespace_mailboxes(struct client *client, struct imap_match_glob *glob,
+			 struct namespace *ns, struct mailbox_list_context *ctx,
+			 enum mailbox_list_flags list_flags)
+{
+	struct mailbox_list *list;
+	const char *name;
+	string_t *str, *name_str;
+	int inbox_found = FALSE;
+
+	t_push();
+	str = t_str_new(256);
+	name_str = t_str_new(256);
+	while ((list = mail_storage_mailbox_list_next(ctx)) != NULL) {
+		str_truncate(name_str, 0);
+		str_append(name_str, ns->prefix);
+		str_append(name_str, list->name);
+
+		if (ns->sep != ns->real_sep) {
+                        char *p = str_c_modifyable(name_str);
+			for (; *p != '\0'; p++) {
+				if (*p == ns->real_sep)
+					*p = ns->sep;
+			}
+		}
+		name = str_c(name_str);
+
+		if (*ns->prefix != '\0') {
+			/* With masks containing '*' we do the checks here
+			   so prefix is included in matching */
+			if (glob != NULL &&
+			    imap_match(glob, name) != IMAP_MATCH_YES)
+				continue;
+		} else if (strcasecmp(list->name, "INBOX") == 0) {
+			if (!ns->inbox)
+				continue;
+
+			name = "INBOX";
+			inbox_found = TRUE;
+		}
+
+		str_truncate(str, 0);
+		str_printfa(str, "* LIST (%s) \"%s\" ",
+			    mailbox_flags2str(list->flags, list_flags),
+			    ns->sep_str);
+		imap_quote_append_string(str, name, FALSE);
+		client_send_line(client, str_c(str));
+	}
+	t_pop();
+
+	if (!inbox_found && ns->inbox) {
+		/* INBOX always exists */
+		str_printfa(str, "* LIST () \"%s\" \"INBOX\"", ns->sep_str);
+		client_send_line(client, str_c(str));
+	}
+
+	return mail_storage_mailbox_list_deinit(ctx);
+}
+
+static void skip_prefix(const char **prefix, const char **mask, int inbox)
+{
+	size_t mask_len, prefix_len, len;
+
+	prefix_len = strlen(*prefix);
+	mask_len = strlen(*mask);
+	len = I_MIN(prefix_len, mask_len);
+
+	if (strncmp(*prefix, *mask, len) == 0 ||
+	    (inbox && len >= 6 &&
+	     strncasecmp(*prefix, *mask, 6) == 0)) {
+		*prefix += len;
+		*mask += len;
+	}
+}
+
+static int list_mailboxes(struct client *client,
+			  const char *ref, const char *mask,
+			  enum mailbox_list_flags list_flags)
+{
+	struct namespace *ns;
+	struct mailbox_list_context *ctx;
+	struct imap_match_glob *glob;
+	enum imap_match_result match;
+	const char *cur_prefix, *cur_ref, *cur_mask;
+	size_t len;
+	int inbox;
+
+	inbox = strncasecmp(ref, "INBOX", 5) == 0 ||
+		(*ref == '\0' && strncasecmp(mask, "INBOX", 5) == 0);
+
+	for (ns = client->namespaces; ns != NULL; ns = ns->next) {
+		t_push();
+		cur_prefix = ns->prefix;
+		cur_ref = ref;
+		cur_mask = mask;
+		if (*ref != '\0') {
+			skip_prefix(&cur_prefix, &cur_ref, inbox);
+
+			if (*cur_ref != '\0' && *cur_prefix != '\0') {
+				/* reference parameter didn't match with
+				   namespace prefix. skip this. */
+				t_pop();
+				continue;
+			}
+		}
+
+		if (*cur_ref == '\0' && *cur_prefix != '\0') {
+			skip_prefix(&cur_prefix, &cur_mask,
+				    inbox && cur_ref == ref);
+		}
+
+		glob = imap_match_init(pool_datastack_create(), mask,
+				       inbox && cur_ref == ref, ns->sep);
+
+		if (*cur_ref != '\0' || *cur_prefix == '\0')
+			match = IMAP_MATCH_CHILDREN;
+		else {
+			len = strlen(cur_prefix);
+			if (cur_prefix[len-1] == ns->sep)
+				cur_prefix = t_strndup(cur_prefix, len-1);
+			match = ns->hidden ? IMAP_MATCH_NO :
+				imap_match(glob, cur_prefix);
+
+			if (match == IMAP_MATCH_YES) {
+				/* The prefix itself matches */
+				string_t *str = t_str_new(128);
+				str_printfa(str, "* LIST (%s) \"%s\" ",
+					mailbox_flags2str(MAILBOX_PLACEHOLDER,
+							  list_flags),
+					ns->sep_str);
+				len = strlen(ns->prefix);
+				imap_quote_append_string(str,
+					t_strndup(ns->prefix, len-1), FALSE);
+				client_send_line(client, str_c(str));
+			}
+		}
+
+		if (match >= 0) {
+			unsigned int count = 0;
+			if (*cur_prefix != '\0') {
+				/* we'll have to fix mask */
+				for (; *cur_prefix != '\0'; cur_prefix++) {
+					if (*cur_prefix == ns->sep)
+						count++;
+				}
+				if (count == 0)
+					count = 1;
+
+				while (count > 0) {
+					if (*cur_ref != '\0') {
+						while (*cur_ref != '\0' &&
+						       *cur_ref++ != ns->sep)
+							;
+					} else {
+						while (*cur_mask != '\0' &&
+						       *cur_mask != '*' &&
+						       *cur_mask != ns->sep)
+							cur_mask++;
+						if (*cur_mask == '*') {
+							cur_mask = "*";
+							break;
+						}
+						if (*cur_mask == '\0')
+							break;
+						cur_mask++;
+					}
+					count--;
+				}
+			}
+
+			if (*cur_mask != '*' || strcmp(mask, "*") == 0)
+				glob = NULL;
+
+			cur_ref = namespace_fix_sep(ns, cur_ref);
+			cur_mask = namespace_fix_sep(ns, cur_mask);
+
+			ctx = mail_storage_mailbox_list_init(ns->storage,
+							     cur_ref, cur_mask,
+							     list_flags);
+			if (list_namespace_mailboxes(client, glob, ns, ctx,
+						     list_flags) < 0) {
+				client_send_storage_error(client, ns->storage);
+				t_pop();
+				return -1;
+			}
+		}
+		t_pop();
+	}
+
+	return 0;
+}
+
 int _cmd_list_full(struct client *client, int lsub)
 {
 	struct namespace *ns;
-	struct mail_storage *storage;
 	struct imap_arg *args;
         enum mailbox_list_flags list_flags;
 	const char *ref, *mask;
-	char sep_chr, sep[3];
-	int failed;
 
 	/* [(<options>)] <reference> <mailbox wildcards> */
 	if (!client_read_args(client, 0, 0, &args))
@@ -145,56 +306,27 @@
 		return TRUE;
 	}
 
-	/* FIXME: really needs some work.. */
-	ns = namespace_find(client->namespaces, *ref != '\0' ? ref : mask);
-	if (ns != NULL)
-		storage = ns->storage;
-	else
-		storage = client->namespaces->storage;
-
-	sep_chr = mail_storage_get_hierarchy_sep(storage);
-	if (sep_chr == '"' || sep_chr == '\\') {
-		sep[0] = '\\';
-		sep[1] = sep_chr;
-		sep[2] = '\0';
-	} else {
-		sep[0] = sep_chr;
-		sep[1] = '\0';
-	}
-
 	if (*mask == '\0' && !lsub) {
 		/* special request to return the hierarchy delimiter */
-		client_send_line(client, t_strconcat(
-			"* LIST (\\Noselect) \"", sep, "\" \"\"", NULL));
-		failed = FALSE;
-	} else {
-		if (*ref != '\0') {
-			/* join reference + mask */
-			if (*mask == sep_chr &&
-			    ref[strlen(ref)-1] == sep_chr) {
-				/* LIST A. .B -> A.B */
-				mask++;
-			}
-			if (*mask != sep_chr &&
-			    ref[strlen(ref)-1] != sep_chr) {
-				/* LIST A B -> A.B */
-				mask = t_strconcat(ref, sep, mask, NULL);
-			} else {
-				mask = t_strconcat(ref, mask, NULL);
-			}
+		ns = namespace_find(client->namespaces, &ref);
+		if (ns == NULL) {
+			const char *empty = "";
+			ns = namespace_find(client->namespaces, &empty);
 		}
 
-		failed = mailbox_list(client, storage, mask, sep,
-				      lsub ? "LSUB" : "LIST", list_flags) < 0;
+		if (ns != NULL) {
+			client_send_line(client, t_strconcat(
+				"* LIST (\\Noselect) \"", ns->sep_str,
+				"\" \"\"", NULL));
+		}
+	} else {
+		if (list_mailboxes(client, ref, mask, list_flags) < 0)
+			return TRUE;
 	}
 
-	if (failed)
-		client_send_storage_error(client, storage);
-	else {
-		client_send_tagline(client, lsub ?
-				    "OK Lsub completed." :
-				    "OK List completed.");
-	}
+	client_send_tagline(client, !lsub ?
+			    "OK List completed." :
+			    "OK Lsub completed.");
 	return TRUE;
 }
 
--- a/src/imap/cmd-namespace.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/cmd-namespace.c	Fri Jul 23 00:20:00 2004 +0300
@@ -20,10 +20,7 @@
 			str_append_c(str, '(');
 			imap_quote_append_string(str, ns->prefix, FALSE);
 			str_append(str, " \"");
-			if (ns->hierarchy_sep == '"' ||
-			    ns->hierarchy_sep == '\\')
-				str_append_c(str, '\\');
-			str_append_c(str, ns->hierarchy_sep);
+			str_append(str, ns->sep_str);
 			str_append(str, "\")");
 		}
 
--- a/src/imap/cmd-rename.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/cmd-rename.c	Fri Jul 23 00:20:00 2004 +0300
@@ -15,11 +15,11 @@
 	if (!client_verify_mailbox_name(client, newname, FALSE, TRUE))
 		return TRUE;
 
-	old_storage = client_find_storage(client, oldname);
+	old_storage = client_find_storage(client, &oldname);
 	if (old_storage == NULL)
 		return TRUE;
 
-	new_storage = client_find_storage(client, newname);
+	new_storage = client_find_storage(client, &newname);
 	if (new_storage == NULL)
 		return TRUE;
 
--- a/src/imap/cmd-select.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/cmd-select.c	Fri Jul 23 00:20:00 2004 +0300
@@ -24,7 +24,7 @@
 		}
 	}
 
-	storage = client_find_storage(client, mailbox);
+	storage = client_find_storage(client, &mailbox);
 	if (storage == NULL)
 		return TRUE;
 
--- a/src/imap/cmd-status.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/cmd-status.c	Fri Jul 23 00:20:00 2004 +0300
@@ -102,7 +102,7 @@
 		return TRUE;
 	}
 
-	storage = client_find_storage(client, mailbox);
+	storage = client_find_storage(client, &mailbox);
 	if (storage == NULL)
 		return FALSE;
 
--- a/src/imap/cmd-subscribe.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/cmd-subscribe.c	Fri Jul 23 00:20:00 2004 +0300
@@ -15,7 +15,7 @@
 	if (!client_verify_mailbox_name(client, mailbox, subscribe, FALSE))
 		return TRUE;
 
-	storage = client_find_storage(client, mailbox);
+	storage = client_find_storage(client, &mailbox);
 	if (storage == NULL)
 		return TRUE;
 
--- a/src/imap/commands-util.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/commands-util.c	Fri Jul 23 00:20:00 2004 +0300
@@ -17,7 +17,7 @@
 #define MAILBOX_MAX_NAME_LEN 512
 
 struct mail_storage *
-client_find_storage(struct client *client, const char *mailbox)
+client_find_storage(struct client *client, const char **mailbox)
 {
 	struct namespace *ns;
 
@@ -37,7 +37,7 @@
 	const char *p;
 	char sep;
 
-	storage = client_find_storage(client, mailbox);
+	storage = client_find_storage(client, &mailbox);
 	if (storage == NULL)
 		return FALSE;
 
--- a/src/imap/commands-util.h	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/commands-util.h	Fri Jul 23 00:20:00 2004 +0300
@@ -11,7 +11,7 @@
 /* Finds mail storage for given mailbox from namespaces. If not found,
    sends "Unknown namespace" error message to client. */
 struct mail_storage *
-client_find_storage(struct client *client, const char *mailbox);
+client_find_storage(struct client *client, const char **mailbox);
 
 /* If should_exist is TRUE, this function returns TRUE if the mailbox
    exists. If it doesn't exist but would be a valid mailbox name, the
--- a/src/imap/namespace.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/namespace.c	Fri Jul 23 00:20:00 2004 +0300
@@ -6,13 +6,32 @@
 
 #include <stdlib.h>
 
+static void namespace_init_storage(struct namespace *ns)
+{
+	ns->prefix_len = strlen(ns->prefix);
+	ns->real_sep = mail_storage_get_hierarchy_sep(ns->storage);
+
+	if (ns->sep == '\0')
+                ns->sep = ns->real_sep;
+
+	if (ns->sep == '"' || ns->sep == '\\') {
+		ns->sep_str[0] = '\\';
+		ns->sep_str[1] = ns->sep;
+	} else {
+		ns->sep_str[0] = ns->sep;
+	}
+
+	if (hook_mail_storage_created != NULL)
+		hook_mail_storage_created(&ns->storage);
+}
+
 static struct namespace *
 namespace_add_env(pool_t pool, const char *data, unsigned int num,
 		  const char *user)
 {
         struct namespace *ns;
         const char *sep, *type, *prefix;
-	int inbox, hidden;
+	int inbox, hidden, subscriptions;
 
 	ns = p_new(pool, struct namespace, 1);
 
@@ -21,6 +40,8 @@
 	prefix = getenv(t_strdup_printf("NAMESPACE_%u_PREFIX", num));
 	inbox = getenv(t_strdup_printf("NAMESPACE_%u_INBOX", num)) != NULL;
 	hidden = getenv(t_strdup_printf("NAMESPACE_%u_HIDDEN", num)) != NULL;
+	subscriptions = getenv(t_strdup_printf("NAMESPACE_%u_SUBSCRIPTIONS",
+					       num)) != NULL;
 
 	if (type == NULL || *type == '\0' || strncmp(type, "private", 7) == 0)
 		ns->type = NAMESPACE_PRIVATE;
@@ -37,17 +58,16 @@
 	ns->prefix = p_strdup(pool, prefix);
 	ns->inbox = inbox;
 	ns->hidden = hidden;
-	ns->storage = mail_storage_create_with_data(data, user, ns->prefix,
-						    sep != NULL ? *sep : '\0');
+	ns->subscriptions = subscriptions;
+	ns->storage = mail_storage_create_with_data(data, user);
 	if (ns->storage == NULL) {
 		i_fatal("Failed to create storage for '%s' with data: %s",
 			ns->prefix, data);
 	}
 
-	if (hook_mail_storage_created != NULL)
-		hook_mail_storage_created(&ns->storage);
-
-	ns->hierarchy_sep = mail_storage_get_hierarchy_sep(ns->storage);
+	if (sep != NULL)
+		ns->sep = *sep;
+        namespace_init_storage(ns);
 	return ns;
 }
 
@@ -88,7 +108,7 @@
 	}
 
 	ns = p_new(pool, struct namespace, 1);
-	ns->storage = mail_storage_create_with_data(mail, user, NULL, '\0');
+	ns->storage = mail_storage_create_with_data(mail, user);
 	if (ns->storage == NULL) {
 		if (mail != NULL && *mail != '\0')
 			i_fatal("Failed to create storage with data: %s", mail);
@@ -105,11 +125,9 @@
 
 	ns->type = NAMESPACE_PRIVATE;
 	ns->inbox = TRUE;
-	ns->prefix = p_strdup(pool, "");
-	ns->hierarchy_sep = mail_storage_get_hierarchy_sep(ns->storage);
-	if (hook_mail_storage_created != NULL)
-		hook_mail_storage_created(&ns->storage);
-
+	ns->subscriptions = TRUE;
+	ns->prefix = "";
+	namespace_init_storage(ns);
 	return ns;
 }
 
@@ -121,39 +139,61 @@
 	}
 }
 
-struct namespace *
-namespace_find(struct namespace *namespaces, const char *mailbox)
+const char *namespace_fix_sep(struct namespace *ns, const char *name)
 {
+	char *ret, *p;
+
+	if (ns->sep == ns->real_sep)
+		return name;
+
+	ret = p_strdup(unsafe_data_stack_pool, name);
+	for (p = ret; *p != '\0'; p++) {
+		if (*p == ns->sep)
+			*p = ns->real_sep;
+	}
+	return ret;
+}
+
+struct namespace *
+namespace_find(struct namespace *namespaces, const char **mailbox)
+{
+        struct namespace *ns = namespaces;
+	const char *box = *mailbox;
 	struct namespace *best = NULL;
-	size_t len, best_len = 0;
+	size_t best_len = 0;
 	int inbox;
 
-	inbox = strncasecmp(mailbox, "INBOX", 5) == 0;
-	if (inbox && mailbox[5] == '\0') {
+	inbox = strncasecmp(box, "INBOX", 5) == 0;
+	if (inbox && box[5] == '\0') {
 		/* find the INBOX namespace */
-		while (namespaces != NULL) {
-			if (namespaces->inbox)
-				return namespaces;
-			if (namespaces->prefix == NULL)
-				best = namespaces;
-			namespaces = namespaces->next;
+		*mailbox = "INBOX";
+		while (ns != NULL) {
+			if (ns->inbox)
+				return ns;
+			if (*ns->prefix == '\0')
+				best = ns;
+			ns = ns->next;
 		}
 		return best;
 	}
 
-	while (namespaces != NULL) {
-		len = namespaces->prefix == NULL ? 0 :
-			strlen(namespaces->prefix);
-		if (len >= best_len &&
-		    (strncmp(namespaces->prefix, mailbox, len) == 0 ||
-		     (inbox && strncmp(namespaces->prefix, "INBOX", 5) == 0 &&
-		      mailbox[5] == namespaces->hierarchy_sep &&
-		      namespaces->prefix[5] == namespaces->hierarchy_sep &&
-		      strncmp(namespaces->prefix+6, mailbox+6, len-6) == 0))) {
-			best = namespaces;
-			best_len = len;
+	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))) {
+			best = ns;
+			best_len = ns->prefix_len;
 		}
-		namespaces = namespaces->next;
+	}
+
+	if (best != NULL) {
+		if (best_len > 0)
+			*mailbox += best_len;
+		else if (inbox && (box[5] == best->sep || box[5] == '\0'))
+			*mailbox = t_strconcat("INBOX", box+5, NULL);
+
+		*mailbox = namespace_fix_sep(best, *mailbox);
 	}
 
 	return best;
--- a/src/imap/namespace.h	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/imap/namespace.h	Fri Jul 23 00:20:00 2004 +0300
@@ -11,16 +11,21 @@
 	struct namespace *next;
 
         enum namespace_type type;
-	char hierarchy_sep;
+	char sep, real_sep, sep_str[3];
+
 	char *prefix;
-	int inbox, hidden;
+	size_t prefix_len;
+
+	int inbox, hidden, subscriptions;
 	struct mail_storage *storage;
 };
 
 struct namespace *namespace_init(pool_t pool, const char *user);
 void namespace_deinit(struct namespace *namespaces);
 
+const char *namespace_fix_sep(struct namespace *ns, const char *name);
+
 struct namespace *
-namespace_find(struct namespace *namespaces, const char *mailbox);
+namespace_find(struct namespace *namespaces, const char **mailbox);
 
 #endif
--- a/src/lib-storage/index/index-storage.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/index/index-storage.c	Fri Jul 23 00:20:00 2004 +0300
@@ -44,7 +44,6 @@
 
 void index_storage_deinit(struct index_storage *storage)
 {
-	i_free(storage->storage.namespace);
 	i_free(storage->storage.error);
 
 	if (--index_storage_refcount > 0)
--- a/src/lib-storage/index/maildir/maildir-list.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/index/maildir/maildir-list.c	Fri Jul 23 00:20:00 2004 +0300
@@ -70,13 +70,6 @@
 		return FALSE;
 	}
 
-	/* INBOX exists always */
-	if (imap_match(glob, "INBOX") > 0 && !update_only) {
-		node = mailbox_tree_get(ctx->tree_ctx, "INBOX", NULL);
-		node->flags |= MAILBOX_FLAG_MATCHED | MAILBOX_NOCHILDREN;
-		node->flags &= ~(MAILBOX_PLACEHOLDER | MAILBOX_NONEXISTENT);
-	}
-
 	stat_dirs = getenv("MAILDIR_STAT_DIRS") != NULL;
 
 	mailbox = t_str_new(PATH_MAX);
@@ -139,9 +132,6 @@
 		    match != IMAP_MATCH_PARENT)
 			continue;
 
-		if (strcasecmp(fname, "INBOX") == 0)
-			continue; /* ignore inboxes */
-
 		if (match == IMAP_MATCH_PARENT) {
 			t_push();
 			while ((p = strrchr(mailbox_c,
@@ -219,9 +209,8 @@
 			node = mailbox_tree_get(ctx->tree_ctx, name, NULL);
 			node->flags = MAILBOX_FLAG_MATCHED;
 			if ((ctx->flags & MAILBOX_LIST_FAST_FLAGS) == 0) {
-				if (strcasecmp(name, "INBOX") != 0)
-					node->flags |= MAILBOX_NONEXISTENT;
-				node->flags |= MAILBOX_NOCHILDREN;
+				node->flags |= MAILBOX_NONEXISTENT |
+					MAILBOX_NOCHILDREN;
 			}
 			break;
 		case IMAP_MATCH_PARENT:
@@ -249,7 +238,8 @@
 
 struct mailbox_list_context *
 maildir_mailbox_list_init(struct mail_storage *storage,
-			  const char *mask, enum mailbox_list_flags flags)
+			  const char *ref, const char *mask,
+			  enum mailbox_list_flags flags)
 {
 	struct index_storage *istorage = (struct index_storage *)storage;
         struct maildir_list_context *ctx;
@@ -266,29 +256,32 @@
 	ctx->flags = flags;
 	ctx->tree_ctx = mailbox_tree_init(MAILDIR_FS_SEP);
 
-	if (storage->hierarchy_sep != MAILDIR_FS_SEP &&
-	    strchr(mask, MAILDIR_FS_SEP) != NULL) {
-		/* this will never match, return nothing */
-		return &ctx->mailbox_ctx;
+	if (*ref != '\0') {
+		/* join reference + mask */
+		if (*mask == MAILDIR_FS_SEP &&
+		    ref[strlen(ref)-1] == MAILDIR_FS_SEP) {
+			/* A. .B -> A.B */
+			mask++;
+		} else if (*mask != MAILDIR_FS_SEP &&
+			   ref[strlen(ref)-1] != MAILDIR_FS_SEP) {
+			/* A B -> A.B */
+			mask = t_strconcat(ref, MAILDIR_FS_SEP_S, mask, NULL);
+		} else {
+			mask = t_strconcat(ref, mask, NULL);
+		}
 	}
 
-	mask = maildir_fix_mailbox_name(istorage, mask, FALSE);
 	glob = imap_match_init(pool, mask, TRUE, MAILDIR_FS_SEP);
 
 	ctx->dir = istorage->dir;
-	ctx->prefix = storage->namespace == NULL ? "" :
-		maildir_fix_mailbox_name(istorage, storage->namespace, FALSE);
+	ctx->prefix = "";
 
 	if ((flags & MAILBOX_LIST_SUBSCRIBED) != 0) {
-		if (!maildir_fill_subscribed(ctx, glob)) {
-                        mailbox_tree_deinit(ctx->tree_ctx);
-			pool_unref(pool);
-			return NULL;
-		}
+		if (!maildir_fill_subscribed(ctx, glob))
+			return &ctx->mailbox_ctx;
 	} else if (full_filesystem_access && (p = strrchr(mask, '/')) != NULL) {
 		dir = t_strdup_until(mask, p);
-		ctx->prefix = t_strconcat(ctx->prefix,
-					  t_strdup_until(mask, p+1), NULL);
+		ctx->prefix = p_strdup_until(pool, mask, p+1);
 
 		if (*mask != '/' && *mask != '~')
 			dir = t_strconcat(istorage->dir, "/", dir, NULL);
@@ -298,14 +291,10 @@
 	if ((flags & MAILBOX_LIST_SUBSCRIBED) == 0 ||
 	    (ctx->flags & MAILBOX_LIST_FAST_FLAGS) == 0) {
 		int update_only = (flags & MAILBOX_LIST_SUBSCRIBED) != 0;
-		if (!maildir_fill_readdir(ctx, glob, update_only)) {
-			mailbox_tree_deinit(ctx->tree_ctx);
-			pool_unref(pool);
-			return NULL;
-		}
+		if (!maildir_fill_readdir(ctx, glob, update_only))
+			return &ctx->mailbox_ctx;
 	}
 
-	ctx->prefix = p_strdup(pool, ctx->prefix);
 	ctx->node_path = str_new(pool, 256);
 	ctx->root = mailbox_tree_get(ctx->tree_ctx, NULL, NULL);
 	ctx->mailbox_ctx.storage = storage;
--- a/src/lib-storage/index/maildir/maildir-storage.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Fri Jul 23 00:20:00 2004 +0300
@@ -30,8 +30,7 @@
 static int verify_inbox(struct index_storage *storage);
 
 static struct mail_storage *
-maildir_create(const char *data, const char *user,
-	       const char *namespace, char hierarchy_sep)
+maildir_create(const char *data, const char *user)
 {
 	struct index_storage *storage;
 	const char *root_dir, *inbox_dir, *index_dir, *control_dir;
@@ -91,10 +90,6 @@
 	storage = i_new(struct index_storage, 1);
 	storage->storage = maildir_storage;
 
-	if (hierarchy_sep != '\0')
-		storage->storage.hierarchy_sep = hierarchy_sep;
-	storage->storage.namespace = i_strdup(namespace);
-
 	/* the default ".temp.xxx" prefix would be treated as directory */
 	storage->temp_prefix =
 		i_strconcat("temp.", my_hostname, ".", my_pid, ".", NULL);
@@ -184,48 +179,6 @@
 			   MAILDIR_FS_SEP_S, p+1, NULL);
 }
 
-const char *maildir_fix_mailbox_name(struct index_storage *storage,
-				     const char *name, int remove_namespace)
-{
-	char *dup, *p, sep;
-	size_t len;
-
-	if (strncasecmp(name, "INBOX", 5) == 0 &&
-	    (name[5] == '\0' || name[5] == storage->storage.hierarchy_sep)) {
-		/* use same case with all INBOX folders or we'll get
-		   into trouble */
-		name = t_strconcat("INBOX", name+5, NULL);
-		if (name[5] == '\0') {
-			/* don't check namespace with INBOX */
-			return name;
-		}
-	}
-
-	if (storage->storage.namespace != NULL && remove_namespace) {
-		len = strlen(storage->storage.namespace);
-		if (strncmp(storage->storage.namespace, name, len) != 0) {
-			i_panic("maildir: expecting namespace '%s' in name "
-				"'%s'", storage->storage.namespace, name);
-		}
-		name += len;
-	}
-
-	if (full_filesystem_access && (*name == '/' || *name == '~'))
-		return name;
-
-	sep = storage->storage.hierarchy_sep;
-	if (sep == MAILDIR_FS_SEP)
-		return name;
-
-	dup = t_strdup_noconst(name);
-	for (p = dup; *p != '\0'; p++) {
-		if (*p == sep)
-			*p = MAILDIR_FS_SEP;
-	}
-
-	return dup;
-}
-
 const char *maildir_get_path(struct index_storage *storage, const char *name)
 {
 	if (full_filesystem_access && (*name == '/' || *name == '~'))
@@ -455,7 +408,6 @@
 
 	mail_storage_clear_error(_storage);
 
-	name = maildir_fix_mailbox_name(storage, name, TRUE);
 	if (strcmp(name, "INBOX") == 0) {
 		if (verify_inbox(storage) < 0)
 			return NULL;
@@ -496,7 +448,6 @@
 
 	mail_storage_clear_error(_storage);
 
-	name = maildir_fix_mailbox_name(storage, name, TRUE);
 	if (!maildir_is_valid_create_name(name)) {
 		mail_storage_set_error(_storage, "Invalid mailbox name");
 		return -1;
@@ -524,7 +475,6 @@
 
 	mail_storage_clear_error(_storage);
 
-	name = maildir_fix_mailbox_name(storage, name, TRUE);
 	if (strcmp(name, "INBOX") == 0) {
 		mail_storage_set_error(_storage, "INBOX can't be deleted.");
 		return -1;
@@ -620,29 +570,23 @@
 {
 	struct mailbox_list_context *ctx;
         struct mailbox_list *list;
-	const char *oldpath, *newpath, *new_listname, *mask;
+	const char *oldpath, *newpath, *new_listname;
 	size_t oldnamelen;
 	int ret;
 
 	ret = 0;
 	oldnamelen = strlen(oldname);
 
-	mask = t_strdup_printf("%s%s%c*", storage->storage.namespace != NULL ?
-			       storage->storage.namespace : "", oldname,
-			       storage->storage.hierarchy_sep);
-	ctx = maildir_mailbox_list_init(&storage->storage, mask,
+	ctx = maildir_mailbox_list_init(&storage->storage, oldname, "*",
 					MAILBOX_LIST_FAST_FLAGS);
 	while ((list = maildir_mailbox_list_next(ctx)) != NULL) {
-		const char *list_name;
-
 		t_push();
 
-		list_name = maildir_fix_mailbox_name(storage, list->name, TRUE);
-		i_assert(oldnamelen <= strlen(list_name));
+		i_assert(oldnamelen <= strlen(list->name));
 
 		new_listname = t_strconcat(newname,
-					   list_name + oldnamelen, NULL);
-		oldpath = maildir_get_path(storage, list_name);
+					   list->name + oldnamelen, NULL);
+		oldpath = maildir_get_path(storage, list->name);
 		newpath = maildir_get_path(storage, new_listname);
 
 		/* FIXME: it's possible to merge two folders if either one of
@@ -665,7 +609,7 @@
 			break;
 		}
 
-		(void)rename_indexes(storage, list_name, new_listname);
+		(void)rename_indexes(storage, list->name, new_listname);
 		t_pop();
 	}
 
@@ -683,9 +627,6 @@
 
 	mail_storage_clear_error(_storage);
 
-	oldname = maildir_fix_mailbox_name(storage, oldname, TRUE);
-	newname = maildir_fix_mailbox_name(storage, newname, TRUE);
-
 	if (!maildir_is_valid_existing_name(oldname) ||
 	    !maildir_is_valid_create_name(newname)) {
 		mail_storage_set_error(_storage, "Invalid mailbox name");
@@ -741,7 +682,6 @@
 			   storage->control_dir : storage->dir,
 			   "/" SUBSCRIPTION_FILE_NAME, NULL);
 
-	name = maildir_fix_mailbox_name(storage, name, FALSE);
 	return subsfile_set_subscribed(_storage, path, storage->temp_prefix,
 				       name, set);
 }
@@ -756,7 +696,6 @@
 
 	mail_storage_clear_error(_storage);
 
-	name = maildir_fix_mailbox_name(storage, name, TRUE);
 	if (!maildir_is_valid_existing_name(name)) {
 		*status = MAILBOX_NAME_INVALID;
 		return 0;
@@ -821,9 +760,8 @@
 
 struct mail_storage maildir_storage = {
 	"maildir", /* name */
-	NULL, /* namespace */
 
-	'.', /* default hierarchy separator */
+	'.', /* hierarchy separator */
 
 	maildir_create,
 	maildir_free,
--- a/src/lib-storage/index/maildir/maildir-storage.h	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Fri Jul 23 00:20:00 2004 +0300
@@ -33,7 +33,8 @@
 
 struct mailbox_list_context *
 maildir_mailbox_list_init(struct mail_storage *storage,
-			  const char *mask, enum mailbox_list_flags flags);
+			  const char *ref, const char *mask,
+			  enum mailbox_list_flags flags);
 int maildir_mailbox_list_deinit(struct mailbox_list_context *ctx);
 struct mailbox_list *
 maildir_mailbox_list_next(struct mailbox_list_context *ctx);
@@ -60,8 +61,6 @@
 int maildir_copy_commit(struct maildir_copy_context *ctx);
 void maildir_copy_rollback(struct maildir_copy_context *ctx);
 
-const char *maildir_fix_mailbox_name(struct index_storage *storage,
-				     const char *name, int remove_namespace);
 const char *maildir_get_path(struct index_storage *storage, const char *name);
 
 int maildir_sync_last_commit(struct index_mailbox *ibox);
--- a/src/lib-storage/index/mbox/mbox-list.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/index/mbox/mbox-list.c	Fri Jul 23 00:20:00 2004 +0300
@@ -31,7 +31,6 @@
 
 	enum mailbox_list_flags flags;
 
-	const char *prefix;
 	struct imap_match_glob *glob;
 	struct subsfile_list_context *subsfile_ctx;
 
@@ -45,23 +44,12 @@
 };
 
 static struct mailbox_list *mbox_list_subs(struct mbox_list_context *ctx);
-static struct mailbox_list *mbox_list_inbox(struct mbox_list_context *ctx);
 static struct mailbox_list *mbox_list_path(struct mbox_list_context *ctx);
 static struct mailbox_list *mbox_list_next(struct mbox_list_context *ctx);
-static struct mailbox_list *mbox_list_none(struct mbox_list_context *ctx);
 
-static const char *mask_get_dir(struct mail_storage *storage, const char *mask)
+static const char *mask_get_dir(const char *mask)
 {
 	const char *p, *last_dir;
-	size_t len;
-
-	if (storage->namespace != NULL) {
-		len = strlen(storage->namespace);
-		if (strncmp(mask, storage->namespace, len) != 0)
-			return NULL;
-
-		mask += len;
-	}
 
 	last_dir = NULL;
 	for (p = mask; *p != '\0' && *p != '%' && *p != '*'; p++) {
@@ -110,7 +98,8 @@
 }
 
 struct mailbox_list_context *
-mbox_mailbox_list_init(struct mail_storage *storage, const char *mask,
+mbox_mailbox_list_init(struct mail_storage *storage,
+		       const char *ref, const char *mask,
 		       enum mailbox_list_flags flags)
 {
 	struct index_storage *istorage = (struct index_storage *)storage;
@@ -118,26 +107,32 @@
 	const char *path, *virtual_path;
 	DIR *dirp;
 
+	ctx = i_new(struct mbox_list_context, 1);
+	ctx->mailbox_ctx.storage = storage;
+	ctx->istorage = istorage;
+	ctx->list_pool = pool_alloconly_create("mbox_list", 1024);
+        ctx->next = mbox_list_next;
+
 	mail_storage_clear_error(storage);
 
-	if (storage->hierarchy_sep != '/' && strchr(mask, '/') != NULL) {
-		/* this will never match, return nothing */
-		ctx = i_new(struct mbox_list_context, 1);
-		ctx->mailbox_ctx.storage = storage;
-                ctx->next = mbox_list_none;
+	/* check that we're not trying to do any "../../" lists */
+	if (!mbox_is_valid_mask(ref) ||
+	    !mbox_is_valid_mask(mask)) {
+		mail_storage_set_error(storage, "Invalid mask");
 		return &ctx->mailbox_ctx;
 	}
 
-	mask = mbox_fix_mailbox_name(istorage, mask, FALSE);
-
-	/* check that we're not trying to do any "../../" lists */
-	if (!mbox_is_valid_mask(mask)) {
-		mail_storage_set_error(storage, "Invalid mask");
-		return NULL;
+	if (*mask == '/' || *mask == '~') {
+		/* mask overrides reference */
+	} else if (*ref != '\0') {
+		/* merge reference and mask */
+		if (ref[strlen(ref)-1] == '/')
+			mask = t_strconcat(ref, mask, NULL);
+		else
+			mask = t_strconcat(ref, "/", mask, NULL);
 	}
 
 	if ((flags & MAILBOX_LIST_SUBSCRIBED) != 0) {
-		ctx = i_new(struct mbox_list_context, 1);
 		ctx->mailbox_ctx.storage = storage;
 		ctx->istorage = istorage;
 		ctx->flags = flags;
@@ -148,45 +143,33 @@
 		ctx->subsfile_ctx =
 			subsfile_list_init(storage, path);
 		if (ctx->subsfile_ctx == NULL) {
-			i_free(ctx);
-			return NULL;
+			ctx->next = mbox_list_next;
+			return &ctx->mailbox_ctx;
 		}
 		ctx->glob = imap_match_init(default_pool, mask, TRUE, '/');
-		ctx->list_pool = pool_alloconly_create("mbox_list", 1024);
 		return &ctx->mailbox_ctx;
 	}
 
 	/* if we're matching only subdirectories, don't bother scanning the
 	   parent directories */
-	virtual_path = mask_get_dir(storage, mask);
+	virtual_path = mask_get_dir(mask);
 
 	path = mbox_get_path(istorage, virtual_path);
 	if (list_opendir(storage, path, TRUE, &dirp) < 0)
-		return NULL;
+		return &ctx->mailbox_ctx;
 	/* if user gave invalid directory, we just don't show any results. */
 
-	ctx = i_new(struct mbox_list_context, 1);
-	ctx->mailbox_ctx.storage = storage;
-	ctx->istorage = istorage;
 	ctx->flags = flags;
 	ctx->glob = imap_match_init(default_pool, mask, TRUE, '/');
-	ctx->list_pool = pool_alloconly_create("mbox_list", 1024);
-	ctx->prefix = storage->namespace == NULL ? "" :
-		mbox_fix_mailbox_name(istorage, storage->namespace, FALSE);
 
-	if (virtual_path == NULL && imap_match(ctx->glob, "INBOX") > 0)
-		ctx->next = mbox_list_inbox;
-	else if (virtual_path != NULL && dirp != NULL)
+	if (virtual_path != NULL && dirp != NULL)
 		ctx->next = mbox_list_path;
-	else
-		ctx->next = mbox_list_next;
 
 	if (dirp != NULL) {
 		ctx->dir = i_new(struct list_dir_context, 1);
 		ctx->dir->dirp = dirp;
 		ctx->dir->real_path = i_strdup(path);
-		ctx->dir->virtual_path = virtual_path == NULL ? NULL :
-			i_strconcat(ctx->prefix, virtual_path, NULL);
+		ctx->dir->virtual_path = i_strdup(virtual_path);
 	}
 	return &ctx->mailbox_ctx;
 }
@@ -253,7 +236,7 @@
 
 	/* check the mask */
 	if (ctx->dir->virtual_path == NULL)
-		list_path = t_strconcat(ctx->prefix, fname, NULL);
+		list_path = fname;
 	else {
 		list_path = t_strconcat(ctx->dir->virtual_path,
 					"/", fname, NULL);
@@ -303,12 +286,7 @@
 		} else if (ret < 0)
 			return -1;
 		return match > 0 || match2 > 0;
-	} else if (match > 0 &&
-		   strcmp(real_path, ctx->istorage->inbox_path) != 0 &&
-		   strcasecmp(list_path, "INBOX") != 0) {
-		/* don't match any INBOX here, it's added separately.
-		   we might also have ~/mail/inbox, ~/mail/Inbox etc.
-		   Just ignore them for now. */
+	} else if (match > 0) {
 		ctx->list.flags = noselect ? MAILBOX_NOSELECT :
 			(MAILBOX_NOINFERIORS | STAT_GET_MARKED(st));
 		ctx->list.name = p_strdup(ctx->list_pool, list_path);
@@ -318,24 +296,6 @@
 	return 0;
 }
 
-static struct mailbox_list *list_fix_name(struct mbox_list_context *ctx)
-{
-	char *p, *str, sep;
-
-	if (strchr(ctx->list.name, '/') != NULL) {
-		str = p_strdup(ctx->list_pool, ctx->list.name);
-		ctx->list.name = str;
-
-		sep = ctx->mailbox_ctx.storage->hierarchy_sep;
-		for (p = str; *p != '\0'; p++) {
-			if (*p == '/')
-				*p = sep;
-		}
-	}
-
-	return &ctx->list;
-}
-
 static struct mailbox_list *mbox_list_subs(struct mbox_list_context *ctx)
 {
 	struct stat st;
@@ -362,19 +322,17 @@
 			if (imap_match(ctx->glob, name) > 0) {
 				p_clear(ctx->list_pool);
 				ctx->list.name = p_strdup(ctx->list_pool, name);
-				return list_fix_name(ctx);
+				return &ctx->list;
 			}
 		}
 		i_unreached();
 	}
 
-        (void)list_fix_name(ctx);
 	if ((ctx->flags & MAILBOX_LIST_FAST_FLAGS) != 0)
 		return &ctx->list;
 
 	t_push();
-	name = mbox_fix_mailbox_name(ctx->istorage, ctx->list.name, TRUE);
-	path = mbox_get_path(ctx->istorage, name);
+	path = mbox_get_path(ctx->istorage, ctx->list.name);
 	if (stat(path, &st) == 0) {
 		if (S_ISDIR(st.st_mode))
 			ctx->list.flags = MAILBOX_NOSELECT | MAILBOX_CHILDREN;
@@ -383,48 +341,22 @@
 				STAT_GET_MARKED(st);
 		}
 	} else {
-		if (strcasecmp(ctx->list.name, "INBOX") == 0)
-			ctx->list.flags = MAILBOX_UNMARKED;
-		else
-			ctx->list.flags = MAILBOX_NONEXISTENT;
+		ctx->list.flags = MAILBOX_NONEXISTENT;
 	}
 	t_pop();
 	return &ctx->list;
 }
 
-static struct mailbox_list *mbox_list_inbox(struct mbox_list_context *ctx)
-{
-	struct stat st;
-
-	if (ctx->dir != NULL && ctx->dir->virtual_path != NULL)
-		ctx->next = mbox_list_path;
-	else
-		ctx->next = mbox_list_next;
-
-	/* INBOX exists always, even if the file doesn't. */
-	ctx->list.flags = strncmp(ctx->prefix, "INBOX/", 6) == 0 ?
-		MAILBOX_CHILDREN : MAILBOX_NOINFERIORS;
-	if ((ctx->flags & MAILBOX_LIST_FAST_FLAGS) == 0) {
-		if (stat(ctx->istorage->inbox_path, &st) < 0)
-			ctx->list.flags |= MAILBOX_UNMARKED;
-		else
-			ctx->list.flags |= STAT_GET_MARKED(st);
-	}
-
-	ctx->list.name = "INBOX";
-	return &ctx->list;
-}
-
 static struct mailbox_list *mbox_list_path(struct mbox_list_context *ctx)
 {
 	ctx->next = mbox_list_next;
 
 	ctx->list.flags = MAILBOX_NOSELECT | MAILBOX_CHILDREN;
-	ctx->list.name = p_strconcat(ctx->list_pool, ctx->prefix,
-				     ctx->dir->virtual_path, "/", NULL);
+	ctx->list.name =
+		p_strconcat(ctx->list_pool, ctx->dir->virtual_path, "/", NULL);
 
 	if (imap_match(ctx->glob, ctx->list.name) > 0)
-		return list_fix_name(ctx);
+		return &ctx->list;
 	else
 		return ctx->next(ctx);
 }
@@ -445,7 +377,7 @@
 			t_pop();
 
 			if (ret > 0)
-				return list_fix_name(ctx);
+				return &ctx->list;
 			if (ret < 0) {
 				ctx->failed = TRUE;
 				return NULL;
@@ -460,9 +392,3 @@
 	/* finished */
 	return NULL;
 }
-
-static struct mailbox_list *
-mbox_list_none(struct mbox_list_context *ctx __attr_unused__)
-{
-	return NULL;
-}
--- a/src/lib-storage/index/mbox/mbox-storage.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Fri Jul 23 00:20:00 2004 +0300
@@ -150,9 +150,7 @@
 	return path;
 }
 
-static struct mail_storage *
-mbox_create(const char *data, const char *user,
-	    const char *namespace, char hierarchy_sep)
+static struct mail_storage *mbox_create(const char *data, const char *user)
 {
 	struct index_storage *storage;
 	const char *root_dir, *inbox_file, *index_dir, *p;
@@ -224,10 +222,6 @@
 	storage = i_new(struct index_storage, 1);
 	storage->storage = mbox_storage;
 
-	if (hierarchy_sep != '\0')
-		storage->storage.hierarchy_sep = hierarchy_sep;
-	storage->storage.namespace = i_strdup(namespace);
-
 	storage->dir = i_strdup(home_expand(root_dir));
 	storage->inbox_path = i_strdup(home_expand(inbox_file));
 	storage->index_dir = i_strdup(home_expand(index_dir));
@@ -251,47 +245,6 @@
 	i_free(storage);
 }
 
-const char *mbox_fix_mailbox_name(struct index_storage *istorage,
-				  const char *name, int remove_namespace)
-{
-        struct mail_storage *storage = &istorage->storage;
-	char *dup, *p, sep;
-	size_t len;
-
-	if (strncasecmp(name, "INBOX", 5) == 0 &&
-	    (name[5] == '\0' || name[5] == storage->hierarchy_sep)) {
-		name = t_strconcat("INBOX", name+5, NULL);
-		if (name[5] == '\0') {
-			/* don't check namespace with INBOX */
-			return name;
-		}
-	}
-
-	if (storage->namespace != NULL && remove_namespace) {
-		len = strlen(storage->namespace);
-		if (strncmp(storage->namespace, name, len) != 0) {
-			i_panic("mbox: expecting namespace '%s' in name '%s'",
-				storage->namespace, name);
-		}
-		name += len;
-	}
-
-	if (*name == '/' && full_filesystem_access)
-		return name;
-
-	sep = storage->hierarchy_sep;
-	if (sep == '/')
-		return name;
-
-	dup = t_strdup_noconst(name);
-	for (p = dup; *p != '\0'; p++) {
-		if (*p == sep)
-			*p = '/';
-	}
-
-	return dup;
-}
-
 int mbox_is_valid_mask(const char *mask)
 {
 	const char *p;
@@ -390,8 +343,8 @@
 	if (fd != -1)
 		(void)close(fd);
 	else if (errno != EEXIST) {
-		mail_storage_set_critical(storage,
-			"open(%s, O_CREAT) failed: %m", storage->inbox_file);
+		mail_storage_set_critical(&storage->storage,
+			"open(%s, O_CREAT) failed: %m", storage->inbox_path);
 	}
 
 	/* make sure the index directories exist */
@@ -404,7 +357,7 @@
 static const char *
 mbox_get_path(struct index_storage *storage, const char *name)
 {
-	if (strcasecmp(name, "INBOX") == 0)
+	if (strcmp(name, "INBOX") == 0)
 		return storage->inbox_path;
 	if (full_filesystem_access && (*name == '/' || *name == '~'))
 		return home_expand(name);
@@ -434,7 +387,7 @@
 	const char *path, *index_dir;
 	uint32_t mbox_extra_idx;
 
-	if (strcasecmp(name, "INBOX") == 0) {
+	if (strcmp(name, "INBOX") == 0) {
 		/* name = "INBOX"
 		   path = "<inbox_file>/INBOX"
 		   index_dir = "/mail/.imap/INBOX" */
@@ -487,11 +440,8 @@
 
 	mail_storage_clear_error(_storage);
 
-	name = mbox_fix_mailbox_name(storage, name, TRUE);
-
-	/* INBOX is always case-insensitive */
-	if (strcasecmp(name, "INBOX") == 0) {
-		/* make sure inbox exists */
+	if (strcmp(name, "INBOX") == 0) {
+		/* make sure INBOX exists */
 		if (verify_inbox(storage) < 0)
 			return NULL;
 		return mbox_open(storage, "INBOX", flags);
@@ -538,8 +488,6 @@
 
 	mail_storage_clear_error(_storage);
 
-	name = mbox_fix_mailbox_name(storage, name, TRUE);
-
 	if (!mbox_is_valid_create_name(name)) {
 		mail_storage_set_error(_storage, "Invalid mailbox name");
 		return -1;
@@ -607,9 +555,7 @@
 
 	mail_storage_clear_error(_storage);
 
-	name = mbox_fix_mailbox_name(storage, name, TRUE);
-
-	if (strcasecmp(name, "INBOX") == 0) {
+	if (strcmp(name, "INBOX") == 0) {
 		mail_storage_set_error(_storage, "INBOX can't be deleted.");
 		return -1;
 	}
@@ -701,9 +647,6 @@
 
 	mail_storage_clear_error(_storage);
 
-	oldname = mbox_fix_mailbox_name(storage, oldname, TRUE);
-	newname = mbox_fix_mailbox_name(storage, newname, TRUE);
-
 	if (!mbox_is_valid_existing_name(oldname) ||
 	    !mbox_is_valid_create_name(newname)) {
 		mail_storage_set_error(_storage, "Invalid mailbox name");
@@ -780,7 +723,6 @@
 	const char *path;
 
 	path = t_strconcat(storage->dir, "/" SUBSCRIPTION_FILE_NAME, NULL);
-	name = mbox_fix_mailbox_name(storage, name, FALSE);
 	return subsfile_set_subscribed(_storage, path, storage->temp_prefix,
 				       name, set);
 }
@@ -795,8 +737,6 @@
 
 	mail_storage_clear_error(_storage);
 
-	name = mbox_fix_mailbox_name(storage, name, TRUE);
-
 	if (!mbox_is_valid_existing_name(name)) {
 		*status = MAILBOX_NAME_INVALID;
 		return 0;
@@ -853,9 +793,8 @@
 
 struct mail_storage mbox_storage = {
 	"mbox", /* name */
-	NULL, /* namespace */
 
-	'/', /* default hierarchy separator */
+	'/', /* hierarchy separator */
 
 	mbox_create,
 	mbox_free,
--- a/src/lib-storage/index/mbox/mbox-storage.h	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.h	Fri Jul 23 00:20:00 2004 +0300
@@ -24,7 +24,8 @@
 int mbox_set_syscall_error(struct index_mailbox *ibox, const char *function);
 
 struct mailbox_list_context *
-mbox_mailbox_list_init(struct mail_storage *storage, const char *mask,
+mbox_mailbox_list_init(struct mail_storage *storage,
+		       const char *ref, const char *mask,
 		       enum mailbox_list_flags flags);
 int mbox_mailbox_list_deinit(struct mailbox_list_context *ctx);
 struct mailbox_list *mbox_mailbox_list_next(struct mailbox_list_context *ctx);
@@ -45,8 +46,6 @@
 int mbox_save_commit(struct mbox_save_context *ctx);
 void mbox_save_rollback(struct mbox_save_context *ctx);
 
-const char *mbox_fix_mailbox_name(struct index_storage *istorage,
-				  const char *name, int remove_namespace);
 int mbox_is_valid_mask(const char *mask);
 
 #endif
--- a/src/lib-storage/mail-storage-private.h	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/mail-storage-private.h	Fri Jul 23 00:20:00 2004 +0300
@@ -5,12 +5,9 @@
 
 struct mail_storage {
 	char *name;
-	char *namespace;
 	char hierarchy_sep;
 
-	struct mail_storage *(*create)(const char *data, const char *user,
-				       const char *namespace,
-				       char hierarchy_sep);
+	struct mail_storage *(*create)(const char *data, const char *user);
 	void (*destroy)(struct mail_storage *storage);
 
 	int (*autodetect)(const char *data);
@@ -31,7 +28,7 @@
 
 	struct mailbox_list_context *
 		(*mailbox_list_init)(struct mail_storage *storage,
-				     const char *mask,
+				     const char *ref, const char *mask,
 				     enum mailbox_list_flags flags);
 	struct mailbox_list *
 		(*mailbox_list_next)(struct mailbox_list_context *ctx);
--- a/src/lib-storage/mail-storage.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/mail-storage.c	Fri Jul 23 00:20:00 2004 +0300
@@ -69,33 +69,28 @@
 }
 
 struct mail_storage *
-mail_storage_create(const char *name, const char *data, const char *user,
-		    const char *namespace, char hierarchy_sep)
+mail_storage_create(const char *name, const char *data, const char *user)
 {
 	struct mail_storage_list *list;
 
 	i_assert(name != NULL);
 
 	for (list = storages; list != NULL; list = list->next) {
-		if (strcasecmp(list->storage->name, name) == 0) {
-			return list->storage->create(data, user,
-						     namespace, hierarchy_sep);
-		}
+		if (strcasecmp(list->storage->name, name) == 0)
+			return list->storage->create(data, user);
 	}
 
 	return NULL;
 }
 
 struct mail_storage *
-mail_storage_create_default(const char *user,
-			    const char *namespace, char hierarchy_sep)
+mail_storage_create_default(const char *user)
 {
 	struct mail_storage_list *list;
 	struct mail_storage *storage;
 
 	for (list = storages; list != NULL; list = list->next) {
-		storage = list->storage->create(NULL, user, namespace,
-						hierarchy_sep);
+		storage = list->storage->create(NULL, user);
 		if (storage != NULL)
 			return storage;
 	}
@@ -116,16 +111,13 @@
 }
 
 struct mail_storage *
-mail_storage_create_with_data(const char *data, const char *user,
-			      const char *namespace, char hierarchy_sep)
+mail_storage_create_with_data(const char *data, const char *user)
 {
 	struct mail_storage *storage;
 	const char *p, *name;
 
-	if (data == NULL || *data == '\0') {
-		return mail_storage_create_default(user, namespace,
-						   hierarchy_sep);
-	}
+	if (data == NULL || *data == '\0')
+		return mail_storage_create_default(user);
 
 	/* check if we're in the form of mailformat:data
 	   (eg. maildir:Maildir) */
@@ -134,14 +126,11 @@
 
 	if (*p == ':') {
 		name = t_strdup_until(data, p);
-		storage = mail_storage_create(name, p+1, user,
-					      namespace, hierarchy_sep);
+		storage = mail_storage_create(name, p+1, user);
 	} else {
 		storage = mail_storage_autodetect(data);
-		if (storage != NULL) {
-			storage = storage->create(data, user,
-						  namespace, hierarchy_sep);
-		}
+		if (storage != NULL)
+			storage = storage->create(data, user);
 	}
 
 	return storage;
@@ -260,10 +249,10 @@
 
 struct mailbox_list_context *
 mail_storage_mailbox_list_init(struct mail_storage *storage,
-			       const char *mask,
+			       const char *ref, const char *mask,
 			       enum mailbox_list_flags flags)
 {
-	return storage->mailbox_list_init(storage, mask, flags);
+	return storage->mailbox_list_init(storage, ref, mask, flags);
 }
 
 struct mailbox_list *
--- a/src/lib-storage/mail-storage.h	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/mail-storage.h	Fri Jul 23 00:20:00 2004 +0300
@@ -167,16 +167,12 @@
    If namespace is non-NULL, all mailbox names are expected to begin with it.
    hierarchy_sep overrides the default separator if it's not '\0'. */
 struct mail_storage *
-mail_storage_create(const char *name, const char *data, const char *user,
-		    const char *namespace, char hierarchy_sep);
+mail_storage_create(const char *name, const char *data, const char *user);
 void mail_storage_destroy(struct mail_storage *storage);
 
+struct mail_storage *mail_storage_create_default(const char *user);
 struct mail_storage *
-mail_storage_create_default(const char *user,
-			    const char *namespace, char hierarchy_sep);
-struct mail_storage *
-mail_storage_create_with_data(const char *data, const char *user,
-			      const char *namespace, char hierarchy_sep);
+mail_storage_create_with_data(const char *data, const char *user);
 
 char mail_storage_get_hierarchy_sep(struct mail_storage *storage);
 
@@ -205,11 +201,11 @@
 				const char *oldname, const char *newname);
 
 /* Initialize new mailbox list request. mask may contain '%' and '*'
-   wildcards as defined in RFC2060. Matching against "INBOX" is
+   wildcards as defined in RFC3501. Matching against "INBOX" is
    case-insensitive, but anything else is not. */
 struct mailbox_list_context *
 mail_storage_mailbox_list_init(struct mail_storage *storage,
-			       const char *mask,
+			       const char *ref, const char *mask,
 			       enum mailbox_list_flags flags);
 /* Get next mailbox. Returns the mailbox name */
 struct mailbox_list *
@@ -259,8 +255,7 @@
 int mailbox_allow_new_keywords(struct mailbox *box);
 
 /* Gets the mailbox status information. */
-int mailbox_get_status(struct mailbox *box,
-		       enum mailbox_status_items items,
+int mailbox_get_status(struct mailbox *box, enum mailbox_status_items items,
 		       struct mailbox_status *status);
 
 /* Synchronize the mailbox. */
--- a/src/lib-storage/proxy-mail-storage.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/lib-storage/proxy-mail-storage.c	Fri Jul 23 00:20:00 2004 +0300
@@ -52,12 +52,13 @@
 }
 
 static struct mailbox_list_context *
-_mailbox_list_init(struct mail_storage *storage, const char *mask,
+_mailbox_list_init(struct mail_storage *storage,
+		   const char *ref, const char *mask,
 		   enum mailbox_list_flags flags)
 {
 	struct proxy_mail_storage *s = (struct proxy_mail_storage *) storage;
 
-	return s->storage->mailbox_list_init(s->storage, mask, flags);
+	return s->storage->mailbox_list_init(s->storage, ref, mask, flags);
 }
 
 static int _set_subscribed(struct mail_storage *storage,
--- a/src/pop3/main.c	Thu Jul 22 22:37:25 2004 +0300
+++ b/src/pop3/main.c	Fri Jul 23 00:20:00 2004 +0300
@@ -130,8 +130,7 @@
 	}
         parse_workarounds();
 
-	storage = mail_storage_create_with_data(mail, getenv("USER"),
-						NULL, '\0');
+	storage = mail_storage_create_with_data(mail, getenv("USER"));
 	if (storage == NULL) {
 		/* failed */
 		if (mail != NULL && *mail != '\0')