From: Timo Sirainen Date: Mon, 6 Sep 2010 18:07:49 +0000 (+0100) Subject: maildir: Moved maildir_filename_flags_*() to a separate file. X-Git-Tag: 2.1.alpha1~466 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6fe91298731abf0b70dfd796ecc30d3be81fa5d1;p=thirdparty%2Fdovecot%2Fcore.git maildir: Moved maildir_filename_flags_*() to a separate file. --- diff --git a/src/lib-storage/index/maildir/Makefile.am b/src/lib-storage/index/maildir/Makefile.am index d155d55a0f..7acf2496d1 100644 --- a/src/lib-storage/index/maildir/Makefile.am +++ b/src/lib-storage/index/maildir/Makefile.am @@ -12,6 +12,7 @@ AM_CPPFLAGS = \ libstorage_maildir_la_SOURCES = \ maildir-copy.c \ maildir-filename.c \ + maildir-filename-flags.c \ maildir-keywords.c \ maildir-mail.c \ maildir-save.c \ @@ -24,6 +25,7 @@ libstorage_maildir_la_SOURCES = \ headers = \ maildir-filename.h \ + maildir-filename-flags.h \ maildir-keywords.h \ maildir-storage.h \ maildir-settings.h \ diff --git a/src/lib-storage/index/maildir/maildir-filename-flags.c b/src/lib-storage/index/maildir/maildir-filename-flags.c new file mode 100644 index 0000000000..409958a31c --- /dev/null +++ b/src/lib-storage/index/maildir/maildir-filename-flags.c @@ -0,0 +1,172 @@ +/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "str.h" +#include "maildir-storage.h" +#include "maildir-keywords.h" +#include "maildir-filename-flags.h" + +#include + +void maildir_filename_flags_get(struct maildir_keywords_sync_ctx *ctx, + const char *fname, enum mail_flags *flags_r, + ARRAY_TYPE(keyword_indexes) *keywords_r) +{ + const char *info; + + array_clear(keywords_r); + *flags_r = 0; + + info = strrchr(fname, MAILDIR_INFO_SEP); + if (info == NULL || info[1] != '2' || info[2] != MAILDIR_FLAGS_SEP) + return; + + for (info += 3; *info != '\0' && *info != MAILDIR_FLAGS_SEP; info++) { + switch (*info) { + case 'R': /* replied */ + *flags_r |= MAIL_ANSWERED; + break; + case 'S': /* seen */ + *flags_r |= MAIL_SEEN; + break; + case 'T': /* trashed */ + *flags_r |= MAIL_DELETED; + break; + case 'D': /* draft */ + *flags_r |= MAIL_DRAFT; + break; + case 'F': /* flagged */ + *flags_r |= MAIL_FLAGGED; + break; + default: + if (*info >= MAILDIR_KEYWORD_FIRST && + *info <= MAILDIR_KEYWORD_LAST) { + int idx; + + idx = maildir_keywords_char_idx(ctx, *info); + if (idx < 0) { + /* unknown keyword. */ + break; + } + + array_append(keywords_r, + (unsigned int *)&idx, 1); + break; + } + + /* unknown flag - ignore */ + break; + } + } +} + +static int char_cmp(const void *p1, const void *p2) +{ + const unsigned char *c1 = p1, *c2 = p2; + + return *c1 - *c2; +} + +static void +maildir_filename_append_keywords(struct maildir_keywords_sync_ctx *ctx, + ARRAY_TYPE(keyword_indexes) *keywords, + string_t *fname) +{ + const unsigned int *indexes; + unsigned int i, count, start = str_len(fname); + char chr; + + indexes = array_get(keywords, &count); + for (i = 0; i < count; i++) { + chr = maildir_keywords_idx_char(ctx, indexes[i]); + if (chr != '\0') + str_append_c(fname, chr); + } + + qsort(str_c_modifiable(fname) + start, str_len(fname) - start, 1, + char_cmp); +} + +const char *maildir_filename_flags_set(struct maildir_keywords_sync_ctx *ctx, + const char *fname, enum mail_flags flags, + ARRAY_TYPE(keyword_indexes) *keywords) +{ + string_t *flags_str; + enum mail_flags flags_left; + const char *info, *oldflags; + int nextflag; + + /* remove the old :info from file name, and get the old flags */ + info = strrchr(fname, MAILDIR_INFO_SEP); + if (info != NULL && strrchr(fname, '/') > info) + info = NULL; + + oldflags = ""; + if (info != NULL) { + fname = t_strdup_until(fname, info); + if (info[1] == '2' && info[2] == MAILDIR_FLAGS_SEP) + oldflags = info+3; + } + + /* insert the new flags between old flags. flags must be sorted by + their ASCII code. unknown flags are kept. */ + flags_str = t_str_new(256); + str_append(flags_str, fname); + str_append(flags_str, MAILDIR_FLAGS_FULL_SEP); + flags_left = flags; + for (;;) { + /* skip all known flags */ + while (*oldflags == 'D' || *oldflags == 'F' || + *oldflags == 'R' || *oldflags == 'S' || + *oldflags == 'T' || + (*oldflags >= MAILDIR_KEYWORD_FIRST && + *oldflags <= MAILDIR_KEYWORD_LAST)) + oldflags++; + + nextflag = *oldflags == '\0' || *oldflags == MAILDIR_FLAGS_SEP ? + 256 : (unsigned char) *oldflags; + + if ((flags_left & MAIL_DRAFT) && nextflag > 'D') { + str_append_c(flags_str, 'D'); + flags_left &= ~MAIL_DRAFT; + } + if ((flags_left & MAIL_FLAGGED) && nextflag > 'F') { + str_append_c(flags_str, 'F'); + flags_left &= ~MAIL_FLAGGED; + } + if ((flags_left & MAIL_ANSWERED) && nextflag > 'R') { + str_append_c(flags_str, 'R'); + flags_left &= ~MAIL_ANSWERED; + } + if ((flags_left & MAIL_SEEN) && nextflag > 'S') { + str_append_c(flags_str, 'S'); + flags_left &= ~MAIL_SEEN; + } + if ((flags_left & MAIL_DELETED) && nextflag > 'T') { + str_append_c(flags_str, 'T'); + flags_left &= ~MAIL_DELETED; + } + + if (keywords != NULL && array_is_created(keywords) && + nextflag > MAILDIR_KEYWORD_FIRST) { + maildir_filename_append_keywords(ctx, keywords, + flags_str); + keywords = NULL; + } + + if (*oldflags == '\0' || *oldflags == MAILDIR_FLAGS_SEP) + break; + + str_append_c(flags_str, *oldflags); + oldflags++; + } + + if (*oldflags == MAILDIR_FLAGS_SEP) { + /* another flagset, we don't know about these, just keep them */ + while (*oldflags != '\0') + str_append_c(flags_str, *oldflags++); + } + + return str_c(flags_str); +} diff --git a/src/lib-storage/index/maildir/maildir-filename-flags.h b/src/lib-storage/index/maildir/maildir-filename-flags.h new file mode 100644 index 0000000000..0270476b79 --- /dev/null +++ b/src/lib-storage/index/maildir/maildir-filename-flags.h @@ -0,0 +1,12 @@ +#ifndef MAILDIR_FILENAME_FLAGS_H +#define MAILDIR_FILENAME_FLAGS_H + +void maildir_filename_flags_get(struct maildir_keywords_sync_ctx *ctx, + const char *fname, enum mail_flags *flags_r, + ARRAY_TYPE(keyword_indexes) *keywords_r); + +const char *maildir_filename_flags_set(struct maildir_keywords_sync_ctx *ctx, + const char *fname, enum mail_flags flags, + ARRAY_TYPE(keyword_indexes) *keywords); + +#endif diff --git a/src/lib-storage/index/maildir/maildir-filename.c b/src/lib-storage/index/maildir/maildir-filename.c index 7836e8294b..95c65158c0 100644 --- a/src/lib-storage/index/maildir/maildir-filename.c +++ b/src/lib-storage/index/maildir/maildir-filename.c @@ -2,16 +2,11 @@ #include "lib.h" #include "ioloop.h" -#include "array.h" -#include "str.h" #include "time-util.h" #include "hostpid.h" #include "maildir-storage.h" -#include "maildir-keywords.h" #include "maildir-filename.h" -#include - const char *maildir_filename_generate(void) { static struct timeval last_tv = { 0, 0 }; @@ -34,168 +29,6 @@ const char *maildir_filename_generate(void) my_pid, my_hostname); } -void maildir_filename_get_flags(struct maildir_keywords_sync_ctx *ctx, - const char *fname, enum mail_flags *flags_r, - ARRAY_TYPE(keyword_indexes) *keywords_r) -{ - const char *info; - - array_clear(keywords_r); - *flags_r = 0; - - info = strrchr(fname, MAILDIR_INFO_SEP); - if (info == NULL || info[1] != '2' || info[2] != MAILDIR_FLAGS_SEP) - return; - - for (info += 3; *info != '\0' && *info != MAILDIR_FLAGS_SEP; info++) { - switch (*info) { - case 'R': /* replied */ - *flags_r |= MAIL_ANSWERED; - break; - case 'S': /* seen */ - *flags_r |= MAIL_SEEN; - break; - case 'T': /* trashed */ - *flags_r |= MAIL_DELETED; - break; - case 'D': /* draft */ - *flags_r |= MAIL_DRAFT; - break; - case 'F': /* flagged */ - *flags_r |= MAIL_FLAGGED; - break; - default: - if (*info >= MAILDIR_KEYWORD_FIRST && - *info <= MAILDIR_KEYWORD_LAST) { - int idx; - - idx = maildir_keywords_char_idx(ctx, *info); - if (idx < 0) { - /* unknown keyword. */ - break; - } - - array_append(keywords_r, - (unsigned int *)&idx, 1); - break; - } - - /* unknown flag - ignore */ - break; - } - } -} - -static int char_cmp(const void *p1, const void *p2) -{ - const unsigned char *c1 = p1, *c2 = p2; - - return *c1 - *c2; -} - -static void -maildir_filename_append_keywords(struct maildir_keywords_sync_ctx *ctx, - ARRAY_TYPE(keyword_indexes) *keywords, - string_t *fname) -{ - const unsigned int *indexes; - unsigned int i, count, start = str_len(fname); - char chr; - - indexes = array_get(keywords, &count); - for (i = 0; i < count; i++) { - chr = maildir_keywords_idx_char(ctx, indexes[i]); - if (chr != '\0') - str_append_c(fname, chr); - } - - qsort(str_c_modifiable(fname) + start, str_len(fname) - start, 1, - char_cmp); -} - -const char *maildir_filename_set_flags(struct maildir_keywords_sync_ctx *ctx, - const char *fname, enum mail_flags flags, - ARRAY_TYPE(keyword_indexes) *keywords) -{ - string_t *flags_str; - enum mail_flags flags_left; - const char *info, *oldflags; - int nextflag; - - /* remove the old :info from file name, and get the old flags */ - info = strrchr(fname, MAILDIR_INFO_SEP); - if (info != NULL && strrchr(fname, '/') > info) - info = NULL; - - oldflags = ""; - if (info != NULL) { - fname = t_strdup_until(fname, info); - if (info[1] == '2' && info[2] == MAILDIR_FLAGS_SEP) - oldflags = info+3; - } - - /* insert the new flags between old flags. flags must be sorted by - their ASCII code. unknown flags are kept. */ - flags_str = t_str_new(256); - str_append(flags_str, fname); - str_append(flags_str, MAILDIR_FLAGS_FULL_SEP); - flags_left = flags; - for (;;) { - /* skip all known flags */ - while (*oldflags == 'D' || *oldflags == 'F' || - *oldflags == 'R' || *oldflags == 'S' || - *oldflags == 'T' || - (*oldflags >= MAILDIR_KEYWORD_FIRST && - *oldflags <= MAILDIR_KEYWORD_LAST)) - oldflags++; - - nextflag = *oldflags == '\0' || *oldflags == MAILDIR_FLAGS_SEP ? - 256 : (unsigned char) *oldflags; - - if ((flags_left & MAIL_DRAFT) && nextflag > 'D') { - str_append_c(flags_str, 'D'); - flags_left &= ~MAIL_DRAFT; - } - if ((flags_left & MAIL_FLAGGED) && nextflag > 'F') { - str_append_c(flags_str, 'F'); - flags_left &= ~MAIL_FLAGGED; - } - if ((flags_left & MAIL_ANSWERED) && nextflag > 'R') { - str_append_c(flags_str, 'R'); - flags_left &= ~MAIL_ANSWERED; - } - if ((flags_left & MAIL_SEEN) && nextflag > 'S') { - str_append_c(flags_str, 'S'); - flags_left &= ~MAIL_SEEN; - } - if ((flags_left & MAIL_DELETED) && nextflag > 'T') { - str_append_c(flags_str, 'T'); - flags_left &= ~MAIL_DELETED; - } - - if (keywords != NULL && array_is_created(keywords) && - nextflag > MAILDIR_KEYWORD_FIRST) { - maildir_filename_append_keywords(ctx, keywords, - flags_str); - keywords = NULL; - } - - if (*oldflags == '\0' || *oldflags == MAILDIR_FLAGS_SEP) - break; - - str_append_c(flags_str, *oldflags); - oldflags++; - } - - if (*oldflags == MAILDIR_FLAGS_SEP) { - /* another flagset, we don't know about these, just keep them */ - while (*oldflags != '\0') - str_append_c(flags_str, *oldflags++); - } - - return str_c(flags_str); -} - bool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r) { uoff_t size = 0; diff --git a/src/lib-storage/index/maildir/maildir-filename.h b/src/lib-storage/index/maildir/maildir-filename.h index 5cde36a98c..1c3807def6 100644 --- a/src/lib-storage/index/maildir/maildir-filename.h +++ b/src/lib-storage/index/maildir/maildir-filename.h @@ -5,14 +5,6 @@ struct maildir_keywords_sync_ctx; const char *maildir_filename_generate(void); -void maildir_filename_get_flags(struct maildir_keywords_sync_ctx *ctx, - const char *fname, enum mail_flags *flags_r, - ARRAY_TYPE(keyword_indexes) *keywords_r); - -const char *maildir_filename_set_flags(struct maildir_keywords_sync_ctx *ctx, - const char *fname, enum mail_flags flags, - ARRAY_TYPE(keyword_indexes) *keywords); - bool maildir_filename_get_size(const char *fname, char type, uoff_t *size_r); unsigned int maildir_filename_base_hash(const void *p); diff --git a/src/lib-storage/index/maildir/maildir-save.c b/src/lib-storage/index/maildir/maildir-save.c index d97222f173..b6a83d6aec 100644 --- a/src/lib-storage/index/maildir/maildir-save.c +++ b/src/lib-storage/index/maildir/maildir-save.c @@ -15,6 +15,7 @@ #include "maildir-uidlist.h" #include "maildir-keywords.h" #include "maildir-filename.h" +#include "maildir-filename-flags.h" #include "maildir-sync.h" #include @@ -268,7 +269,7 @@ maildir_get_dest_filename(struct maildir_save_context *ctx, return TRUE; } - *fname_r = maildir_filename_set_flags(NULL, basename, + *fname_r = maildir_filename_flags_set(NULL, basename, mf->flags & MAIL_FLAGS_MASK, NULL); return FALSE; } @@ -276,7 +277,7 @@ maildir_get_dest_filename(struct maildir_save_context *ctx, i_assert(ctx->keywords_sync_ctx != NULL || mf->keywords_count == 0); buffer_create_const_data(&ctx->keywords_buffer, mf + 1, mf->keywords_count * sizeof(unsigned int)); - *fname_r = maildir_filename_set_flags(ctx->keywords_sync_ctx, basename, + *fname_r = maildir_filename_flags_set(ctx->keywords_sync_ctx, basename, mf->flags & MAIL_FLAGS_MASK, &ctx->keywords_array); return FALSE; diff --git a/src/lib-storage/index/maildir/maildir-sync-index.c b/src/lib-storage/index/maildir/maildir-sync-index.c index f9764b9ab8..9eec9d3a51 100644 --- a/src/lib-storage/index/maildir/maildir-sync-index.c +++ b/src/lib-storage/index/maildir/maildir-sync-index.c @@ -8,7 +8,7 @@ #include "index-sync-changes.h" #include "maildir-uidlist.h" #include "maildir-keywords.h" -#include "maildir-filename.h" +#include "maildir-filename-flags.h" #include "maildir-sync.h" #include @@ -123,7 +123,7 @@ static int maildir_sync_flags(struct maildir_mailbox *mbox, const char *path, i_assert(*fname != '\0'); /* get the current flags and keywords */ - maildir_filename_get_flags(ctx->keywords_sync_ctx, + maildir_filename_flags_get(ctx->keywords_sync_ctx, fname, &ctx->flags, &ctx->keywords); /* apply changes */ @@ -133,7 +133,7 @@ static int maildir_sync_flags(struct maildir_mailbox *mbox, const char *path, ctx->flags = flags8; /* and try renaming with the new name */ - newfname = maildir_filename_set_flags(ctx->keywords_sync_ctx, fname, + newfname = maildir_filename_flags_set(ctx->keywords_sync_ctx, fname, ctx->flags, &ctx->keywords); newpath = t_strconcat(dir, newfname, NULL); if (strcmp(path, newpath) == 0) { @@ -497,7 +497,7 @@ int maildir_sync_index(struct maildir_index_sync_context *ctx, i_array_init(&ctx->idx_keywords, MAILDIR_MAX_KEYWORDS); iter = maildir_uidlist_iter_init(mbox->uidlist); while (maildir_uidlist_iter_next(iter, &uid, &uflags, &filename)) { - maildir_filename_get_flags(ctx->keywords_sync_ctx, filename, + maildir_filename_flags_get(ctx->keywords_sync_ctx, filename, &ctx->flags, &ctx->keywords); i_assert(uid > prev_uid); diff --git a/src/lib-storage/index/maildir/maildir-util.c b/src/lib-storage/index/maildir/maildir-util.c index 685d95c8b9..8df24d33db 100644 --- a/src/lib-storage/index/maildir/maildir-util.c +++ b/src/lib-storage/index/maildir/maildir-util.c @@ -9,7 +9,7 @@ #include "maildir-storage.h" #include "maildir-uidlist.h" #include "maildir-keywords.h" -#include "maildir-filename.h" +#include "maildir-filename-flags.h" #include "maildir-sync.h" #include @@ -41,12 +41,12 @@ maildir_filename_guess(struct maildir_mailbox *mbox, uint32_t uid, mail_index_lookup_view_flags(view, seq, &flags, &keywords); if (array_count(&keywords) == 0) { *have_flags_r = (flags & MAIL_FLAGS_NONRECENT) != 0; - fname = maildir_filename_set_flags(NULL, fname, flags, NULL); + fname = maildir_filename_flags_set(NULL, fname, flags, NULL); } else { *have_flags_r = TRUE; kw_ctx = maildir_keywords_sync_init_readonly(mbox->keywords, mbox->box.index); - fname = maildir_filename_set_flags(kw_ctx, fname, + fname = maildir_filename_flags_set(kw_ctx, fname, flags, &keywords); maildir_keywords_sync_deinit(&kw_ctx); }