From: Timo Sirainen Date: Wed, 23 Jul 2003 01:44:16 +0000 (+0300) Subject: API change for updating message flags. X-Git-Tag: 1.1.alpha1~4468 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6389aeec8c26b585e583c364b48ad12adf741898;p=thirdparty%2Fdovecot%2Fcore.git API change for updating message flags. --HG-- branch : HEAD --- diff --git a/src/imap/client.h b/src/imap/client.h index 495338b415..49ee80cd58 100644 --- a/src/imap/client.h +++ b/src/imap/client.h @@ -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 */ diff --git a/src/imap/cmd-copy.c b/src/imap/cmd-copy.c index 6be697700d..5f799031c4 100644 --- a/src/imap/cmd-copy.c +++ b/src/imap/cmd-copy.c @@ -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; diff --git a/src/imap/cmd-store.c b/src/imap/cmd-store.c index 9cb639af0d..a7b4a41916 100644 --- a/src/imap/cmd-store.c +++ b/src/imap/cmd-store.c @@ -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; } diff --git a/src/imap/imap-fetch.c b/src/imap/imap-fetch.c index b7c0140538..59dcfd0239 100644 --- a/src/imap/imap-fetch.c +++ b/src/imap/imap-fetch.c @@ -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; diff --git a/src/imap/imap-fetch.h b/src/imap/imap-fetch.h index ace7f86f9f..e04ce38dc2 100644 --- a/src/imap/imap-fetch.h +++ b/src/imap/imap-fetch.h @@ -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; }; diff --git a/src/imap/mail-storage-callbacks.c b/src/imap/mail-storage-callbacks.c index 141711eac3..d5c5e4de96 100644 --- a/src/imap/mail-storage-callbacks.c +++ b/src/imap/mail-storage-callbacks.c @@ -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(); } diff --git a/src/lib-imap/imap-util.c b/src/lib-imap/imap-util.c index abc7632b81..ea7790ed46 100644 --- a/src/lib-imap/imap-util.c +++ b/src/lib-imap/imap-util.c @@ -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, ' '); diff --git a/src/lib-imap/imap-util.h b/src/lib-imap/imap-util.h index 64d7a4a3b7..2cd5ac3b69 100644 --- a/src/lib-imap/imap-util.h +++ b/src/lib-imap/imap-util.h @@ -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 diff --git a/src/lib-storage/index/index-fetch.c b/src/lib-storage/index/index-fetch.c index 58dd9b76ba..dc8850a42d 100644 --- a/src/lib-storage/index/index-fetch.c +++ b/src/lib-storage/index/index-fetch.c @@ -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); } diff --git a/src/lib-storage/index/index-mail.c b/src/lib-storage/index/index-mail.c index 095bf40b43..faf36a3301 100644 --- a/src/lib-storage/index/index-mail.c +++ b/src/lib-storage/index/index-mail.c @@ -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; diff --git a/src/lib-storage/index/index-mail.h b/src/lib-storage/index/index-mail.h index 7c8e102132..609cdbc2b4 100644 --- a/src/lib-storage/index/index-mail.h +++ b/src/lib-storage/index/index-mail.h @@ -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); diff --git a/src/lib-storage/index/index-search.c b/src/lib-storage/index/index-search.c index 66f9bd5ebc..26d0b1a8c5 100644 --- a/src/lib-storage/index/index-search.c +++ b/src/lib-storage/index/index-search.c @@ -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; diff --git a/src/lib-storage/index/index-storage.h b/src/lib-storage/index/index-storage.h index ab98ccb004..afd052e9a0 100644 --- a/src/lib-storage/index/index-storage.h +++ b/src/lib-storage/index/index-storage.h @@ -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 diff --git a/src/lib-storage/index/index-sync.c b/src/lib-storage/index/index-sync.c index 4b9206c465..50ca4f5e9b 100644 --- a/src/lib-storage/index/index-sync.c +++ b/src/lib-storage/index/index-sync.c @@ -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++; diff --git a/src/lib-storage/index/index-update-flags.c b/src/lib-storage/index/index-update-flags.c index 255ba363be..34d5c1a544 100644 --- a/src/lib-storage/index/index-update-flags.c +++ b/src/lib-storage/index/index-update-flags.c @@ -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; } diff --git a/src/lib-storage/index/maildir/maildir-storage.c b/src/lib-storage/index/maildir/maildir-storage.c index 40284af8d1..fbc5dc02ce 100644 --- a/src/lib-storage/index/maildir/maildir-storage.c +++ b/src/lib-storage/index/maildir/maildir-storage.c @@ -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, diff --git a/src/lib-storage/index/mbox/mbox-storage.c b/src/lib-storage/index/mbox/mbox-storage.c index ce4823de25..7525842edd 100644 --- a/src/lib-storage/index/mbox/mbox-storage.c +++ b/src/lib-storage/index/mbox/mbox-storage.c @@ -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, diff --git a/src/lib-storage/mail-storage.h b/src/lib-storage/mail-storage.h index 973063e03e..e120d5e43e 100644 --- a/src/lib-storage/mail-storage.h +++ b/src/lib-storage/mail-storage.h @@ -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,