By Jan Srzednicki

diff -ruN dovecot-1.0.2.orig/src/lib-storage/index/maildir/maildir-list.c dovecot-1.0.2/src/lib-storage/index/maildir/maildir-list.c
--- dovecot-1.0.2.orig/src/lib-storage/index/maildir/maildir-list.c	Sat May 19 13:14:04 2007
+++ dovecot-1.0.2/src/lib-storage/index/maildir/maildir-list.c	Sat Aug  4 11:43:17 2007
@@ -58,7 +58,8 @@
 	string_t *mailbox;
 	enum imap_match_result match;
 	struct mailbox_node *node;
-	bool stat_dirs, created, hide;
+	bool stat_dirs, created, hide, prefix_subfolders;
+	int prefix_subfolders_int;
 
 	dirp = opendir(ctx->dir);
 	if (dirp == NULL) {
@@ -72,12 +73,18 @@
 
 	stat_dirs = getenv("MAILDIR_STAT_DIRS") != NULL;
 
+	prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL;
+	if ( prefix_subfolders )
+		prefix_subfolders_int = 1;
+	else
+		prefix_subfolders_int = 0;
+
 	t_push();
 	mailbox = t_str_new(PATH_MAX);
 	while ((d = readdir(dirp)) != NULL) {
 		const char *fname = d->d_name;
 
-		if (fname[0] != MAILDIR_FS_SEP)
+		if (prefix_subfolders && fname[0] != MAILDIR_FS_SEP)
 			continue;
 
 		/* skip . and .. */
@@ -106,8 +113,8 @@
 				continue;
 		}
 
-		if (fname[1] == MAILDIR_FS_SEP &&
-		    strcmp(fname+1, MAILDIR_UNLINK_DIRNAME) == 0) {
+		if (fname[prefix_subfolders_int] == MAILDIR_FS_SEP &&
+		    strcmp(fname+prefix_subfolders_int, MAILDIR_UNLINK_DIRNAME) == 0) {
 			/* this directory is in the middle of being deleted,
 			   or the process trying to delete it had died.
 			   delete it ourself if it's been there longer than
@@ -120,7 +127,8 @@
 			t_pop();
 			continue;
 		}
-		fname++;
+		if (prefix_subfolders)
+			fname++;
 
 		/* make sure the mask matches */
 		str_truncate(mailbox, 0);
@@ -143,6 +151,11 @@
 				if (imap_match(glob, mailbox_c) > 0)
 					break;
 			}
+			if (! prefix_subfolders && p == NULL &&
+					(p = strrchr(mailbox_c, '/')) != NULL ) {
+				str_truncate(mailbox, (size_t) (p-mailbox_c));
+				mailbox_c = str_c(mailbox);
+			}
 			i_assert(p != NULL);
 
 			created = FALSE;
@@ -217,7 +230,9 @@
 	struct subsfile_list_context *subsfile_ctx;
 	const char *path, *name, *p;
 	struct mailbox_node *node;
-	bool created;
+	bool created, prefix_subfolders;
+
+	prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL;
 
 	path = t_strconcat(storage->control_dir != NULL ?
 			   storage->control_dir : INDEX_STORAGE(storage)->dir,
@@ -244,6 +259,10 @@
 				if (imap_match(glob, name) > 0)
 					break;
 			}
+			if (! prefix_subfolders && p == NULL &&
+					(p = strrchr(name, '/')) != NULL )
+				name = t_strdup_until(name, p);
+
 			i_assert(p != NULL);
 
 			node = mailbox_tree_get(ctx->tree_ctx, name, &created);
diff -ruN dovecot-1.0.2.orig/src/lib-storage/index/maildir/maildir-storage.c dovecot-1.0.2/src/lib-storage/index/maildir/maildir-storage.c
--- dovecot-1.0.2.orig/src/lib-storage/index/maildir/maildir-storage.c	Wed May 30 14:16:28 2007
+++ dovecot-1.0.2/src/lib-storage/index/maildir/maildir-storage.c	Sat Aug  4 11:43:24 2007
@@ -26,6 +26,7 @@
 
 #define MAILDIR_SUBFOLDER_FILENAME "maildirfolder"
 
+
 struct rename_context {
 	bool found;
 	size_t oldnamelen;
@@ -279,6 +280,17 @@
 static const char *maildir_get_absolute_path(const char *name)
 {
 	const char *p;
+	bool prefix_subfolders;
+	char *separator;
+
+	prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL;
+
+	if (prefix_subfolders && unlink)
+		separator = MAILDIR_FS_SEP_S MAILDIR_FS_SEP_S;
+	else if (prefix_subfolders || unlink)
+		separator = MAILDIR_FS_SEP_S;
+	else
+		separator = "";
 
 	if (home_try_expand(&name) < 0) {
 		/* fallback to using as ~name */
@@ -289,11 +301,15 @@
 	if (p == NULL)
 		return name;
 	return t_strconcat(t_strdup_until(name, p+1),
-			   MAILDIR_FS_SEP_S, p+1, NULL);
+			   separator, p+1, NULL);
 }
 
 const char *maildir_get_path(struct index_storage *storage, const char *name)
 {
+	bool prefix_subfolders;
+
+	prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL;
+
 	if ((storage->storage.flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
 	    (*name == '/' || *name == '~'))
 		return maildir_get_absolute_path(name);
@@ -303,7 +319,8 @@
 			storage->inbox_path : storage->dir;
 	}
 
-	return t_strconcat(storage->dir, "/"MAILDIR_FS_SEP_S, name, NULL);
+	return t_strconcat(storage->dir, prefix_subfolders ? "/"MAILDIR_FS_SEP_S :
+			"/", name, NULL);
 }
 
 static const char *
@@ -319,6 +336,10 @@
 static const char *maildir_get_index_path(struct index_storage *storage,
 					  const char *name)
 {
+	bool prefix_subfolders;
+
+	prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL;
+
 	if (storage->index_dir == NULL)
 		return NULL;
 
@@ -330,12 +351,17 @@
 	    (*name == '/' || *name == '~'))
 		return maildir_get_absolute_path(name);
 
-	return t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, name, NULL);
+	return t_strconcat(storage->index_dir,
+			prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/", name, NULL);
 }
 
 static const char *maildir_get_control_path(struct maildir_storage *storage,
 					    const char *name)
 {
+	bool prefix_subfolders;
+
+	prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL;
+	
 	if (storage->control_dir == NULL)
 		return maildir_get_path(INDEX_STORAGE(storage), name);
 
@@ -343,8 +369,9 @@
 	    (*name == '/' || *name == '~'))
 		return maildir_get_absolute_path(name);
 
-	return t_strconcat(storage->control_dir, "/"MAILDIR_FS_SEP_S,
-			   name, NULL);
+	return t_strconcat(storage->control_dir,
+			prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/",
+			name, NULL);
 }
 
 static int mkdir_verify(struct index_storage *storage,
@@ -412,8 +439,11 @@
 
 static int create_index_dir(struct index_storage *storage, const char *name)
 {
+	bool prefix_subfolders;
 	const char *dir;
 
+	prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL;
+	
 	if (storage->index_dir == NULL)
 		return 0;
 
@@ -422,7 +452,8 @@
 	     strcmp(storage->index_dir, storage->inbox_path) == 0))
 		return 0;
 
-	dir = t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, name, NULL);
+	dir = t_strconcat(storage->index_dir,
+			prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/", name, NULL);
 	if (mkdir_parents(dir, CREATE_MODE) < 0 && errno != EEXIST) {
 		if (!ENOSPACE(errno)) {
 			mail_storage_set_critical(&storage->storage,
@@ -437,11 +468,14 @@
 static int create_control_dir(struct maildir_storage *storage, const char *name)
 {
 	const char *dir;
+	bool prefix_subfolders;
+
+	prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL;
 
 	if (storage->control_dir == NULL)
 		return 0;
 
-	dir = t_strconcat(storage->control_dir, "/"MAILDIR_FS_SEP_S,
+	dir = t_strconcat(storage->control_dir, prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/",
 			  name, NULL);
 	if (mkdir_parents(dir, CREATE_MODE) < 0 && errno != EEXIST) {
 		mail_storage_set_critical(STORAGE(storage),
@@ -733,6 +767,9 @@
 	struct stat st;
 	const char *src, *dest, *index_dir, *control_dir;
 	int count;
+	bool prefix_subfolders;
+
+	prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL;
 
 	mail_storage_clear_error(_storage);
 
@@ -766,7 +803,7 @@
 	if (storage->index_dir != NULL && dest != NULL &&
 	    strcmp(storage->index_dir, storage->dir) != 0) {
 		index_dir = t_strconcat(storage->index_dir,
-					"/"MAILDIR_FS_SEP_S, name, NULL);
+				prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/", name, NULL);
 		if (unlink_directory(index_dir, TRUE) < 0 &&
 		    errno != ENOTEMPTY) {
 			mail_storage_set_critical(_storage,
@@ -863,16 +900,21 @@
 			  const char *oldname, const char *newname)
 {
 	const char *oldpath, *newpath;
+	bool prefix_subfolders;
+
+	prefix_subfolders = getenv("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR") != NULL;
 
 	if (storage->index_dir == NULL ||
 	    strcmp(storage->index_dir, storage->dir) == 0)
 		return 0;
 
 	/* Rename it's index. */
-	oldpath = t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S,
-			      oldname, NULL);
-	newpath = t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S,
-			      newname, NULL);
+	oldpath = t_strconcat(storage->index_dir,
+			prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/",
+			oldname, NULL);
+	newpath = t_strconcat(storage->index_dir,
+			prefix_subfolders ? "/"MAILDIR_FS_SEP_S :"/",
+			newname, NULL);
 
 	if (rename(oldpath, newpath) < 0 && errno != ENOENT) {
 		mail_storage_set_critical(&storage->storage,
diff -ruN dovecot-1.0.2.orig/src/master/mail-process.c dovecot-1.0.2/src/master/mail-process.c
--- dovecot-1.0.2.orig/src/master/mail-process.c	Tue Jun 12 19:14:08 2007
+++ dovecot-1.0.2/src/master/mail-process.c	Sat Aug  4 11:22:11 2007
@@ -247,6 +247,8 @@
 		env_put("MAILDIR_STAT_DIRS=1");
 	if (set->maildir_copy_with_hardlinks)
 		env_put("MAILDIR_COPY_WITH_HARDLINKS=1");
+	if (set->maildir_prefix_subfolders_with_separator)
+		env_put("MAILDIR_PREFIX_SUBFOLDERS_WITH_SEPARATOR=1");
 	if (set->maildir_copy_preserve_filename)
 		env_put("MAILDIR_COPY_PRESERVE_FILENAME=1");
 	if (set->mail_debug)
diff -ruN dovecot-1.0.2.orig/src/master/master-settings-defs.c dovecot-1.0.2/src/master/master-settings-defs.c
--- dovecot-1.0.2.orig/src/master/master-settings-defs.c	Sat May 19 13:14:04 2007
+++ dovecot-1.0.2/src/master/master-settings-defs.c	Sat Aug  4 12:01:08 2007
@@ -77,6 +77,7 @@
 	DEF(SET_STR, lock_method),
 	DEF(SET_BOOL, maildir_stat_dirs),
 	DEF(SET_BOOL, maildir_copy_with_hardlinks),
+	DEF(SET_BOOL, maildir_prefix_subfolders_with_separator),
 	DEF(SET_BOOL, maildir_copy_preserve_filename),
 	DEF(SET_STR, mbox_read_locks),
 	DEF(SET_STR, mbox_write_locks),
diff -ruN dovecot-1.0.2.orig/src/master/master-settings.c dovecot-1.0.2/src/master/master-settings.c
--- dovecot-1.0.2.orig/src/master/master-settings.c	Wed Jul 11 00:40:40 2007
+++ dovecot-1.0.2/src/master/master-settings.c	Sat Aug  4 11:22:23 2007
@@ -230,6 +230,7 @@
 	MEMBER(lock_method) "fcntl",
 	MEMBER(maildir_stat_dirs) FALSE,
 	MEMBER(maildir_copy_with_hardlinks) FALSE,
+	MEMBER(maildir_prefix_subfolders_with_separator) TRUE,
 	MEMBER(maildir_copy_preserve_filename) FALSE,
 	MEMBER(mbox_read_locks) "fcntl",
 	MEMBER(mbox_write_locks) "dotlock fcntl",
diff -ruN dovecot-1.0.2.orig/src/master/master-settings.h dovecot-1.0.2/src/master/master-settings.h
--- dovecot-1.0.2.orig/src/master/master-settings.h	Tue Jun 12 18:42:52 2007
+++ dovecot-1.0.2/src/master/master-settings.h	Sat Aug  4 11:48:49 2007
@@ -85,6 +85,7 @@
 	const char *lock_method;
 	bool maildir_stat_dirs;
 	bool maildir_copy_with_hardlinks;
+	bool maildir_prefix_subfolders_with_separator;
 	bool maildir_copy_preserve_filename;
 	const char *mbox_read_locks;
 	const char *mbox_write_locks;
