dovecot-2.2: pop3: Handle UIDL failures by disconnecting the cli...

dovecot at dovecot.org dovecot at dovecot.org
Mon Dec 2 18:48:05 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/0c9ab8cf9c1a
changeset: 17035:0c9ab8cf9c1a
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Dec 02 18:47:52 2013 +0200
description:
pop3: Handle UIDL failures by disconnecting the client instead of killing the whole process.

diffstat:

 src/pop3/pop3-commands.c |  80 ++++++++++++++++++++++++++++++++---------------
 1 files changed, 54 insertions(+), 26 deletions(-)

diffs (183 lines):

diff -r 5c170e0786f3 -r 0c9ab8cf9c1a src/pop3/pop3-commands.c
--- a/src/pop3/pop3-commands.c	Tue Nov 26 21:10:23 2013 +0100
+++ b/src/pop3/pop3-commands.c	Mon Dec 02 18:47:52 2013 +0200
@@ -558,7 +558,7 @@
 	bool list_all;
 };
 
-static void
+static int
 pop3_get_uid(struct client *client, struct mail *mail, string_t *str,
 	     bool *permanent_uidl_r)
 {
@@ -579,7 +579,7 @@
 		str_append(str, uidl);
 		/* UIDL is already permanent */
 		*permanent_uidl_r = TRUE;
-		return;
+		return 0;
 	}
 
 	*permanent_uidl_r = FALSE;
@@ -587,7 +587,7 @@
 	if (client->set->pop3_reuse_xuidl &&
 	    mail_get_first_header(mail, "X-UIDL", &uidl) > 0) {
 		str_append(str, uidl);
-		return;
+		return 0;
 	}
 
 	tab = t_malloc(sizeof(static_tab));
@@ -595,39 +595,48 @@
 	tab[0].value = t_strdup_printf("%u", client->uid_validity);
 
 	if ((client->uidl_keymask & UIDL_UID) != 0) {
-		if (i_snprintf(uid_str, sizeof(uid_str), "%u",
-			       mail->uid) < 0)
+		if (i_snprintf(uid_str, sizeof(uid_str), "%u", mail->uid) < 0)
 			i_unreached();
 		tab[1].value = uid_str;
 	}
 	if ((client->uidl_keymask & UIDL_MD5) != 0) {
 		if (mail_get_special(mail, MAIL_FETCH_HEADER_MD5,
-				     &tab[2].value) < 0 ||
-		    *tab[2].value == '\0') {
-			/* broken */
-			i_fatal("UIDL: Header MD5 not found "
+				     &tab[2].value) < 0) {
+			i_error("UIDL: Header MD5 lookup failed: %s",
+				mailbox_get_last_error(mail->box, NULL));
+			return -1;
+		} else if (*tab[2].value == '\0') {
+			i_error("UIDL: Header MD5 not found "
 				"(pop3_uidl_format=%%m not supported by storage?)");
+			return -1;
 		}
 	}
 	if ((client->uidl_keymask & UIDL_FILE_NAME) != 0) {
 		if (mail_get_special(mail, MAIL_FETCH_UIDL_FILE_NAME,
-				     &tab[3].value) < 0 ||
-		    *tab[3].value == '\0') {
-			/* broken */
-			i_fatal("UIDL: File name not found "
+				     &tab[3].value) < 0) {
+			i_error("UIDL: File name lookup failed: %s",
+				mailbox_get_last_error(mail->box, NULL));
+			return -1;
+		} else if (*tab[3].value == '\0') {
+			i_error("UIDL: File name not found "
 				"(pop3_uidl_format=%%f not supported by storage?)");
+			return -1;
 		}
 	}
 	if ((client->uidl_keymask & UIDL_GUID) != 0) {
 		if (mail_get_special(mail, MAIL_FETCH_GUID,
-				     &tab[4].value) < 0 ||
-		    *tab[4].value == '\0') {
-			/* broken */
-			i_fatal("UIDL: Message GUID not found "
+				     &tab[4].value) < 0) {
+			i_error("UIDL: Message GUID lookup failed: %s",
+				mailbox_get_last_error(mail->box, NULL));
+			return -1;
+		} else if (*tab[4].value == '\0') {
+			i_error("UIDL: Message GUID not found "
 				"(pop3_uidl_format=%%g not supported by storage?)");
+			return -1;
 		}
 	}
 	var_expand(str, client->mail_set->pop3_uidl_format, tab);
