[dovecot-cvs] dovecot/src/imap cmd-fetch.c, 1.33, 1.34 imap-fetch-body.c, 1.29, 1.30 imap-fetch.c, 1.52, 1.53 imap-fetch.h, 1.23, 1.24

tss at dovecot.org tss at dovecot.org
Thu Dec 28 18:40:33 UTC 2006


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

Modified Files:
	cmd-fetch.c imap-fetch-body.c imap-fetch.c imap-fetch.h 
Log Message:
When client fetches message data that has already been expunged, reply with
dummy NIL and such values for the message. Don't disconnect the client 
anymore.


Index: cmd-fetch.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/cmd-fetch.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- cmd-fetch.c	20 Dec 2006 19:23:46 -0000	1.33
+++ cmd-fetch.c	28 Dec 2006 18:40:29 -0000	1.34
@@ -72,15 +72,11 @@
 {
 	struct client_command_context *cmd = ctx->cmd;
 	static const char *ok_message = "OK Fetch completed.";
-	bool failed, partial;
-
-	partial = ctx->partial_fetch;
-	failed = ctx->failed;
 
 	if (imap_fetch_deinit(ctx) < 0)
-		failed = TRUE;
+		ctx->failed = TRUE;
 
-	if (failed || (partial && !cmd->uid)) {
+	if (ctx->failed) {
 		struct mail_storage *storage;
 		const char *error;
 		bool syntax, temporary_error;
@@ -96,10 +92,6 @@
 		if (!syntax) {
 			/* We never want to reply NO to FETCH requests,
 			   BYE is preferrable (see imap-ml for reasons). */
-			if (partial) {
-				error = "Out of sync: "
-					"Trying to fetch expunged message";
-			}
 			client_disconnect_with_error(cmd->client, error);
 		} else {
 			/* user error, we'll reply with BAD */

Index: imap-fetch-body.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch-body.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- imap-fetch-body.c	15 Dec 2006 18:38:10 -0000	1.29
+++ imap-fetch-body.c	28 Dec 2006 18:40:29 -0000	1.30
@@ -83,6 +83,17 @@
 	return size <= body->max_size ? size : body->max_size;
 }
 
+static const char *get_body_name(const struct imap_fetch_body_data *body)
+{
+	string_t *str;
+
+	str = t_str_new(128);
+	str_printfa(str, "BODY[%s]", body->section);
+	if (body->skip_set)
+		str_printfa(str, "<%"PRIuUOFF_T">", body->skip);
+	return str_c(str);
+}
+
 static string_t *get_prefix(struct imap_fetch_context *ctx,
 			    const struct imap_fetch_body_data *body,
 			    uoff_t size)
@@ -95,9 +106,7 @@
 	else
 		str_append_c(str, ' ');
 
-	str_printfa(str, "BODY[%s]", body->section);
-	if (body->skip_set)
-		str_printfa(str, "<%"PRIuUOFF_T">", body->skip);
+	str_append(str, get_body_name(body));
 
 	if (size != (uoff_t)-1)
 		str_printfa(str, " {%"PRIuUOFF_T"}\r\n", size);
@@ -583,16 +592,17 @@
 					  struct imap_fetch_body_data *body,
 					  const char *section)
 {
-	const char *const *arr;
+	const char *const *arr, *name;
 
 	if (!fetch_body_header_fields_check(section))
 		return FALSE;
 
+	name = get_body_name(body);
 	if ((ctx->fetch_data & (MAIL_FETCH_STREAM_HEADER |
 				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, FALSE, FALSE,
+		imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL",
 				       fetch_body_header_partial, body);
 		return TRUE;
 	}
@@ -605,7 +615,7 @@
 	}
 
 	body->header_ctx = mailbox_header_lookup_init(ctx->box, body->fields);
-	imap_fetch_add_handler(ctx, FALSE, TRUE,
+	imap_fetch_add_handler(ctx, FALSE, TRUE, name, "NIL",
 			       fetch_body_header_fields, body);
 	t_pop();
 	return TRUE;
@@ -614,18 +624,21 @@
 static bool fetch_body_section_name_init(struct imap_fetch_context *ctx,
 					 struct imap_fetch_body_data *body)
 {
-	const char *section = body->section;
+	const char *name, *section = body->section;
 
+	name = get_body_name(body);
 	if (*section == '\0') {
 		ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER |
 			MAIL_FETCH_STREAM_BODY;
-		imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_body, body);
+		imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL",
+				       fetch_body, body);
 		return TRUE;
 	}
 
 	if (strcmp(section, "TEXT") == 0) {
 		ctx->fetch_data |= MAIL_FETCH_STREAM_BODY;
-		imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_body, body);
+		imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL",
+				       fetch_body, body);
 		return TRUE;
 	}
 
@@ -633,7 +646,7 @@
 		/* exact header matches could be cached */
 		if (section[6] == '\0') {
 			ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER;
-			imap_fetch_add_handler(ctx, FALSE, FALSE,
+			imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL",
 					       fetch_body, body);
 			return TRUE;
 		}
@@ -644,7 +657,7 @@
 
 		if (strncmp(section, "HEADER.FIELDS.NOT ", 18) == 0 &&
 		    fetch_body_header_fields_check(section+18)) {
-			imap_fetch_add_handler(ctx, FALSE, FALSE,
+			imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL",
 					       fetch_body_header_partial, body);
 			return TRUE;
 		}
@@ -663,7 +676,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, FALSE, FALSE,
+			imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL",
 					       fetch_body_mime, body);
 			return TRUE;
 		}
