[dovecot-cvs] dovecot/src/lib-storage/index/mbox mbox-list.c,1.21,1.22 mbox-storage.c,1.62,1.63 mbox-storage.h,1.17,1.18

cras at procontrol.fi cras at procontrol.fi
Sun Jul 27 07:12:16 EEST 2003


Update of /home/cvs/dovecot/src/lib-storage/index/mbox
In directory danu:/tmp/cvs-serv23650/lib-storage/index/mbox

Modified Files:
	mbox-list.c mbox-storage.c mbox-storage.h 
Log Message:
Mail storages support now configurable namespace prefix and hierarchy
separator. Subscription file handling needs some more thought.



Index: mbox-list.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-list.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- mbox-list.c	26 Jul 2003 23:53:05 -0000	1.21
+++ mbox-list.c	27 Jul 2003 03:12:13 -0000	1.22
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2003 Timo Sirainen */
 
 #include "lib.h"
 #include "unlink-directory.h"
@@ -30,6 +30,7 @@
 	struct mail_storage *storage;
 	enum mailbox_list_flags flags;
 
+	const char *prefix;
 	struct imap_match_glob *glob;
 	struct subsfile_list_context *subsfile_ctx;
 
@@ -46,10 +47,20 @@
 static struct mailbox_list *mbox_list_inbox(struct mailbox_list_context *ctx);
 static struct mailbox_list *mbox_list_path(struct mailbox_list_context *ctx);
 static struct mailbox_list *mbox_list_next(struct mailbox_list_context *ctx);
+static struct mailbox_list *mbox_list_none(struct mailbox_list_context *ctx);
 
-static const char *mask_get_dir(const char *mask)
+static const char *mask_get_dir(struct mail_storage *storage, 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++) {
@@ -104,14 +115,24 @@
 	const char *path, *virtual_path;
 	DIR *dirp;
 
+	mail_storage_clear_error(storage);
+
+	if (storage->hierarchy_sep != '/' && strchr(mask, '/') != NULL) {
+		/* this will never match, return nothing */
+		ctx = i_new(struct mailbox_list_context, 1);
+		ctx->storage = storage;
+                ctx->next = mbox_list_none;
+		return ctx;
+	}
+
+	mask = mbox_fix_mailbox_name(storage, 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;
 	}
 
-	mail_storage_clear_error(storage);
-
 	if ((flags & MAILBOX_LIST_SUBSCRIBED) != 0) {
 		ctx = i_new(struct mailbox_list_context, 1);
 		ctx->storage = storage;
@@ -123,17 +144,17 @@
 			return NULL;
 		}
 		ctx->glob = imap_match_init(default_pool, mask, TRUE, '/');
+		ctx->list_pool = pool_alloconly_create("mbox_list", 1024);
 		return ctx;
 	}
 
 	/* if we're matching only subdirectories, don't bother scanning the
 	   parent directories */
-	virtual_path = mask_get_dir(mask);
+	virtual_path = mask_get_dir(storage, mask);
 
 	path = mbox_get_path(storage, virtual_path);
 	if (list_opendir(storage, path, TRUE, &dirp) < 0)
 		return NULL;
-
 	/* if user gave invalid directory, we just don't show any results. */
 
 	ctx = i_new(struct mailbox_list_context, 1);
@@ -141,6 +162,8 @@
 	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(storage, storage->namespace, FALSE);
 
 	if (virtual_path == NULL && imap_match(ctx->glob, "INBOX") > 0)
 		ctx->next = mbox_list_inbox;
@@ -153,7 +176,8 @@
 		ctx->dir = i_new(struct list_dir_context, 1);
 		ctx->dir->dirp = dirp;
 		ctx->dir->real_path = i_strdup(path);
-		ctx->dir->virtual_path = i_strdup(virtual_path);
+		ctx->dir->virtual_path = virtual_path == NULL ? NULL :
+			i_strconcat(ctx->prefix, virtual_path, NULL);
 	}
 	return ctx;
 }
@@ -184,7 +208,8 @@
 
 	if (ctx->list_pool != NULL)
 		pool_unref(ctx->list_pool);
-	imap_match_deinit(ctx->glob);
+	if (ctx->glob != NULL)
+		imap_match_deinit(ctx->glob);
 	i_free(ctx);
 
 	return !failed;
@@ -216,7 +241,7 @@
 
 	/* check the mask */
 	if (ctx->dir->virtual_path == NULL)
-		list_path = fname;
+		list_path = t_strconcat(ctx->prefix, fname, NULL);
 	else {
 		list_path = t_strconcat(ctx->dir->virtual_path,
 					"/", fname, NULL);
@@ -280,6 +305,24 @@
 	return 0;
 }
 
