[dovecot-cvs] dovecot/src/imap cmd-append.c, 1.38, 1.39 cmd-copy.c, 1.21, 1.22 cmd-create.c, 1.8, 1.9 cmd-delete.c, 1.6, 1.7 cmd-list.c, 1.35, 1.36 cmd-namespace.c, 1.2, 1.3 cmd-rename.c, 1.6, 1.7 cmd-select.c, 1.28, 1.29 cmd-status.c, 1.18, 1.19 cmd-subscribe.c, 1.9, 1.10 commands-util.c, 1.33, 1.34 commands-util.h, 1.15, 1.16 namespace.c, 1.4, 1.5 namespace.h, 1.3, 1.4

cras at dovecot.org cras at dovecot.org
Fri Jul 23 00:20:03 EEST 2004


Update of /home/cvs/dovecot/src/imap
In directory talvi:/tmp/cvs-serv11339/imap

Modified Files:
	cmd-append.c cmd-copy.c cmd-create.c cmd-delete.c cmd-list.c 
	cmd-namespace.c cmd-rename.c cmd-select.c cmd-status.c 
	cmd-subscribe.c commands-util.c commands-util.h namespace.c 
	namespace.h 
Log Message:
Moved namespace and hierarchy separator handling to imap-specific code. LIST
now shows non-hidden namespaces in the LIST reply.



Index: cmd-append.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-append.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- cmd-append.c	21 Jun 2004 14:51:04 -0000	1.38
+++ cmd-append.c	22 Jul 2004 21:20:00 -0000	1.39
@@ -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;
 

Index: cmd-copy.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-copy.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- cmd-copy.c	21 Jun 2004 14:51:04 -0000	1.21
+++ cmd-copy.c	22 Jul 2004 21:20:00 -0000	1.22
@@ -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;
 

Index: cmd-create.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-create.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- cmd-create.c	27 Apr 2004 20:25:52 -0000	1.8
+++ cmd-create.c	22 Jul 2004 21:20:00 -0000	1.9
@@ -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;
 

Index: cmd-delete.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-delete.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- cmd-delete.c	27 Apr 2004 20:25:52 -0000	1.6
+++ cmd-delete.c	22 Jul 2004 21:20:00 -0000	1.7
@@ -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;
 	}

Index: cmd-list.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-list.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- cmd-list.c	27 Apr 2004 20:25:52 -0000	1.35
+++ cmd-list.c	22 Jul 2004 21:20:00 -0000	1.36
@@ -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;
 }
 

Index: cmd-namespace.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-namespace.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- cmd-namespace.c	15 Sep 2003 14:02:07 -0000	1.2
+++ cmd-namespace.c	22 Jul 2004 21:20:00 -0000	1.3
@@ -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, "\")");
 		}
 

Index: cmd-rename.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-rename.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- cmd-rename.c	27 Apr 2004 20:25:52 -0000	1.6
+++ cmd-rename.c	22 Jul 2004 21:20:00 -0000	1.7
@@ -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;
 

Index: cmd-select.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-select.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- cmd-select.c	12 Jul 2004 11:35:50 -0000	1.28
+++ cmd-select.c	22 Jul 2004 21:20:00 -0000	1.29
@@ -24,7 +24,7 @@
 		}
 	}
 
-	storage = client_find_storage(client, mailbox);
+	storage = client_find_storage(client, &mailbox);
 	if (storage == NULL)
 		return TRUE;
 

Index: cmd-status.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-status.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- cmd-status.c	12 Jul 2004 11:35:50 -0000	1.18
+++ cmd-status.c	22 Jul 2004 21:20:00 -0000	1.19
@@ -102,7 +102,7 @@
 		return TRUE;
 	}
 
-	storage = client_find_storage(client, mailbox);
+	storage = client_find_storage(client, &mailbox);
 	if (storage == NULL)
 		return FALSE;
 

Index: cmd-subscribe.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/cmd-subscribe.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cmd-subscribe.c	10 May 2004 16:12:39 -0000	1.9
+++ cmd-subscribe.c	22 Jul 2004 21:20:00 -0000	1.10
@@ -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;
 

Index: commands-util.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/commands-util.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- commands-util.c	12 Jul 2004 11:35:50 -0000	1.33
+++ commands-util.c	22 Jul 2004 21:20:00 -0000	1.34
@@ -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;
 

Index: commands-util.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/commands-util.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- commands-util.h	20 Jun 2004 03:25:33 -0000	1.15
+++ commands-util.h	22 Jul 2004 21:20:00 -0000	1.16
@@ -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

Index: namespace.c
===================================================================
RCS file: /home/cvs/dovecot/src/imap/namespace.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- namespace.c	27 Apr 2004 20:25:52 -0000	1.4
+++ namespace.c	22 Jul 2004 21:20:00 -0000	1.5
@@ -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 @@
 	}
 }
 
+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)
+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;

Index: namespace.h
===================================================================
RCS file: /home/cvs/dovecot/src/imap/namespace.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- namespace.h	15 Sep 2003 14:02:07 -0000	1.3
+++ namespace.h	22 Jul 2004 21:20:00 -0000	1.4
@@ -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



More information about the dovecot-cvs mailing list