@@ -927,26 +940,27 @@
 		ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER |
 			MAIL_FETCH_STREAM_BODY;
 		ctx->flags_update_seen = TRUE;
-		imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_rfc822, NULL);
+		imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL",
+				       fetch_rfc822, NULL);
 		return TRUE;
 	}
 
 	if (strcmp(name+6, ".SIZE") == 0) {
 		ctx->fetch_data |= MAIL_FETCH_VIRTUAL_SIZE;
-		imap_fetch_add_handler(ctx, TRUE, FALSE,
+		imap_fetch_add_handler(ctx, TRUE, FALSE, name, "0",
 				       fetch_rfc822_size, NULL);
 		return TRUE;
 	}
 	if (strcmp(name+6, ".HEADER") == 0) {
 		ctx->fetch_data |= MAIL_FETCH_STREAM_HEADER;
-		imap_fetch_add_handler(ctx, FALSE, FALSE,
+		imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL",
 				       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, FALSE, FALSE,
+		imap_fetch_add_handler(ctx, FALSE, FALSE, name, "NIL",
 				       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.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- imap-fetch.c	28 Dec 2006 18:37:25 -0000	1.52
+++ imap-fetch.c	28 Dec 2006 18:40:29 -0000	1.53
@@ -15,6 +15,9 @@
 
 #include <stdlib.h>
 
+#define BODY_NIL_REPLY \
+	"\"text\" \"plain\" NIL NIL NIL \"7bit\" 0 0 NIL NIL NIL"
+
 const struct imap_fetch_handler default_handlers[7];
 static buffer_t *fetch_handlers = NULL;
 
@@ -102,6 +105,7 @@
 #undef imap_fetch_add_handler
 void imap_fetch_add_handler(struct imap_fetch_context *ctx,
 			    bool buffered, bool want_deinit,
+			    const char *name, const char *nil_reply,
 			    imap_fetch_handler_t *handler, void *context)
 {
 	/* partially because of broken clients, but also partially because
@@ -134,6 +138,8 @@
 	h.context = context;
 	h.buffered = buffered;
 	h.want_deinit = want_deinit;
+	h.name = p_strdup(ctx->cmd->pool, name);
+	h.nil_reply = p_strdup(ctx->cmd->pool, nil_reply);
 
 	if (!buffered)
 		array_append(&ctx->handlers, &h, 1);
@@ -183,8 +189,6 @@
 	const unsigned char *data;
 	size_t len;
 
-	i_assert(ctx->first);
-
 	data = str_data(ctx->cur_str);
 	len = str_len(ctx->cur_str);
 
@@ -202,11 +206,29 @@
 	return 0;
 }
 
+static int imap_fetch_send_nil_reply(struct imap_fetch_context *ctx)
+{
+	const struct imap_fetch_context_handler *handler;
+
+	if (!ctx->first)
+		str_append_c(ctx->cur_str, ' ');
+
+	handler = array_idx(&ctx->handlers, ctx->cur_handler);
+	str_printfa(ctx->cur_str, "%s %s ",
+		    handler->name, handler->nil_reply);
+
+	if (!handler->buffered) {
+		if (imap_fetch_flush_buffer(ctx) < 0)
+			return -1;
+	}
+	return 0;
+}
+
 int imap_fetch(struct imap_fetch_context *ctx)
 {
 	struct client *client = ctx->client;
 	const struct imap_fetch_context_handler *handlers;
-	unsigned int size;
+	unsigned int count;
 	int ret;
 
 	if (ctx->cont_handler != NULL) {
@@ -215,10 +237,14 @@
 			return 0;
 
 		if (ret < 0) {
+			if (ctx->client->output->closed)
+				return -1;
+
 			if (ctx->cur_mail->expunged) {
 				/* not an error, just lost it. */
 				ctx->partial_fetch = TRUE;
-				ctx->partial_fetch = TRUE;
+				if (imap_fetch_send_nil_reply(ctx) < 0)
+					return -1;
 			} else {
 				return -1;
 			}
@@ -234,7 +260,7 @@
 		 client->output_lock == ctx->cmd);
 	client->output_lock = ctx->cmd;
 
-	handlers = array_get(&ctx->handlers, &size);
+	handlers = array_get(&ctx->handlers, &count);
 	for (;;) {
 		if (o_stream_get_buffer_used_size(client->output) >=
 		    CLIENT_OUTPUT_OPTIMAL_SIZE) {
@@ -266,7 +292,7 @@
 			ctx->line_finished = FALSE;
 		}
 
-		for (; ctx->cur_handler < size; ctx->cur_handler++) {
+		for (; ctx->cur_handler < count; ctx->cur_handler++) {
 			if (str_len(ctx->cur_str) > 0 &&
 			    !handlers[ctx->cur_handler].buffered) {
 				/* first non-buffered handler.
@@ -294,6 +320,8 @@
 				if (ctx->cur_mail->expunged) {
 					/* not an error, just lost it. */
 					ctx->partial_fetch = TRUE;
+					if (imap_fetch_send_nil_reply(ctx) < 0)
+						return -1;
 				} else {
 					i_assert(ret < 0 ||
 						 ctx->cont_handler != NULL);
@@ -393,7 +421,8 @@
 {
 	if (name[4] == '\0') {
 		ctx->fetch_data |= MAIL_FETCH_IMAP_BODY;
-		imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_body, NULL);
+		imap_fetch_add_handler(ctx, FALSE, FALSE, name,
+				       "("BODY_NIL_REPLY")", fetch_body, NULL);
 		return TRUE;
 	}
 	return fetch_body_section_init(ctx, name, args);
@@ -424,11 +453,13 @@
 }
 
 static bool fetch_bodystructure_init(struct imap_fetch_context *ctx,
-				     const char *name __attr_unused__,
+				     const char *name,
 				     struct imap_arg **args __attr_unused__)
 {
 	ctx->fetch_data |= MAIL_FETCH_IMAP_BODYSTRUCTURE;
-	imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_bodystructure, NULL);
+	imap_fetch_add_handler(ctx, FALSE, FALSE, name,
+			       "("BODY_NIL_REPLY" NIL NIL NIL NIL)",
+			       fetch_bodystructure, NULL);
 	return TRUE;
 }
 
@@ -456,11 +487,13 @@
 }
 
 static bool fetch_envelope_init(struct imap_fetch_context *ctx,
-				const char *name __attr_unused__,
+				const char *name,
 				struct imap_arg **args __attr_unused__)
 {
 	ctx->fetch_data |= MAIL_FETCH_IMAP_ENVELOPE;
-	imap_fetch_add_handler(ctx, FALSE, FALSE, fetch_envelope, NULL);
+	imap_fetch_add_handler(ctx, FALSE, FALSE, name,
+			       "(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL)",
+			       fetch_envelope, NULL);
 	return TRUE;
 }
 
@@ -489,12 +522,12 @@
 }
 
 static bool fetch_flags_init(struct imap_fetch_context *ctx,
-			     const char *name __attr_unused__,
+			     const char *name,
 			     struct imap_arg **args __attr_unused__)
 {
 	ctx->flags_have_handler = TRUE;
 	ctx->fetch_data |= MAIL_FETCH_FLAGS;
-	imap_fetch_add_handler(ctx, TRUE, FALSE, fetch_flags, NULL);
+	imap_fetch_add_handler(ctx, TRUE, FALSE, name, "()", fetch_flags, NULL);
 	return TRUE;
 }
 
@@ -512,13 +545,14 @@
 	return 1;
 }
 
-
 static bool fetch_internaldate_init(struct imap_fetch_context *ctx,
-				    const char *name __attr_unused__,
+				    const char *name,
 				    struct imap_arg **args __attr_unused__)
 {
 	ctx->fetch_data |= MAIL_FETCH_RECEIVED_DATE;
-	imap_fetch_add_handler(ctx, TRUE, FALSE, fetch_internaldate, NULL);
+	imap_fetch_add_handler(ctx, TRUE, FALSE, name,
+			       "\"01-01-1970 00:00:00 +0000\"",
+			       fetch_internaldate, NULL);
 	return TRUE;
 }
 
@@ -530,10 +564,10 @@
 }
 
 static bool fetch_uid_init(struct imap_fetch_context *ctx __attr_unused__,
-			   const char *name __attr_unused__,
+			   const char *name,
 			   struct imap_arg **args __attr_unused__)
 {
-	imap_fetch_add_handler(ctx, TRUE, FALSE, fetch_uid, NULL);
+	imap_fetch_add_handler(ctx, TRUE, FALSE, name, NULL, fetch_uid, NULL);
 	return TRUE;
 }
 

Index: imap-fetch.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/imap-fetch.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- imap-fetch.h	20 Dec 2006 19:23:46 -0000	1.23
+++ imap-fetch.h	28 Dec 2006 18:40:29 -0000	1.24
@@ -20,6 +20,9 @@
 	imap_fetch_handler_t *handler;
 	void *context;
 
+	const char *name;
+	const char *nil_reply;
+
 	unsigned int buffered:1;
 	unsigned int want_deinit:1;
 };
