Mercurial > dovecot > core-2.2
changeset 625:fe017093e4d8 HEAD
Don't allow '*' and '%' characters in mailbox names. Maildir RENAME works
now properly when renaming folders having subfolders.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 20 Nov 2002 18:03:36 +0200 |
parents | 8bc4876397cd |
children | 5ce5aafe28d9 |
files | src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/mbox/mbox-storage.c |
diffstat | 2 files changed, 62 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-storage.c Wed Nov 20 16:59:11 2002 +0200 +++ b/src/lib-storage/index/maildir/maildir-storage.c Wed Nov 20 18:03:36 2002 +0200 @@ -13,6 +13,12 @@ #define CREATE_MODE 0770 /* umask() should limit it more */ +typedef struct { + int found; + size_t oldnamelen; + const char *newname; +} RenameContext; + extern MailStorage maildir_storage; extern Mailbox maildir_mailbox; @@ -68,7 +74,9 @@ static int maildir_is_valid_name(MailStorage *storage, const char *name) { return name[0] != '\0' && name[0] != storage->hierarchy_sep && - strchr(name, '/') == NULL && strchr(name, '\\') == NULL; + name[strlen(name)-1] != storage->hierarchy_sep && + strchr(name, '/') == NULL && strchr(name, '\\') == NULL && + strchr(name, '*') == NULL && strchr(name, '%') == NULL; } /* create or fix maildir, ignore if it already exists */ @@ -309,10 +317,39 @@ return TRUE; } +static void rename_subfolder(MailStorage *storage, const char *name, + MailboxFlags flags __attr_unused__, void *context) +{ + RenameContext *ctx = context; + char oldpath[1024], newpath[1024]; + + i_assert(ctx->oldnamelen <= strlen(name)); + + i_snprintf(oldpath, sizeof(oldpath), "%s/.%s", storage->dir, name); + i_snprintf(newpath, sizeof(newpath), "%s/.%s.%s", + storage->dir, ctx->newname, name + ctx->oldnamelen); + + /* FIXME: it's possible to merge two folders if either one of them + doesn't have existing root folder. We could check this but I'm not + sure if it's worth it. It could be even considered as a feature. + + Anyway, the bug with merging is that if both folders have + identically named subfolder they conflict. Just ignore those and + leave them under the old folder. */ + if (rename(oldpath, newpath) == 0 || errno == EEXIST) + ctx->found = TRUE; + else { + mail_storage_set_critical(storage, "rename(%s, %s) failed: %m", + oldpath, newpath); + } +} + static int maildir_rename_mailbox(MailStorage *storage, const char *oldname, const char *newname) { + RenameContext ctx; char oldpath[1024], newpath[1024]; + int ret; mail_storage_clear_error(storage); @@ -325,12 +362,31 @@ /* NOTE: renaming INBOX works just fine with us, it's simply created the next time it's needed. Only problem with it is that it's not - atomic operation but that can't be really helped. */ + atomic operation but that can't be really helped. + + NOTE: is't possible to rename a nonexisting folder which has + subfolders. In that case we should ignore the rename() error. */ i_snprintf(oldpath, sizeof(oldpath), "%s/.%s", storage->dir, oldname); i_snprintf(newpath, sizeof(newpath), "%s/.%s", storage->dir, newname); - if (rename(oldpath, newpath) == 0) { + + ret = rename(oldpath, newpath); + if (ret == 0 || (errno == ENOENT && strcmp(oldname, "INBOX") != 0)) { if (strcmp(oldname, "INBOX") == 0) return move_inbox_data(storage, newpath); + + ctx.found = ret == 0; + ctx.oldnamelen = strlen(oldname)+1; + ctx.newname = newname; + if (!maildir_find_mailboxes(storage, + t_strconcat(oldname, ".*", NULL), + rename_subfolder, &ctx)) + return FALSE; + + if (!ctx.found) { + mail_storage_set_error(storage, + "Mailbox doesn't exist"); + return FALSE; + } return TRUE; }
--- a/src/lib-storage/index/mbox/mbox-storage.c Wed Nov 20 16:59:11 2002 +0200 +++ b/src/lib-storage/index/mbox/mbox-storage.c Wed Nov 20 18:03:36 2002 +0200 @@ -91,7 +91,9 @@ const char *p; int newdir; - if (name[0] == '\0' || name[0] == storage->hierarchy_sep) + if (name[0] == '\0' || name[0] == storage->hierarchy_sep || + name[strlen(name)-1] == storage->hierarchy_sep || + strchr(name, '*') != NULL || strchr(name, '%') != NULL) return FALSE; /* make sure there's no "../" or "..\" stuff */