--- dovecot-1.0-stable.orig/src/imap/imap-fetch.h	Fri Feb 11 18:30:13 2005
+++ dovecot-1.0-stable/src/imap/imap-fetch.h	Tue Apr  5 11:42:38 2005
@@ -19,6 +19,7 @@
 struct imap_fetch_context_handler {
 	imap_fetch_handler_t *handler;
 	void *context;
+	int buffered;
 };
 
 struct imap_fetch_context {
@@ -33,6 +34,7 @@
         struct mailbox_header_lookup_ctx *all_headers_ctx;
 
 	buffer_t *handlers;
+	unsigned int buffered_handlers_count;
 
 	struct mail *cur_mail;
 	unsigned int cur_handler;
@@ -61,7 +63,7 @@
 void imap_fetch_handlers_register(const struct imap_fetch_handler *handlers,
 				  size_t count);
 
-void imap_fetch_add_handler(struct imap_fetch_context *ctx,
+void imap_fetch_add_handler(struct imap_fetch_context *ctx, int buffered,
 			    imap_fetch_handler_t *handler, void *context);
 
 struct imap_fetch_context *imap_fetch_init(struct client *client);
--- dovecot-1.0-stable.orig/src/imap/imap-fetch.c	Fri Feb 11 18:30:13 2005
+++ dovecot-1.0-stable/src/imap/imap-fetch.c	Tue Apr  5 11:55:02 2005
@@ -97,9 +97,19 @@
 	return ctx;
 }
 
-void imap_fetch_add_handler(struct imap_fetch_context *ctx,
-			    imap_fetch_handler_t *handler, void *context)
+void imap_fetch_add_handler(struct imap_fetch_context *ctx, int buffered,
+ 			    imap_fetch_handler_t *handler, void *context)
 {
+	/* partially because of broken clients, but also partially because
+	   it potentially can make client implementations faster, we have a
+	   buffered parameter which basically means that the handler promises
+	   to write the output in ctx->cur_str. The cur_str is then sent to
+	   client before calling any non-buffered handlers.
+
+	   We try to keep the handler registration order the same as the
+	   client requested them. This is especially useful to get UID
+	   returned first, which some clients rely on..
+	*/
 	const struct imap_fetch_context_handler *handlers;
 	struct imap_fetch_context_handler h;
 	size_t i, size;
@@ -119,8 +129,14 @@
 	memset(&h, 0, sizeof(h));
 	h.handler = handler;
 	h.context = context;
+	h.buffered = buffered;
 
-	buffer_append(ctx->handlers, &h, sizeof(h));
+	if (!buffered)
+		buffer_append(ctx->handlers, &h, sizeof(h));
+	else {
+		buffer_insert(ctx->handlers, ctx->buffered_handlers_count * sizeof(h), &h, sizeof(h)); 
+                ctx->buffered_handlers_count++;
+	}
 }
 
 void imap_fetch_begin(struct imap_fetch_context *ctx,
@@ -155,6 +171,30 @@
 				    ctx->fetch_data, ctx->all_headers_ctx);
 }
 
+static int imap_fetch_flush_buffer(struct imap_fetch_context *ctx)
+{
+	const unsigned char *data;
+	size_t len;
+
+	i_assert(ctx->first);
+
+	data = str_data(ctx->cur_str);
+	len = str_len(ctx->cur_str);
+
+	/* there's an extra space at the end if we added any fetch items
+	   to buffer */
+	if (data[len-1] == ' ') {
+		len--;
+		ctx->first = FALSE;
+	}
+
+	if (o_stream_send(ctx->client->output, data, len) < 0)
+		return -1;
+
+	str_truncate(ctx->cur_str, 0);
+	return 0;
+}
+
 int imap_fetch(struct imap_fetch_context *ctx)
 {
 	const struct imap_fetch_context_handler *handlers;
@@ -204,18 +244,19 @@
 
 			str_printfa(ctx->cur_str, "* %u FETCH (",
 				    ctx->cur_mail->seq);
-			if (o_stream_send(ctx->client->output,
-					  str_data(ctx->cur_str),
-					  str_len(ctx->cur_str)) < 0)
-				return -1;
-
-			str_truncate(ctx->cur_str, 0);
-			str_append_c(ctx->cur_str, ' ');
 			ctx->first = TRUE;
 			ctx->line_finished = FALSE;
 		}
 
