]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
API change for updating message flags.
authorTimo Sirainen <tss@iki.fi>
Wed, 23 Jul 2003 01:44:16 +0000 (04:44 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 23 Jul 2003 01:44:16 +0000 (04:44 +0300)
--HG--
branch : HEAD

18 files changed:
src/imap/client.h
src/imap/cmd-copy.c
src/imap/cmd-store.c
src/imap/imap-fetch.c
src/imap/imap-fetch.h
src/imap/mail-storage-callbacks.c
src/lib-imap/imap-util.c
src/lib-imap/imap-util.h
src/lib-storage/index/index-fetch.c
src/lib-storage/index/index-mail.c
src/lib-storage/index/index-mail.h
src/lib-storage/index/index-search.c
src/lib-storage/index/index-storage.h
src/lib-storage/index/index-sync.c
src/lib-storage/index/index-update-flags.c
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/mail-storage.h

index 495338b415a66c0c1f4dcde20bbfb001c485e31d..49ee80cd588b0ec83ea4564d838a059883c84e38 100644 (file)
@@ -39,7 +39,6 @@ struct client {
 
        unsigned int cmd_error:1;
        unsigned int cmd_uid:1; /* used UID command */
-       unsigned int sync_flags_send_uid:1;
        unsigned int rawlog:1;
        unsigned int input_skip_line:1; /* skip all the data until we've
                                           found a new line */
index 6be697700d6fb9d7e92f2815f27b51252a9b6fd1..5f799031c4cd12e4c789b1ca69b597e5e0af79b1 100644 (file)
@@ -12,7 +12,7 @@ static int fetch_and_copy(struct mail_copy_context *copy_ctx,
        int failed = FALSE;
 
        fetch_ctx = box->fetch_init(box, MAIL_FETCH_STREAM_HEADER |
-                                   MAIL_FETCH_STREAM_BODY, NULL,
+                                   MAIL_FETCH_STREAM_BODY, FALSE,
                                    messageset, uidset);
        if (fetch_ctx == NULL)
                return FALSE;
index 9cb639af0d70ca1a1d233b93ffdb0670b554baac..a7b4a4191646bbc1b9ab02ed016602120c8da0fe 100644 (file)
@@ -32,13 +32,37 @@ static int get_modify_type(struct client *client, const char *item,
        return TRUE;
 }
 
+static int mail_send_flags(struct client *client, struct mail *mail)
+{
+       const struct mail_full_flags *flags;
+       const char *str;
+
+       flags = mail->get_flags(mail);
+       if (flags == NULL)
+               return FALSE;
+
+       t_push();
+       str = imap_write_flags(flags);
+       str = t_strdup_printf(client->cmd_uid ?
+                             "* %u FETCH (FLAGS (%s) UID %u)" :
+                             "* %u FETCH (FLAGS (%s))",
+                             mail->seq, str, mail->uid);
+       client_send_line(client, str);
+       t_pop();
+
+       return TRUE;
+}
+
 int cmd_store(struct client *client)
 {
        struct imap_arg *args;
        struct mail_full_flags flags;
        enum modify_type modify_type;
+       struct mailbox *box;
+       struct mail_fetch_context *fetch_ctx;
+       struct mail *mail;
        const char *messageset, *item;
-       int silent, all_found;
+       int silent, all_found, failed;
 
        if (!client_read_args(client, 0, 0, &args))
                return FALSE;
@@ -70,10 +94,32 @@ int cmd_store(struct client *client)
        }
 
        /* and update the flags */
-       client->sync_flags_send_uid = client->cmd_uid;
-       if (client->mailbox->update_flags(client->mailbox, messageset,
-                                         client->cmd_uid, &flags,
-                                         modify_type, !silent, &all_found)) {
+       box = client->mailbox;
+       fetch_ctx = box->fetch_init(box, MAIL_FETCH_FLAGS, TRUE,
+                                   messageset, client->cmd_uid);
+       if (fetch_ctx == NULL)
+               failed = TRUE;
+       else {
+               failed = FALSE;
+               while ((mail = box->fetch_next(fetch_ctx)) != NULL) {
+                       if (!mail->update_flags(mail, &flags, modify_type)) {
+                               failed = TRUE;
+                               break;
+                       }
+
+                       if (!silent) {
+                               if (!mail_send_flags(client, mail)) {
+                                       failed = TRUE;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       if (!box->fetch_deinit(fetch_ctx, &all_found))
+               failed = TRUE;
+
+       if (!failed) {
                if (client->cmd_uid)
                        client_sync_full_fast(client);
                else
@@ -84,6 +130,5 @@ int cmd_store(struct client *client)
                client_send_storage_error(client);
        }
 
-       client->sync_flags_send_uid = FALSE;
        return TRUE;
 }
index b7c014053817e84c5870c734c3c45f04535dc5a2..59dcfd02390f5540245c68c7811286157378f6d0 100644 (file)
@@ -17,17 +17,16 @@ static void fetch_uid(struct imap_fetch_context *ctx, struct mail *mail)
        str_printfa(ctx->str, "UID %u ", mail->uid);
 }
 
-static int fetch_flags(struct imap_fetch_context *ctx, struct mail *mail)
+static int fetch_flags(struct imap_fetch_context *ctx, struct mail *mail,
+                      const struct mail_full_flags *flags)
 {
-       const struct mail_full_flags *flags;
-
-       flags = mail->get_flags(mail);
-       if (flags == NULL)
-               return FALSE;
+       if (flags == NULL) {
+               flags = mail->get_flags(mail);
+               if (flags == NULL)
+                       return FALSE;
+       }
 
-       str_printfa(ctx->str, "FLAGS (%s) ",
-                   imap_write_flags(flags->flags, flags->custom_flags,
-                                    flags->custom_flags_count));
+       str_printfa(ctx->str, "FLAGS (%s) ", imap_write_flags(flags));
        return TRUE;
 }
 
@@ -165,9 +164,27 @@ static int fetch_send_rfc822_text(struct imap_fetch_context *ctx,
 
 static int fetch_mail(struct imap_fetch_context *ctx, struct mail *mail)
 {
+       const struct mail_full_flags *flags;
        struct imap_fetch_body_data *body;
        size_t len, orig_len;
-       int failed, data_written;
+       int failed, data_written, seen_updated = FALSE;
+
+       if (!ctx->update_seen)
+               flags = NULL;
+       else {
+               flags = mail->get_flags(mail);
+               if (flags == NULL)
+                       return FALSE;
+
+               if ((flags->flags & MAIL_SEEN) == 0) {
+                       if (!mail->update_flags(mail, &ctx->seen_flag,
+                                               MODIFY_ADD))
+                               return FALSE;
+
+                       flags = NULL; /* \Seen won't update automatically */
+                       seen_updated = TRUE;
+               }
+       }
 
        t_push();
 
@@ -181,8 +198,8 @@ static int fetch_mail(struct imap_fetch_context *ctx, struct mail *mail)
                /* write the data into temp string */
                if (ctx->imap_data & IMAP_FETCH_UID)
                        fetch_uid(ctx, mail);
-               if ((ctx->fetch_data & MAIL_FETCH_FLAGS) || mail->seen_updated)
-                       if (!fetch_flags(ctx, mail))
+               if ((ctx->fetch_data & MAIL_FETCH_FLAGS) || seen_updated)
+                       if (!fetch_flags(ctx, mail, flags))
                                break;
                if (ctx->fetch_data & MAIL_FETCH_RECEIVED_DATE)
                        if (!fetch_internaldate(ctx, mail))
@@ -247,7 +264,15 @@ int imap_fetch(struct client *client,
 {
        struct imap_fetch_context ctx;
        struct mail *mail;
-       int all_found, update_seen = FALSE;
+       int all_found;
+
+       memset(&ctx, 0, sizeof(ctx));
+       ctx.fetch_data = fetch_data;
+       ctx.imap_data = imap_data;
+       ctx.bodies = bodies;
+       ctx.output = client->output;
+       ctx.select_counter = client->select_counter;
+       ctx.seen_flag.flags = MAIL_SEEN;
 
        if (!client->mailbox->readonly) {
                /* If we have any BODY[..] sections, \Seen flag is added for
@@ -256,24 +281,17 @@ int imap_fetch(struct client *client,
 
                for (body = bodies; body != NULL; body = body->next) {
                        if (!body->peek) {
-                               update_seen = TRUE;
+                               ctx.update_seen = TRUE;
                                break;
                        }
                }
 
                if (imap_data & (IMAP_FETCH_RFC822|IMAP_FETCH_RFC822_TEXT))
-                       update_seen = TRUE;
+                       ctx.update_seen = TRUE;
        }
 
-       memset(&ctx, 0, sizeof(ctx));
-       ctx.fetch_data = fetch_data;
-       ctx.imap_data = imap_data;
-       ctx.bodies = bodies;
-       ctx.output = client->output;
-       ctx.select_counter = client->select_counter;
-
        ctx.fetch_ctx = client->mailbox->
-               fetch_init(client->mailbox, fetch_data, &update_seen,
+               fetch_init(client->mailbox, fetch_data, ctx.update_seen,
                           messageset, uidset);
        if (ctx.fetch_ctx == NULL)
                return -1;
index ace7f86f9f4ddf4b59d9c3538ba6ae045710d963..e04ce38dc212a98f626531b343347c0b2888a66a 100644 (file)
@@ -30,6 +30,9 @@ struct imap_fetch_context {
        const char *prefix;
        unsigned int select_counter;
 
+       int update_seen;
+       struct mail_full_flags seen_flag;
+
        int first, failed;
 };
 
index 141711eac3ce31b2791533db215d3c6efc3cfe24..d5c5e4de96ef472a95523399082bab09e8d86a6a 100644 (file)
@@ -46,9 +46,8 @@ static void expunge(struct mailbox *mailbox, unsigned int seq, void *context)
 }
 
 static void update_flags(struct mailbox *mailbox,
-                        unsigned int seq, unsigned int uid,
-                        enum mail_flags flags, const char *custom_flags[],
-                        unsigned int custom_flags_count, void *context)
+                        unsigned int seq, unsigned int uid __attr_unused__,
+                        const struct mail_full_flags *flags, void *context)
 {
        struct client *client = context;
        const char *str;
@@ -57,15 +56,8 @@ static void update_flags(struct mailbox *mailbox,
                return;
 
        t_push();
-       str = imap_write_flags(flags, custom_flags, custom_flags_count);
-
-       if (client->sync_flags_send_uid) {
-               str = t_strdup_printf("* %u FETCH (FLAGS (%s) UID %u)",
-                                     seq, str, uid);
-       } else {
-               str = t_strdup_printf("* %u FETCH (FLAGS (%s))", seq, str);
-       }
-
+       str = imap_write_flags(flags);
+       str = t_strdup_printf("* %u FETCH (FLAGS (%s))", seq, str);
        client_send_line(client, str);
        t_pop();
 }
index abc7632b81c13528c7c5de4117232e47178e1265..ea7790ed46863cf6da376b2d454d4234eef8fcb2 100644 (file)
@@ -4,39 +4,39 @@
 #include "str.h"
 #include "imap-util.h"
 
-const char *imap_write_flags(enum mail_flags flags, const char *custom_flags[],
-                            unsigned int custom_flags_count)
+const char *imap_write_flags(const struct mail_full_flags *flags)
 {
        string_t *str;
        const char *sysflags, *name;
        unsigned int i;
 
-       i_assert(custom_flags_count <= MAIL_CUSTOM_FLAGS_COUNT);
+       i_assert(flags->custom_flags_count <= MAIL_CUSTOM_FLAGS_COUNT);
 
        if (flags == 0)
                return "";
 
-       sysflags = t_strconcat((flags & MAIL_ANSWERED) ? " \\Answered" : "",
-                              (flags & MAIL_FLAGGED) ? " \\Flagged" : "",
-                              (flags & MAIL_DELETED) ? " \\Deleted" : "",
-                              (flags & MAIL_SEEN) ? " \\Seen" : "",
-                              (flags & MAIL_DRAFT) ? " \\Draft" : "",
-                              (flags & MAIL_RECENT)  ? " \\Recent" : "",
-                              NULL);
+       sysflags = t_strconcat(
+               (flags->flags & MAIL_ANSWERED) ? " \\Answered" : "",
+               (flags->flags & MAIL_FLAGGED) ? " \\Flagged" : "",
+               (flags->flags & MAIL_DELETED) ? " \\Deleted" : "",
+               (flags->flags & MAIL_SEEN) ? " \\Seen" : "",
+               (flags->flags & MAIL_DRAFT) ? " \\Draft" : "",
+               (flags->flags & MAIL_RECENT)  ? " \\Recent" : "",
+               NULL);
 
        if (*sysflags != '\0')
                sysflags++;
 
-       if ((flags & MAIL_CUSTOM_FLAGS_MASK) == 0)
+       if ((flags->flags & MAIL_CUSTOM_FLAGS_MASK) == 0)
                return sysflags;
 
        /* we have custom flags too */
        str = t_str_new(256);
        str_append(str, sysflags);
 
-       for (i = 0; i < custom_flags_count; i++) {
-               if (flags & (1 << (i + MAIL_CUSTOM_FLAG_1_BIT))) {
-                       name = custom_flags[i];
+       for (i = 0; i < flags->custom_flags_count; i++) {
+               if (flags->flags & (1 << (i + MAIL_CUSTOM_FLAG_1_BIT))) {
+                       name = flags->custom_flags[i];
                        if (name != NULL && *name != '\0') {
                                if (str_len(str) > 0)
                                        str_append_c(str, ' ');
index 64d7a4a3b77df9fe0a60abf5b978c513c5f5810c..2cd5ac3b691694800ee7945f549bd72ca9a39a6b 100644 (file)
@@ -16,6 +16,13 @@ enum mail_flags {
        MAIL_CUSTOM_FLAGS_MASK  = 0xfffffc0
 };
 
+struct mail_full_flags {
+       enum mail_flags flags;
+
+       const char **custom_flags;
+       unsigned int custom_flags_count;
+};
+
 /* growing number of flags isn't very easy. biggest problem is that they're
    stored into unsigned int, which is 32bit almost everywhere. another thing
    to remember is that with maildir format, the custom flags are stored into
@@ -28,9 +35,8 @@ enum {
        MAIL_FLAGS_COUNT        = 32
 };
 
-/* Return flags as a space separated string. custom_flags[] is a list of
-   names for custom flags, flags having NULL or "" entry are ignored. */
-const char *imap_write_flags(enum mail_flags flags, const char *custom_flags[],
-                            unsigned int custom_flags_count);
+/* Return flags as a space separated string. If custom flags don't have entry
+   in flags->custom_flags[], or if it's NULL or "" the flag s ignored. */
+const char *imap_write_flags(const struct mail_full_flags *flags);
 
 #endif
index 58dd9b76ba2c2a624b8de2fee582473fdcd4b8b2..dc8850a42d2f3fb77ba52e8c2377cb8378998c73 100644 (file)
@@ -17,13 +17,12 @@ struct mail_fetch_context {
        struct messageset_context *msgset_ctx;
        struct index_mail mail;
 
-       int update_seen;
        enum mail_lock_type old_lock;
 };
 
 struct mail_fetch_context *
 index_storage_fetch_init(struct mailbox *box,
-                        enum mail_fetch_field wanted_fields, int *update_seen,
+                        enum mail_fetch_field wanted_fields, int update_flags,
                         const char *messageset, int uidset)
 {
        struct index_mailbox *ibox = (struct index_mailbox *) box;
@@ -33,11 +32,8 @@ index_storage_fetch_init(struct mailbox *box,
        ctx = i_new(struct mail_fetch_context, 1);
        ctx->old_lock = ibox->index->lock_type;
 
-       if (box->readonly && update_seen != NULL)
-               *update_seen = FALSE;
-
        /* need exclusive lock to update the \Seen flags */
-       if (update_seen != NULL && *update_seen) {
+       if (update_flags && !box->readonly) {
                if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
                        return NULL;
        }
@@ -48,19 +44,8 @@ index_storage_fetch_init(struct mailbox *box,
                                         MAIL_LOCK_SHARED))
                return NULL;
 
-       if (update_seen != NULL && *update_seen &&
-           ibox->index->header->messages_count ==
-           ibox->index->header->seen_messages_count &&
-           ctx->old_lock != MAIL_LOCK_EXCLUSIVE) {
-               /* if all messages are already seen, there's no point in
-                  keeping exclusive lock */
-               *update_seen = FALSE;
-               (void)index_storage_lock(ibox, MAIL_LOCK_SHARED);
-       }
-
        ctx->ibox = ibox;
        ctx->index = ibox->index;
-       ctx->update_seen = update_seen != NULL && *update_seen;
 
        index_mail_init(ibox, &ctx->mail, wanted_fields, NULL);
        ctx->msgset_ctx = index_messageset_init(ibox, messageset, uidset, TRUE);
@@ -89,7 +74,6 @@ int index_storage_fetch_deinit(struct mail_fetch_context *ctx, int *all_found)
 struct mail *index_storage_fetch_next(struct mail_fetch_context *ctx)
 {
        const struct messageset_mail *msgset_mail;
-       struct mail_index_record *rec;
        int ret;
 
        do {
@@ -97,20 +81,11 @@ struct mail *index_storage_fetch_next(struct mail_fetch_context *ctx)
                if (msgset_mail == NULL)
                        return NULL;
 
-               rec = msgset_mail->rec;
-               ctx->mail.mail.seen_updated = FALSE;
-               if (ctx->update_seen && (rec->msg_flags & MAIL_SEEN) == 0) {
-                       if (ctx->index->update_flags(ctx->index, rec,
-                                                    msgset_mail->idx_seq,
-                                                    rec->msg_flags | MAIL_SEEN,
-                                                    FALSE))
-                               ctx->mail.mail.seen_updated = TRUE;
-               }
-
                ctx->mail.mail.seq = msgset_mail->client_seq;
-               ctx->mail.mail.uid = rec->uid;
+               ctx->mail.mail.uid = msgset_mail->rec->uid;
 
-               ret = index_mail_next(&ctx->mail, rec);
+               ret = index_mail_next(&ctx->mail, msgset_mail->rec,
+                                     msgset_mail->idx_seq);
        } while (ret == 0);
 
        return ret < 0 ? NULL : &ctx->mail.mail;
@@ -118,13 +93,13 @@ struct mail *index_storage_fetch_next(struct mail_fetch_context *ctx)
 
 static struct mail *
 fetch_record(struct index_mailbox *ibox, struct mail_index_record *rec,
-            enum mail_fetch_field wanted_fields)
+            unsigned int idx_seq, enum mail_fetch_field wanted_fields)
 {
        if (ibox->fetch_mail.pool != NULL)
                index_mail_deinit(&ibox->fetch_mail);
 
        index_mail_init(ibox, &ibox->fetch_mail, wanted_fields, NULL);
-       if (index_mail_next(&ibox->fetch_mail, rec) <= 0)
+       if (index_mail_next(&ibox->fetch_mail, rec, idx_seq) <= 0)
                return NULL;
 
        return &ibox->fetch_mail.mail;
@@ -134,15 +109,16 @@ struct mail *index_storage_fetch_uid(struct mailbox *box, unsigned int uid,
                                     enum mail_fetch_field wanted_fields)
 {
        struct index_mailbox *ibox = (struct index_mailbox *) box;
-        struct mail_index_record *rec;
+       struct mail_index_record *rec;
+       unsigned int seq;
 
        i_assert(ibox->index->lock_type != MAIL_LOCK_UNLOCK);
 
-       rec = ibox->index->lookup_uid_range(ibox->index, uid, uid, NULL);
+       rec = ibox->index->lookup_uid_range(ibox->index, uid, uid, &seq);
        if (rec == NULL)
                return NULL;
 
-       return fetch_record(ibox, rec, wanted_fields);
+       return fetch_record(ibox, rec, seq, wanted_fields);
 }
 
 struct mail *index_storage_fetch_seq(struct mailbox *box, unsigned int seq,
@@ -158,9 +134,10 @@ struct mail *index_storage_fetch_seq(struct mailbox *box, unsigned int seq,
                                            &expunges_before) == NULL)
                return NULL;
 
-       rec = ibox->index->lookup(ibox->index, seq - expunges_before);
+       seq -= expunges_before;
+       rec = ibox->index->lookup(ibox->index, seq);
        if (rec == NULL)
                return NULL;
 
-       return fetch_record(ibox, rec, wanted_fields);
+       return fetch_record(ibox, rec, seq, wanted_fields);
 }
index 095bf40b43761142a2a2d02bd133d1549965cb39..faf36a3301a15eb28b0c78e9ce0c3bcbdb60e71f 100644 (file)
@@ -637,7 +637,7 @@ static const char *get_special(struct mail *_mail, enum mail_fetch_field field)
 }
 
 static struct mail index_mail = {
-       0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0,
 
        get_flags,
        get_parts,
@@ -649,6 +649,7 @@ static struct mail index_mail = {
        get_first_mailbox,
        get_stream,
        get_special,
+       index_storage_update_flags,
        index_storage_copy
 };
 
@@ -668,7 +669,8 @@ void index_mail_init(struct index_mailbox *ibox, struct index_mail *mail,
                ibox->mail_init(mail);
 }
 
-int index_mail_next(struct index_mail *mail, struct mail_index_record *rec)
+int index_mail_next(struct index_mail *mail, struct mail_index_record *rec,
+                   unsigned int idx_seq)
 {
        struct index_mail_data *data = &mail->data;
        int ret, open_mail, parse_header, envelope_headers;
@@ -688,6 +690,7 @@ int index_mail_next(struct index_mail *mail, struct mail_index_record *rec)
                (rec->index_flags & INDEX_MAIL_FLAG_HAS_NO_NULS) != 0;
 
        data->rec = rec;
+       data->idx_seq = idx_seq;
        data->size = (uoff_t)-1;
        data->received_date = data->sent_time = (time_t)-1;
 
index 7c8e10213234e10e5aae14c057da9bc4a6324377..609cdbc2b46f0a96e855125a74efd51eb8d80d64 100644 (file)
@@ -22,6 +22,8 @@ struct index_mail_data {
         struct message_part_envelope_data *envelope_data;
 
        struct mail_index_record *rec;
+       unsigned int idx_seq;
+
        struct istream *stream;
         struct message_size hdr_size, body_size;
 
@@ -47,7 +49,8 @@ struct index_mail {
 void index_mail_init(struct index_mailbox *ibox, struct index_mail *mail,
                     enum mail_fetch_field wanted_fields,
                     const char *const wanted_headers[]);
-int index_mail_next(struct index_mail *mail, struct mail_index_record *rec);
+int index_mail_next(struct index_mail *mail, struct mail_index_record *rec,
+                   unsigned int idx_seq);
 void index_mail_deinit(struct index_mail *mail);
 
 void index_mail_init_parse_header(struct index_mail *mail);
index 66f9bd5ebc8efa8dbac4f8917de60beb1a560283..26d0b1a8c5d515222fd65bd64325e96173aeeec1 100644 (file)
@@ -1003,7 +1003,8 @@ struct mail *index_storage_search_next(struct mail_search_context *ctx)
 
                ctx->mail->seq = msgset_mail->client_seq;
                ctx->mail->uid = msgset_mail->rec->uid;
-               ret = index_mail_next(&ctx->imail, msgset_mail->rec);
+               ret = index_mail_next(&ctx->imail, msgset_mail->rec,
+                                     msgset_mail->idx_seq);
 
                if (ret < 0)
                        return NULL;
index ab98ccb004596ca05a7ab5aa2e2f9d9fd6287841..afd052e9a0e71055eae323809e6ea10df6b5d48e 100644 (file)
@@ -88,14 +88,10 @@ int index_storage_get_status(struct mailbox *box,
                             enum mailbox_status_items items,
                             struct mailbox_status *status);
 int index_storage_sync(struct mailbox *box, enum mail_sync_flags flags);
-int index_storage_update_flags(struct mailbox *box, const char *messageset,
-                              int uidset, const struct mail_full_flags *flags,
-                              enum modify_type modify_type, int notify,
-                              int *all_found);
 
 struct mail_fetch_context *
 index_storage_fetch_init(struct mailbox *box,
-                        enum mail_fetch_field wanted_fields, int *update_seen,
+                        enum mail_fetch_field wanted_fields, int update_flags,
                         const char *messageset, int uidset);
 int index_storage_fetch_deinit(struct mail_fetch_context *ctx, int *all_found);
 struct mail *index_storage_fetch_next(struct mail_fetch_context *ctx);
@@ -120,4 +116,8 @@ struct mail_copy_context *index_storage_copy_init(struct mailbox *box);
 int index_storage_copy_deinit(struct mail_copy_context *ctx, int rollback);
 int index_storage_copy(struct mail *mail, struct mail_copy_context *ctx);
 
+int index_storage_update_flags(struct mail *mail,
+                              const struct mail_full_flags *flags,
+                              enum modify_type modify_type);
+
 #endif
index 4b9206c4656359bbab93d8639d47190bbd8d30ee..50ca4f5e9b4e6abb48d3b377f9b63b11798138bd 100644 (file)
@@ -99,10 +99,9 @@ int index_storage_sync_modifylog(struct index_mailbox *ibox, int hide_deleted)
 {
        const struct modify_log_record *log1, *log2, *log, *first_flag_log;
        struct mail_index_record *rec;
-       enum mail_flags flags;
+       struct mail_full_flags flags;
         struct mail_storage_callbacks *sc;
        void *sc_context;
-       const char **custom_flags;
        unsigned int count1, count2, total_count, seq, seq_count, i, messages;
        unsigned int first_flag_change, first_flag_messages_count;
 
@@ -159,7 +158,9 @@ int index_storage_sync_modifylog(struct index_mailbox *ibox, int hide_deleted)
 
        /* now show the flags */
        messages = first_flag_messages_count;
-       custom_flags = mail_custom_flags_list_get(ibox->index->custom_flags);
+       flags.custom_flags =
+               mail_custom_flags_list_get(ibox->index->custom_flags);
+       flags.custom_flags_count = MAIL_CUSTOM_FLAGS_COUNT;
 
        if (sc->update_flags == NULL) {
                /* don't bother going through, we're not printing them anyway */
@@ -185,19 +186,17 @@ int index_storage_sync_modifylog(struct index_mailbox *ibox, int hide_deleted)
                                                            log->uid1,
                                                            log->uid2, &seq);
                        while (rec != NULL && rec->uid <= log->uid2) {
-                               flags = rec->msg_flags;
+                               flags.flags = rec->msg_flags;
                                if (rec->uid >= ibox->index->first_recent_uid)
-                                       flags |= MAIL_RECENT;
+                                       flags.flags |= MAIL_RECENT;
 
                                /* \Deleted-hiding is useful when syncing just
                                   before doing EXPUNGE. */
-                               if ((flags & MAIL_DELETED) == 0 ||
+                               if ((flags.flags & MAIL_DELETED) == 0 ||
                                    !hide_deleted) {
-                                       sc->update_flags(
-                                               &ibox->box, seq, rec->uid,
-                                               flags, custom_flags,
-                                               MAIL_CUSTOM_FLAGS_COUNT,
-                                               sc_context);
+                                       sc->update_flags(&ibox->box, seq,
+                                                        rec->uid, &flags,
+                                                        sc_context);
                                }
 
                                 seq++;
index 255ba363be4f5a503143dada5a23e7c67cf3a15b..34d5c1a5447cef679e0938b738db576253b29991 100644 (file)
@@ -5,97 +5,54 @@
 #include "index-messageset.h"
 #include "mail-custom-flags.h"
 
-static int update_messageset(struct messageset_context *ctx,
-                            struct index_mailbox *ibox, enum mail_flags flags,
-                            enum modify_type modify_type, int notify)
+int index_storage_update_flags(struct mail *mail,
+                              const struct mail_full_flags *flags,
+                              enum modify_type modify_type)
 {
-       struct mail_storage *storage;
-       const struct messageset_mail *mail;
-       const char **custom_flags;
-       enum mail_flags new_flags;
+       struct index_mail *imail = (struct index_mail *) mail;
+       struct index_mailbox *ibox = imail->ibox;
+       struct mail_storage *storage = mail->box->storage;
+       enum mail_flags modify_flags, new_flags;
 
-       storage = ibox->box.storage;
-       custom_flags = mail_custom_flags_list_get(ibox->index->custom_flags);
-
-       while ((mail = index_messageset_next(ctx)) != NULL) {
-               switch (modify_type) {
-               case MODIFY_ADD:
-                       new_flags = mail->rec->msg_flags | flags;
-                       break;
-               case MODIFY_REMOVE:
-                       new_flags = mail->rec->msg_flags & ~flags;
-                       break;
-               case MODIFY_REPLACE:
-                       new_flags = flags;
-                       break;
-               default:
-                       i_unreached();
-               }
-
-               if (!ibox->index->update_flags(ibox->index, mail->rec,
-                                              mail->idx_seq, new_flags, FALSE))
-                       return -1;
-
-               if (mail_custom_flags_has_changes(ibox->index->custom_flags)) {
-                       storage->callbacks->new_custom_flags(&ibox->box,
-                               custom_flags, MAIL_CUSTOM_FLAGS_COUNT,
-                               storage->callback_context);
-               }
-
-               if (notify) {
-                       if (mail->rec->uid >= ibox->index->first_recent_uid)
-                               new_flags |= MAIL_RECENT;
-
-                       storage->callbacks->update_flags(&ibox->box,
-                               mail->client_seq, mail->rec->uid, new_flags,
-                               custom_flags, MAIL_CUSTOM_FLAGS_COUNT,
-                               storage->callback_context);
-               }
-       }
-
-       return 1;
-}
-
-int index_storage_update_flags(struct mailbox *box, const char *messageset,
-                              int uidset, const struct mail_full_flags *flags,
-                              enum modify_type modify_type, int notify,
-                              int *all_found)
-{
-       struct index_mailbox *ibox = (struct index_mailbox *) box;
-        struct messageset_context *ctx;
-       enum mail_flags mail_flags;
-       int ret, ret2;
-
-       if (box->readonly) {
-               box->storage->callbacks->
+       if (mail->box->readonly) {
+               storage->callbacks->
                        notify_no(&ibox->box,
-                                 "Mailbox is read-only, ignoring store",
-                                 box->storage->callback_context);
+                                 "Mailbox is read-only, ignoring flag changes",
+                                 storage->callback_context);
                return TRUE;
        }
 
-       mail_flags = flags->flags;
-       if (!index_mailbox_fix_custom_flags(ibox, &mail_flags,
+       /* \Recent can't be changed */
+       modify_flags = flags->flags & ~MAIL_RECENT;
+
+       if (!index_mailbox_fix_custom_flags(ibox, &modify_flags,
                                            flags->custom_flags,
                                            flags->custom_flags_count))
                return FALSE;
 
-       if (!index_storage_lock(ibox, MAIL_LOCK_EXCLUSIVE))
-               return FALSE;
+       switch (modify_type) {
+       case MODIFY_ADD:
+               new_flags = imail->data.rec->msg_flags | modify_flags;
+               break;
+       case MODIFY_REMOVE:
+               new_flags = imail->data.rec->msg_flags & ~modify_flags;
+               break;
+       case MODIFY_REPLACE:
+               new_flags = modify_flags;
+               break;
+       default:
+               i_unreached();
+       }
 
-       if (!index_storage_sync_and_lock(ibox, TRUE, TRUE, MAIL_LOCK_UNLOCK))
+       if (!ibox->index->update_flags(ibox->index, imail->data.rec,
+                                      imail->data.idx_seq, new_flags, FALSE))
                return FALSE;
 
-       mail_flags &= ~MAIL_RECENT; /* \Recent can't be changed */
-
-       ctx = index_messageset_init(ibox, messageset, uidset, TRUE);
-       ret = update_messageset(ctx, ibox, mail_flags, modify_type, notify);
-       ret2 = index_messageset_deinit(ctx);
-
-       if (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
-               return FALSE;
+       if (mail_custom_flags_has_changes(ibox->index->custom_flags)) {
+               storage->callbacks->new_custom_flags(&ibox->box,
+                       mail_custom_flags_list_get(ibox->index->custom_flags),
+                       MAIL_CUSTOM_FLAGS_COUNT, storage->callback_context);
+       }
 
-       if (all_found != NULL)
-               *all_found = ret2 > 0;
-       return ret >= 0 && ret2 >= 0;
+       return TRUE;
 }
index 40284af8d1033d8138c8a4bbd8c58bff9e6b6185..fbc5dc02ce0c0ff85a59c4f6603abf4a650ef65f 100644 (file)
@@ -745,7 +745,6 @@ struct mailbox maildir_mailbox = {
        index_storage_sync,
        maildir_storage_auto_sync,
        index_storage_expunge,
-       index_storage_update_flags,
        index_storage_fetch_init,
        index_storage_fetch_deinit,
        index_storage_fetch_next,
index ce4823de2555de9b509af48b477101ef002075d0..7525842edd4c3505a752110e2e0e289221118887 100644 (file)
@@ -747,7 +747,6 @@ struct mailbox mbox_mailbox = {
        index_storage_sync,
        mbox_storage_auto_sync,
        index_storage_expunge,
-       index_storage_update_flags,
        index_storage_fetch_init,
        index_storage_fetch_deinit,
        index_storage_fetch_next,
index 973063e03e89152113bfbb3be03c60a520c186e1..e120d5e43e6c562d5d486fbb73615ba4bd54d1ea 100644 (file)
@@ -109,13 +109,6 @@ enum client_workarounds {
        WORKAROUND_OUTLOOK_IDLE         = 0x02
 };
 
-struct mail_full_flags {
-       enum mail_flags flags;
-
-       const char **custom_flags;
-       unsigned int custom_flags_count;
-};
-
 struct mail_storage;
 struct mail_storage_callbacks;
 struct mailbox_list;
@@ -248,22 +241,13 @@ struct mailbox {
           expunge callbacks. Also always does full syncing. */
        int (*expunge)(struct mailbox *box, int notify);
 
-       /* Update mail flags, calling update_flags callbacks. */
-       int (*update_flags)(struct mailbox *box,
-                           const char *messageset, int uidset,
-                           const struct mail_full_flags *flags,
-                           enum modify_type modify_type, int notify,
-                           int *all_found);
-
        /* Initialize new fetch request. wanted_fields isn't required, but it
-          can be used for optimizations. If *update_seen is TRUE, \Seen flag
-          is set for all fetched mails. *update_seen may be changed back to
-          FALSE if all mails are already seen, or if it's not possible to
-          change the flag (eg. read-only mailbox). */
+          can be used for optimizations. update_flags must be set to TRUE, if
+          you want to call mail->update_flags() */
        struct mail_fetch_context *
                (*fetch_init)(struct mailbox *box,
                              enum mail_fetch_field wanted_fields,
-                             int *update_seen,
+                             int update_flags,
                              const char *messageset, int uidset);
        /* Deinitialize fetch request. all_found is set to TRUE if all of the
           fetched messages were found (ie. not just deleted). */
@@ -350,7 +334,6 @@ struct mail {
        unsigned int seq;
        unsigned int uid;
 
-       unsigned int seen_updated:1; /* if update_seen was TRUE */
        unsigned int has_nuls:1; /* message data is known to contain NULs */
        unsigned int has_no_nuls:1; /* -''- known to not contain NULs */
 
@@ -388,6 +371,11 @@ struct mail {
        const char *(*get_special)(struct mail *mail,
                                   enum mail_fetch_field field);
 
+       /* Update message flags. */
+       int (*update_flags)(struct mail *mail,
+                           const struct mail_full_flags *flags,
+                           enum modify_type modify_type);
+
        /* Copy this mail to another mailbox. */
        int (*copy)(struct mail *mail, struct mail_copy_context *ctx);
 };
@@ -428,10 +416,10 @@ struct mail_storage_callbacks {
        void (*expunge)(struct mailbox *mailbox, unsigned int seq,
                        void *context);
        /* FETCH FLAGS */
-       void (*update_flags)(struct mailbox *mailbox, unsigned int seq,
-                            unsigned int uid, enum mail_flags flags,
-                            const char *custom_flags[],
-                            unsigned int custom_flags_count, void *context);
+       void (*update_flags)(struct mailbox *mailbox,
+                            unsigned int seq, unsigned int uid,
+                            const struct mail_full_flags *flags,
+                            void *context);
 
        /* EXISTS, RECENT */
        void (*new_messages)(struct mailbox *mailbox,