+static struct mailbox_list *list_fix_name(struct mailbox_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->storage->hierarchy_sep;
+		for (p = str; *p != '\0'; p++) {
+			if (*p == '/')
+				*p = sep;
+		}
+	}
+
+	return &ctx->list;
+}
+
 static struct mailbox_list *mbox_list_subs(struct mailbox_list_context *ctx)
 {
 	struct stat st;
@@ -304,18 +347,21 @@
 		while ((p = strrchr(name, '/')) != NULL) {
 			name = t_strdup_until(name, p);
 			if (imap_match(ctx->glob, name) > 0) {
-				ctx->list.name = name;
-				return &ctx->list;
+				p_clear(ctx->list_pool);
+				ctx->list.name = p_strdup(ctx->list_pool, name);
+				return list_fix_name(ctx);
 			}
 		}
 		i_unreached();
 	}
 
+        (void)list_fix_name(ctx);
 	if ((ctx->flags & MAILBOX_LIST_FAST_FLAGS) != 0)
 		return &ctx->list;
 
 	t_push();
-	path = mbox_get_path(ctx->storage, ctx->list.name);
+	name = mbox_fix_mailbox_name(ctx->storage, ctx->list.name, TRUE);
+	path = mbox_get_path(ctx->storage, name);
 	if (stat(path, &st) == 0) {
 		if (S_ISDIR(st.st_mode))
 			ctx->list.flags = MAILBOX_NOSELECT | MAILBOX_CHILDREN;
@@ -343,7 +389,8 @@
 		ctx->next = mbox_list_next;
 
 	/* INBOX exists always, even if the file doesn't. */
-	ctx->list.flags = MAILBOX_NOINFERIORS;
+	ctx->list.flags = strncmp(ctx->prefix, "INBOX/", 6) == 0 ?
+		MAILBOX_CHILDREN : MAILBOX_NOINFERIORS;
 	if ((ctx->flags & MAILBOX_LIST_FAST_FLAGS) == 0) {
 		if (stat(ctx->storage->inbox_file, &st) < 0)
 			ctx->list.flags |= MAILBOX_UNMARKED;
@@ -360,11 +407,11 @@
 	ctx->next = mbox_list_next;
 
 	ctx->list.flags = MAILBOX_NOSELECT | MAILBOX_CHILDREN;
-	ctx->list.name = p_strconcat(ctx->list_pool,
+	ctx->list.name = p_strconcat(ctx->list_pool, ctx->prefix,
 				     ctx->dir->virtual_path, "/", NULL);
 
 	if (imap_match(ctx->glob, ctx->list.name) > 0)
-		return &ctx->list;
+		return list_fix_name(ctx);
 	else
 		return ctx->next(ctx);
 }
@@ -385,7 +432,7 @@
 			t_pop();
 
 			if (ret > 0)
-				return &ctx->list;
+				return list_fix_name(ctx);
 			if (ret < 0) {
 				ctx->failed = TRUE;
 				return NULL;
@@ -398,5 +445,11 @@
 	}
 
 	/* finished */
+	return NULL;
+}
+
+static struct mailbox_list *
+mbox_list_none(struct mailbox_list_context *ctx __attr_unused__)
+{
 	return NULL;
 }

Index: mbox-storage.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-storage.c,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -d -r1.62 -r1.63
--- mbox-storage.c	26 Jul 2003 16:55:12 -0000	1.62
+++ mbox-storage.c	27 Jul 2003 03:12:13 -0000	1.63
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Timo Sirainen */
+/* Copyright (C) 2002-2003 Timo Sirainen */
 
 #include "lib.h"
 #include "home-expand.h"
@@ -126,7 +126,9 @@
 	return path;
 }
 