+	return 0;
 }
 
 static bool
@@ -669,6 +678,7 @@
 {
 	string_t *str;
 	bool permanent_uidl, found = FALSE;
+	bool failed = FALSE;
 
 	if (client->message_uidls != NULL)
 		return list_uidls_saved_iter(client, ctx);
@@ -677,8 +687,10 @@
 	while (mailbox_search_next(ctx->search_ctx, &ctx->mail)) {
 		uint32_t msgnum = ctx->msgnum++;
 
-		if (client_verify_ordering(client, ctx->mail, msgnum) < 0)
-			i_fatal("Can't finish POP3 UIDL command");
+		if (client_verify_ordering(client, ctx->mail, msgnum) < 0) {
+			failed = TRUE;
+			break;
+		}
 		if (client->deleted) {
 			if (client->deleted_bitmask[msgnum / CHAR_BIT] &
 			    (1 << (msgnum % CHAR_BIT)))
@@ -687,7 +699,10 @@
 		found = TRUE;
 
 		str_truncate(str, 0);
-		pop3_get_uid(client, ctx->mail, str, &permanent_uidl);
+		if (pop3_get_uid(client, ctx->mail, str, &permanent_uidl) < 0) {
+			failed = TRUE;
+			break;
+		}
 		if (client->set->pop3_save_uidl && !permanent_uidl)
 			mail_update_pop3_uidl(ctx->mail, str_c(str));
 
@@ -707,10 +722,12 @@
 
 	client->cmd = NULL;
 
-	if (ctx->list_all)
+	if (ctx->list_all && !failed)
 		client_send_line(client, ".");
 	i_free(ctx);
-	return found;
+	if (failed)
+		client_disconnect(client, "POP3 UIDLs couldn't be listed");
+	return found || failed;
 }
 
 static void cmd_uidl_callback(struct client *client)
@@ -749,7 +766,7 @@
 	char *uidl;
 	enum mail_fetch_field wanted_fields;
 	uint32_t msgnum;
-	bool permanent_uidl, uidl_duplicates_rename;
+	bool permanent_uidl, uidl_duplicates_rename, failed = FALSE;
 
 	i_assert(client->message_uidls == NULL);
 
@@ -772,11 +789,17 @@
 
 	str = t_str_new(128); msgnum = 0;
 	while (mailbox_search_next(search_ctx, &mail)) {
-		if (client_verify_ordering(client, mail, msgnum) < 0)
-			i_fatal("Can't finish POP3 UIDL command");
+		if (client_verify_ordering(client, mail, msgnum) < 0) {
+			failed = TRUE;
+			break;
+		}
 
 		str_truncate(str, 0);
-		pop3_get_uid(client, mail, str, &permanent_uidl);
+		if (pop3_get_uid(client, mail, str, &permanent_uidl) < 0) {
+			failed = TRUE;
+			break;
+		}
+
 		if (client->set->pop3_save_uidl && !permanent_uidl)
 			mail_update_pop3_uidl(mail, str_c(str));
 
@@ -789,6 +812,11 @@
 	}
 	(void)mailbox_search_deinit(&search_ctx);
 	hash_table_destroy(&prev_uidls);
+
+	if (failed) {
+		pool_unref(&client->uidl_pool);
+		client->message_uidls = NULL;
+	}
 }
 
 static struct cmd_uidl_context *


More information about the dovecot-cvs mailing list