[dovecot-cvs] dovecot/src/imap imap-fetch-body.c, 1.18, 1.19 imap-fetch.c, 1.38, 1.39 imap-fetch.h, 1.15, 1.16

cras at dovecot.org cras at dovecot.org
Fri Mar 18 20:49:56 EET 2005


Update of /var/lib/cvs/dovecot/src/imap
In directory talvi:/tmp/cvs-serv6206

Modified Files:
	imap-fetch-body.c imap-fetch.c imap-fetch.h 
Log Message:
Send buffered fetch items to client first. Fixes kmail and Thunderbird
issues..



Index: imap-fetch-body.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch-body.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- imap-fetch-body.c	15 Mar 2005 19:01:51 -0000	1.18
+++ imap-fetch-body.c	18 Mar 2005 18:49:53 -0000	1.19
@@ -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,8 +637,8 @@
 
 		if (strncmp(section, "HEADER.FIELDS.NOT ", 18) == 0 &&
 		    fetch_body_header_fields_check(section+18)) {
-			imap_fetch_add_handler(ctx, fetch_body_header_partial,
-					       body);
+			imap_fetch_add_handler(ctx, FALSE,
+					       fetch_body_header_partial, body);
 			return TRUE;
 		}
 	} else if (*section >= '0' && *section <= '9') {
@@ -655,7 +656,8 @@
 		     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;
 		}
 	}
@@ -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;
 	}
 

Index: imap-fetch.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- imap-fetch.c	15 Mar 2005 19:01:51 -0000	1.38
+++ imap-fetch.c	18 Mar 2005 18:49:53 -0000	1.39
@@ -93,22 +93,32 @@
 
 	ctx->cur_str = str_new(default_pool, 8192);
 	ctx->all_headers_buf = buffer_create_dynamic(cmd->pool, 128);
-	ctx->handlers = buffer_create_dynamic(cmd->pool, 128);
+	ARRAY_CREATE(&ctx->handlers, cmd->pool,
+		     struct imap_fetch_context_handler, 16);
 	ctx->line_finished = TRUE;
 	return ctx;
 }
 
-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)
 {
+	/* 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;
+	unsigned int i, size;
 
 	if (context == NULL) {
 		/* don't allow duplicate handlers */
-		handlers = buffer_get_data(ctx->handlers, &size);
-		size /= sizeof(*handlers);
+		handlers = array_get(&ctx->handlers, &size);
 
 		for (i = 0; i < size; i++) {
 			if (handlers[i].handler == handler &&
@@ -120,8 +130,15 @@
 	memset(&h, 0, sizeof(h));
 	h.handler = handler;
 	h.context = context;
+	h.buffered = buffered;
 
-	buffer_append(ctx->handlers, &h, sizeof(h));
+	if (!buffered)
+		array_append(&ctx->handlers, &h, 1);
+	else {
+		array_insert(&ctx->handlers, ctx->buffered_handlers_count,
+			     &h, 1);
+                ctx->buffered_handlers_count++;
+	}
 }
 
 void imap_fetch_begin(struct imap_fetch_context *ctx,
@@ -158,10 +175,34 @@
 		mailbox_search_init(ctx->trans, NULL, search_arg, NULL);
 }
 
+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;
-	size_t size;
+	unsigned int size;
 	int ret;
 
 	if (ctx->cont_handler != NULL) {
@@ -184,9 +225,7 @@
                 ctx->cur_handler++;
 	}
 
-	handlers = buffer_get_data(ctx->handlers, &size);
-	size /= sizeof(*handlers);
-
+	handlers = array_get(&ctx->handlers, &size);
 	for (;;) {
 		if (o_stream_get_buffer_used_size(ctx->client->output) >=
 		    CLIENT_OUTPUT_OPTIMAL_SIZE) {
@@ -208,18 +247,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++) {
+			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,
@@ -244,14 +284,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)
@@ -327,7 +364,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);
@@ -362,7 +399,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;
 }
 
@@ -394,7 +431,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;
 }
 
@@ -428,7 +465,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;
 }
 
@@ -452,7 +489,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;
 }
 
@@ -467,7 +504,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;
 }
 

Index: imap-fetch.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- imap-fetch.h	15 Mar 2005 19:01:51 -0000	1.15
+++ imap-fetch.h	18 Mar 2005 18:49:54 -0000	1.16
@@ -19,6 +19,7 @@
 struct imap_fetch_context_handler {
 	imap_fetch_handler_t *handler;
 	void *context;
+	int buffered;
 };
 
 struct imap_fetch_context {
@@ -34,7 +35,8 @@
 	buffer_t *all_headers_buf;
         struct mailbox_header_lookup_ctx *all_headers_ctx;
 
-	buffer_t *handlers;
+	array_t ARRAY_DEFINE(handlers, struct imap_fetch_context_handler);
+	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_command_context *cmd);



More information about the dovecot-cvs mailing list