-		for (; ctx->cur_handler < size; ctx->cur_handler++) {
+ 		for (; ctx->cur_handler < size; ctx->cur_handler++) {
+			if (str_len(ctx->cur_str) > 0 &&
+			    !handlers[ctx->cur_handler].buffered) {
+				/* first non-buffered handler.
+				   flush the buffer. */
+				if (imap_fetch_flush_buffer(ctx) < 0)
+					return -1;
+			}
+
 			t_push();
 			ret = handlers[ctx->cur_handler].
 				handler(ctx, ctx->cur_mail,
@@ -240,14 +281,11 @@
 			ctx->cur_offset = 0;
 		}
 
-		if (str_len(ctx->cur_str) > 1) {
-			if (o_stream_send(ctx->client->output,
-					  str_data(ctx->cur_str) + ctx->first,
-					  str_len(ctx->cur_str) - 1 -
-					  ctx->first) < 0)
+		if (str_len(ctx->cur_str) > 0) {
+			/* no non-buffered handlers */
+			if (imap_fetch_flush_buffer(ctx) < 0)
 				return -1;
 		}
-		str_truncate(ctx->cur_str, 0);
 
 		ctx->line_finished = TRUE;
 		if (o_stream_send(ctx->client->output, ")\r\n", 3) < 0)
@@ -320,7 +358,7 @@
 {
 	if (name[4] == '\0') {
 		ctx->fetch_data |= MAIL_FETCH_IMAP_BODY;
-		imap_fetch_add_handler(ctx, fetch_body, NULL);
+		imap_fetch_add_handler(ctx, FALSE, fetch_body, NULL);
 		return TRUE;
 	}
 	return fetch_body_section_init(ctx, name, args);
@@ -355,7 +393,7 @@
 				    struct imap_arg **args __attr_unused__)
 {
 	ctx->fetch_data |= MAIL_FETCH_IMAP_BODYSTRUCTURE;
-	imap_fetch_add_handler(ctx, fetch_bodystructure, NULL);
+	imap_fetch_add_handler(ctx, FALSE, fetch_bodystructure, NULL);
 	return TRUE;
 }
 
@@ -387,7 +425,7 @@
 			       struct imap_arg **args __attr_unused__)
 {
 	ctx->fetch_data |= MAIL_FETCH_IMAP_ENVELOPE;
-	imap_fetch_add_handler(ctx, fetch_envelope, NULL);
+	imap_fetch_add_handler(ctx, FALSE, fetch_envelope, NULL);
 	return TRUE;
 }
 
@@ -425,7 +463,7 @@
 {
 	ctx->flags_have_handler = TRUE;
 	ctx->fetch_data |= MAIL_FETCH_FLAGS;
-	imap_fetch_add_handler(ctx, fetch_flags, NULL);
+	imap_fetch_add_handler(ctx, TRUE, fetch_flags, NULL);
 	return TRUE;
 }
 
@@ -449,7 +487,7 @@
 				   struct imap_arg **args __attr_unused__)
 {
 	ctx->fetch_data |= MAIL_FETCH_RECEIVED_DATE;
-	imap_fetch_add_handler(ctx, fetch_internaldate, NULL);
+	imap_fetch_add_handler(ctx, TRUE, fetch_internaldate, NULL);
 	return TRUE;
 }
 
@@ -464,7 +502,7 @@
 			  const char *name __attr_unused__,
 			  struct imap_arg **args __attr_unused__)
 {
-	imap_fetch_add_handler(ctx, fetch_uid, NULL);
+	imap_fetch_add_handler(ctx, TRUE, fetch_uid, NULL);
 	return TRUE;
 }
 
--- dovecot-1.0-stable.orig/src/imap/imap-fetch-body.c	Mon Jan 31 16:37:54 2005
+++ dovecot-1.0-stable/src/imap/imap-fetch-body.c	Tue Apr  5 11:24:45 2005
@@ -587,7 +587,8 @@
 				MAIL_FETCH_STREAM_BODY)) != 0) {
 		/* we'll need to open the file anyway, don't try to get the
 		   headers from cache. */
-		imap_fetch_add_handler(ctx, fetch_body_header_partial, body);
+		imap_fetch_add_handler(ctx, FALSE,
+				       fetch_body_header_partial, body);
 		return TRUE;
 	}
 
