[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