-static struct mail_storage *mbox_create(const char *data, const char *user)
+static struct mail_storage *
+mbox_create(const char *data, const char *user,
+	    const char *namespace, char hierarchy_sep)
 {
 	struct mail_storage *storage;
 	const char *root_dir, *inbox_file, *index_dir, *p;
@@ -187,6 +189,10 @@
 	storage = i_new(struct mail_storage, 1);
 	memcpy(storage, &mbox_storage, sizeof(struct mail_storage));
 
+	if (hierarchy_sep != '\0')
+		storage->hierarchy_sep = hierarchy_sep;
+	storage->namespace = i_strdup(namespace);
+
 	storage->dir = i_strdup(home_expand(root_dir));
 	storage->inbox_file = i_strdup(home_expand(inbox_file));
 	storage->index_dir = i_strdup(home_expand(index_dir));
@@ -200,6 +206,7 @@
 {
 	index_storage_deinit(storage);
 
+	i_free(storage->namespace);
 	i_free(storage->dir);
 	i_free(storage->inbox_file);
 	i_free(storage->index_dir);
@@ -209,6 +216,46 @@
 	i_free(storage);
 }
 
+const char *mbox_fix_mailbox_name(struct mail_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->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;
@@ -218,25 +265,26 @@
 		return TRUE;
 
 	/* make sure it's not absolute path */
-	if (*mask == '/' || *mask == '\\' || *mask == '~')
+	if (*mask == '/' || *mask == '~')
 		return FALSE;
 
-	/* make sure there's no "../" or "..\" stuff */
+	/* make sure there's no "../" stuff */
 	newdir = TRUE;
 	for (p = mask; *p != '\0'; p++) {
-		if (newdir && p[0] == '.' && p[1] == '.' &&
-		    (p[2] == '/' || p[2] == '\\'))
+		if (newdir && p[0] == '.' && p[1] == '.' && p[2] == '/')
 			return FALSE;
-		newdir = p[0] == '/' || p[0] == '\\';
+		newdir = p[0] == '/';
 	}
 
 	return TRUE;
 }
 
-static int mbox_is_valid_create_name(struct mail_storage *storage,
-				     const char *name)
+static int mbox_is_valid_create_name(const char *name)
 {
-	if (name[0] == '\0' || name[strlen(name)-1] == storage->hierarchy_sep ||
+	size_t len;
+
+	len = strlen(name);
+	if (name[0] == '\0' || name[len-1] == '/' ||
 	    strchr(name, '*') != NULL || strchr(name, '%') != NULL)
 		return FALSE;
 
@@ -367,6 +415,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 */
@@ -413,10 +463,9 @@
 
 	mail_storage_clear_error(storage);
 
-	if (strcasecmp(name, "INBOX") == 0)
-		name = "INBOX";
+	name = mbox_fix_mailbox_name(storage, name, TRUE);
 
-	if (!mbox_is_valid_create_name(storage, name)) {
+	if (!mbox_is_valid_create_name(name)) {
 		mail_storage_set_error(storage, "Invalid mailbox name");
 		return FALSE;
 	}
@@ -482,6 +531,8 @@
 
 	mail_storage_clear_error(storage);
 
+	name = mbox_fix_mailbox_name(storage, name, TRUE);
+
 	if (strcasecmp(name, "INBOX") == 0) {
 		mail_storage_set_error(storage, "INBOX can't be deleted.");
 		return FALSE;
@@ -573,15 +624,15 @@
 
 	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(storage, newname)) {
+	    !mbox_is_valid_create_name(newname)) {
 		mail_storage_set_error(storage, "Invalid mailbox name");
 		return FALSE;
 	}
 
-	if (strcasecmp(oldname, "INBOX") == 0)
-		oldname = "INBOX";
-
 	oldpath = mbox_get_path(storage, oldname);
 	newpath = mbox_get_path(storage, newname);
 
@@ -640,6 +691,13 @@
 	return TRUE;
 }
 
+static int mbox_set_subscribed(struct mail_storage *storage,
+			       const char *name, int set)
+{
+	name = mbox_fix_mailbox_name(storage, name, FALSE);
+	return subsfile_set_subscribed(storage, name, set);
+}
+
 static int mbox_get_mailbox_name_status(struct mail_storage *storage,
 					const char *name,
 					enum mailbox_name_status *status)
@@ -649,8 +707,7 @@
 
 	mail_storage_clear_error(storage);
 
-	if (strcasecmp(name, "INBOX") == 0)
-		name = "INBOX";
+	name = mbox_fix_mailbox_name(storage, name, TRUE);
 
 	if (!mbox_is_valid_existing_name(name)) {
 		*status = MAILBOX_NAME_INVALID;
@@ -663,7 +720,7 @@
 		return TRUE;
 	}
 
-	if (!mbox_is_valid_create_name(storage, name)) {
+	if (!mbox_is_valid_create_name(name)) {
 		*status = MAILBOX_NAME_INVALID;
 		return TRUE;
 	}
@@ -748,8 +805,9 @@
 
 struct mail_storage mbox_storage = {
 	"mbox", /* name */
+	NULL, /* namespace */
 
-	'/', /* hierarchy_sep - can't be changed */
+	'/', /* default hierarchy separator */
 
 	mbox_create,
 	mbox_free,
@@ -762,7 +820,7 @@
 	mbox_list_mailbox_init,
 	mbox_list_mailbox_deinit,
 	mbox_list_mailbox_next,
-	subsfile_set_subscribed,
+	mbox_set_subscribed,
 	mbox_get_mailbox_name_status,
 	mail_storage_get_last_error,
 

Index: mbox-storage.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib-storage/index/mbox/mbox-storage.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- mbox-storage.h	26 Jul 2003 23:53:05 -0000	1.17
+++ mbox-storage.h	27 Jul 2003 03:12:13 -0000	1.18
@@ -28,6 +28,8 @@
 int mbox_storage_expunge(struct mail *mail, struct mail_expunge_context *ctx,
 			 unsigned int *seq_r, int notify);
 
+const char *mbox_fix_mailbox_name(struct mail_storage *storage,
+				  const char *name, int remove_namespace);
 int mbox_is_valid_mask(const char *mask);
 
 #endif



More information about the dovecot-cvs mailing list