@@ -68,16 +71,19 @@
 
 void imap_fetch_add_handler(struct imap_fetch_context *ctx,
 			    bool buffered, bool want_deinit,
+			    const char *name, const char *nil_reply,
 			    imap_fetch_handler_t *handler, void *context);
 #ifdef CONTEXT_TYPE_SAFETY
-#  define imap_fetch_add_handler(ctx, buffered, want_deinit, handler, context) \
+#  define imap_fetch_add_handler(ctx, buffered, want_deinit, name, nil_reply, \
+				 handler, context) \
 	({(void)(1 ? 0 : handler((struct imap_fetch_context *)NULL, \
 				 (struct mail *)NULL, context)); \
-	  imap_fetch_add_handler(ctx, buffered, want_deinit, \
+	  imap_fetch_add_handler(ctx, buffered, want_deinit, name, nil_reply, \
 		(imap_fetch_handler_t *)handler, context); })
 #else
-#  define imap_fetch_add_handler(ctx, buffered, want_deinit, handler, context) \
-	  imap_fetch_add_handler(ctx, buffered, want_deinit, \
+#  define imap_fetch_add_handler(ctx, buffered, want_deinit, name, nil_reply, \
+				 handler, context) \
+	  imap_fetch_add_handler(ctx, buffered, want_deinit, name, nil_reply, \
 		(imap_fetch_handler_t *)handler, context)
 #endif
 



More information about the dovecot-cvs mailing list