@@ -599,7 +600,7 @@
 	}
 
 	body->header_ctx = mailbox_header_lookup_init(ctx->box, body->fields);
-	imap_fetch_add_handler(ctx, fetch_body_header_fields, body);
+	imap_fetch_add_handler(ctx, FALSE, fetch_body_header_fields, body);
 	t_pop();
 	return TRUE;
 }
@@ -612,13 +613,13 @@
 	if (*section == '\0') {
 		ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER |
 			MAIL_FETCH_STREAM_BODY;
-		imap_fetch_add_handler(ctx, fetch_body, body);
+		imap_fetch_add_handler(ctx, FALSE, fetch_body, body);
 		return TRUE;
 	}
 
 	if (strcmp(section, "TEXT") == 0) {
 		ctx->fetch_data |= MAIL_FETCH_STREAM_BODY;
-		imap_fetch_add_handler(ctx, fetch_body, body);
+		imap_fetch_add_handler(ctx, FALSE, fetch_body, body);
 		return TRUE;
 	}
 
@@ -626,7 +627,7 @@
 		/* exact header matches could be cached */
 		if (section[6] == '\0') {
 			ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER;
-			imap_fetch_add_handler(ctx, fetch_body, body);
+			imap_fetch_add_handler(ctx, FALSE, fetch_body, body);
 			return TRUE;
 		}
 
@@ -636,7 +637,7 @@
 
 		if (strncmp(section, "HEADER.FIELDS.NOT ", 18) == 0 &&
 		    fetch_body_header_fields_check(section+18)) {
-			imap_fetch_add_handler(ctx, fetch_body_header_partial,
+			imap_fetch_add_handler(ctx, FALSE, fetch_body_header_partial,
 					       body);
 			return TRUE;
 		}
@@ -655,7 +656,7 @@
 		     fetch_body_header_fields_check(section+14)) ||
 		    (strncmp(section, "HEADER.FIELDS.NOT ", 18) == 0 &&
 		     fetch_body_header_fields_check(section+18))) {
-			imap_fetch_add_handler(ctx, fetch_body_mime, body);
+			imap_fetch_add_handler(ctx, FALSE, fetch_body_mime, body);
 			return TRUE;
 		}
 	}
@@ -829,6 +830,7 @@
 static int fetch_rfc822_size(struct imap_fetch_context *ctx, struct mail *mail,
 			     void *context __attr_unused__)
 {
+	const char *str;
 	uoff_t size;
 
 	size = mail->get_virtual_size(mail);
@@ -926,24 +928,24 @@
 		ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER |
 			MAIL_FETCH_STREAM_BODY;
 		ctx->flags_update_seen = TRUE;
-		imap_fetch_add_handler(ctx, fetch_rfc822, NULL);
+		imap_fetch_add_handler(ctx, FALSE, fetch_rfc822, NULL);
 		return TRUE;
 	}
 
 	if (strcmp(name+6, ".SIZE") == 0) {
 		ctx->fetch_data |= MAIL_FETCH_VIRTUAL_SIZE;
-		imap_fetch_add_handler(ctx, fetch_rfc822_size, NULL);
+		imap_fetch_add_handler(ctx, TRUE, fetch_rfc822_size, NULL);
 		return TRUE;
 	}
 	if (strcmp(name+6, ".HEADER") == 0) {
 		ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER;
-		imap_fetch_add_handler(ctx, fetch_rfc822_header, NULL);
+		imap_fetch_add_handler(ctx, FALSE, fetch_rfc822_header, NULL);
 		return TRUE;
 	}
 	if (strcmp(name+6, ".TEXT") == 0) {
 		ctx->fetch_data |= MAIL_FETCH_STREAM_BODY;
 		ctx->flags_update_seen = TRUE;
-		imap_fetch_add_handler(ctx, fetch_rfc822_text, NULL);
+		imap_fetch_add_handler(ctx, FALSE, fetch_rfc822_text, NULL);
 		return TRUE;
 	}
 
