libstorage_maildir_la_SOURCES = \
maildir-copy.c \
maildir-filename.c \
+ maildir-filename-flags.c \
maildir-keywords.c \
maildir-mail.c \
maildir-save.c \
headers = \
maildir-filename.h \
+ maildir-filename-flags.h \
maildir-keywords.h \
maildir-storage.h \
maildir-settings.h \
--- /dev/null
+/* 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 <stdlib.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 *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);
+}
--- /dev/null
+#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
#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 <stdlib.h>
-
const char *maildir_filename_generate(void)
{
static struct timeval last_tv = { 0, 0 };
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;
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);
#include "maildir-uidlist.h"
#include "maildir-keywords.h"
#include "maildir-filename.h"
+#include "maildir-filename-flags.h"
#include "maildir-sync.h"
#include <stdio.h>
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;
}
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;
#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 <stdio.h>
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 */
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) {
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);
#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 <stdio.h>
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);
}