changeset 1638:e95c0e462591 HEAD

API change for updating message flags.
author Timo Sirainen <tss@iki.fi>
date Wed, 23 Jul 2003 04:44:16 +0300
parents a64391b49589
children 3621292209f4
files 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
diffstat 18 files changed, 213 insertions(+), 224 deletions(-) [+]
line wrap: on
line diff
--- a/src/imap/client.h	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/imap/client.h	Wed Jul 23 04:44:16 2003 +0300
@@ -39,7 +39,6 @@
 
 	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 */
--- a/src/imap/cmd-copy.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/imap/cmd-copy.c	Wed Jul 23 04:44:16 2003 +0300
@@ -12,7 +12,7 @@
 	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;
--- a/src/imap/cmd-store.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/imap/cmd-store.c	Wed Jul 23 04:44:16 2003 +0300
@@ -32,13 +32,37 @@
 	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 @@
 	}
 
 	/* 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 @@
 		client_send_storage_error(client);
 	}
 
-	client->sync_flags_send_uid = FALSE;
 	return TRUE;
 }
--- a/src/imap/imap-fetch.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/imap/imap-fetch.c	Wed Jul 23 04:44:16 2003 +0300
@@ -17,17 +17,16 @@
 	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;
+	if (flags == NULL) {
+		flags = mail->get_flags(mail);
+		if (flags == NULL)
+			return FALSE;
+	}
 
-	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_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 @@
 		/* 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 @@
 {
 	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 @@
 
 		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;
--- a/src/imap/imap-fetch.h	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/imap/imap-fetch.h	Wed Jul 23 04:44:16 2003 +0300
@@ -30,6 +30,9 @@
 	const char *prefix;
 	unsigned int select_counter;
 
+	int update_seen;
+	struct mail_full_flags seen_flag;
+
 	int first, failed;
 };
 
--- a/src/imap/mail-storage-callbacks.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/imap/mail-storage-callbacks.c	Wed Jul 23 04:44:16 2003 +0300
@@ -46,9 +46,8 @@
 }
 
 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 @@
 		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();
 }
--- a/src/lib-imap/imap-util.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-imap/imap-util.c	Wed Jul 23 04:44:16 2003 +0300
@@ -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, ' ');
--- a/src/lib-imap/imap-util.h	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-imap/imap-util.h	Wed Jul 23 04:44:16 2003 +0300
@@ -16,6 +16,13 @@
 	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 @@
 	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
--- a/src/lib-storage/index/index-fetch.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-storage/index/index-fetch.c	Wed Jul 23 04:44:16 2003 +0300
@@ -17,13 +17,12 @@
 	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 @@
 	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 @@
 					 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 @@
 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 @@
 		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 = msgset_mail->rec->uid;
 
-		ctx->mail.mail.seq = msgset_mail->client_seq;
-		ctx->mail.mail.uid = 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 @@
 
 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 @@
 				     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 @@
 					    &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);
 }
--- a/src/lib-storage/index/index-mail.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-storage/index/index-mail.c	Wed Jul 23 04:44:16 2003 +0300
@@ -637,7 +637,7 @@
 }
 
 static struct mail index_mail = {
-	0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0,
 
 	get_flags,
 	get_parts,
@@ -649,6 +649,7 @@
 	get_first_mailbox,
 	get_stream,
 	get_special,
+	index_storage_update_flags,
 	index_storage_copy
 };
 
@@ -668,7 +669,8 @@
 		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 @@
 		(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;
 
--- a/src/lib-storage/index/index-mail.h	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-storage/index/index-mail.h	Wed Jul 23 04:44:16 2003 +0300
@@ -22,6 +22,8 @@
         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 @@
 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);
--- a/src/lib-storage/index/index-search.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-storage/index/index-search.c	Wed Jul 23 04:44:16 2003 +0300
@@ -1003,7 +1003,8 @@
 
 		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;
--- a/src/lib-storage/index/index-storage.h	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-storage/index/index-storage.h	Wed Jul 23 04:44:16 2003 +0300
@@ -88,14 +88,10 @@
 			     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 @@
 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
--- a/src/lib-storage/index/index-sync.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-storage/index/index-sync.c	Wed Jul 23 04:44:16 2003 +0300
@@ -99,10 +99,9 @@
 {
 	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 @@
 
 	/* 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 @@
 							    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++;
--- a/src/lib-storage/index/index-update-flags.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-storage/index/index-update-flags.c	Wed Jul 23 04:44:16 2003 +0300
@@ -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;
-
-	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;
+	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;
 
-		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 (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 (!index_storage_lock(ibox, MAIL_LOCK_UNLOCK))
-		return FALSE;
-
-	if (all_found != NULL)
-		*all_found = ret2 > 0;
-	return ret >= 0 && ret2 >= 0;
+	return TRUE;
 }
--- a/src/lib-storage/index/maildir/maildir-storage.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Wed Jul 23 04:44:16 2003 +0300
@@ -745,7 +745,6 @@
 	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,
--- a/src/lib-storage/index/mbox/mbox-storage.c	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Wed Jul 23 04:44:16 2003 +0300
@@ -747,7 +747,6 @@
 	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,
--- a/src/lib-storage/mail-storage.h	Wed Jul 23 03:40:49 2003 +0300
+++ b/src/lib-storage/mail-storage.h	Wed Jul 23 04:44:16 2003 +0300
@@ -109,13 +109,6 @@
 	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 @@
 	   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 @@
 	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 @@
 	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 @@
 	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,