dovecot-2.2: imap_body_parse_from_bodystructure() now returns th...

dovecot at dovecot.org dovecot at dovecot.org
Sat Sep 15 16:13:09 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/6acd8b149709
changeset: 15056:6acd8b149709
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Sep 15 16:13:02 2012 +0300
description:
imap_body_parse_from_bodystructure() now returns the error instead of logging it.

diffstat:

 src/lib-imap/imap-bodystructure.c  |  119 ++++++++++++++++++++++--------------
 src/lib-imap/imap-bodystructure.h  |    7 +-
 src/lib-storage/index/index-mail.c |   10 ++-
 3 files changed, 82 insertions(+), 54 deletions(-)

diffs (271 lines):

diff -r c436a6c3f7d2 -r 6acd8b149709 src/lib-imap/imap-bodystructure.c
--- a/src/lib-imap/imap-bodystructure.c	Sat Sep 15 15:46:01 2012 +0300
+++ b/src/lib-imap/imap-bodystructure.c	Sat Sep 15 16:13:02 2012 +0300
@@ -533,7 +533,7 @@
 	}
 }
 
-static bool str_append_imap_arg(string_t *str, const struct imap_arg *arg)
+static bool str_append_nstring(string_t *str, const struct imap_arg *arg)
 {
 	const char *cstr;
 
@@ -566,19 +566,20 @@
 	return TRUE;
 }
 
-static bool imap_write_list(const struct imap_arg *args, string_t *str)
+static void imap_write_list(const struct imap_arg *args, string_t *str)
 {
 	const struct imap_arg *children;
 
 	/* don't do any typechecking, just write it out */
 	str_append_c(str, '(');
 	while (!IMAP_ARG_IS_EOL(args)) {
-		if (!str_append_imap_arg(str, args)) {
-			if (!imap_arg_get_list(args, &children))
-				return FALSE;
+		if (!str_append_nstring(str, args)) {
+			if (!imap_arg_get_list(args, &children)) {
+				/* everything is either nstring or list */
+				i_unreached();
+			}
 
-			if (!imap_write_list(children, str))
-				return FALSE;
+			imap_write_list(children, str);
 		}
 		args++;
 
@@ -586,11 +587,10 @@
 			str_append_c(str, ' ');
 	}
 	str_append_c(str, ')');
-	return TRUE;
 }
 
-static bool imap_parse_bodystructure_args(const struct imap_arg *args,
-					  string_t *str)
+static int imap_parse_bodystructure_args(const struct imap_arg *args,
+					 string_t *str, const char **error_r)
 {
 	const struct imap_arg *subargs;
 	const struct imap_arg *list_args;
@@ -602,8 +602,8 @@
 	while (args->type == IMAP_ARG_LIST) {
 		str_append_c(str, '(');
 		list_args = imap_arg_as_list(args);
-		if (!imap_parse_bodystructure_args(list_args, str))
-			return FALSE;
+		if (imap_parse_bodystructure_args(list_args, str, error_r) < 0)
+			return -1;
 		str_append_c(str, ')');
 
 		multipart = TRUE;
@@ -613,19 +613,25 @@
 	if (multipart) {
 		/* next is subtype of Content-Type. rest is skipped. */
 		str_append_c(str, ' ');
-		return str_append_imap_arg(str, args);
+		if (!str_append_nstring(str, args)) {
+			*error_r = "Invalid multipart content-type";
+			return -1;
+		}
+		return 0;
 	}
 
 	/* "content type" "subtype" */
 	if (!imap_arg_get_astring(&args[0], &content_type) ||
-	    !imap_arg_get_astring(&args[1], &subtype))
-		return FALSE;
+	    !imap_arg_get_astring(&args[1], &subtype)) {
+		*error_r = "Invalid content-type";
+		return -1;
+	}
 
-	if (!str_append_imap_arg(str, &args[0]))
-		return FALSE;
+	if (!str_append_nstring(str, &args[0]))
+		i_unreached();
 	str_append_c(str, ' ');
-	if (!str_append_imap_arg(str, &args[1]))
-		return FALSE;
+	if (!str_append_nstring(str, &args[1]))
+		i_unreached();
 
 	text = strcasecmp(content_type, "text") == 0;
 	message_rfc822 = strcasecmp(content_type, "message") == 0 &&
@@ -637,11 +643,15 @@
 	if (imap_arg_get_list(args, &subargs)) {
 		str_append(str, " (");
 		while (!IMAP_ARG_IS_EOL(subargs)) {
-			if (!str_append_imap_arg(str, &subargs[0]))
-				return FALSE;
+			if (!str_append_nstring(str, &subargs[0])) {
+				*error_r = "Invalid content param key";
+				return -1;
+			}
 			str_append_c(str, ' ');
-			if (!str_append_imap_arg(str, &subargs[1]))
-				return FALSE;
+			if (!str_append_nstring(str, &subargs[1])) {
+				*error_r = "Invalid content param value";
+				return -1;
+			}
 
 			subargs += 2;
 			if (IMAP_ARG_IS_EOL(subargs))
@@ -652,7 +662,8 @@
 	} else if (args->type == IMAP_ARG_NIL) {
 		str_append(str, " NIL");
 	} else {
-		return FALSE;
+		*error_r = "list/NIL expected";
+		return -1;
 	}
 	args++;
 
@@ -660,14 +671,18 @@
 	for (i = 0; i < 4; i++, args++) {
 		str_append_c(str, ' ');
 
-		if (!str_append_imap_arg(str, args))
-			return FALSE;
+		if (!str_append_nstring(str, args)) {
+			*error_r = "nstring expected";
+			return -1;
+		}
 	}
 
 	if (text) {
 		/* text/xxx - text lines */
-		if (!imap_arg_get_atom(args, &value))
-			return FALSE;
+		if (!imap_arg_get_atom(args, &value)) {
+			*error_r = "Text lines expected";
+			return -1;
+		}
 
 		str_append_c(str, ' ');
 		str_append(str, value);
@@ -675,33 +690,37 @@
 		/* message/rfc822 - envelope + bodystructure + text lines */
 		str_append_c(str, ' ');
 
-		if (!imap_arg_get_list(&args[0], &list_args))
-			return FALSE;
-		if (!imap_write_list(list_args, str))
-			return FALSE;
-
+		if (!imap_arg_get_list(&args[0], &list_args)) {
+			*error_r = "Envelope list expected";
+			return -1;
+		}
+		imap_write_list(list_args, str);
 		str_append(str, " (");
 
-		if (!imap_arg_get_list(&args[1], &list_args))
-			return FALSE;
-		if (!imap_parse_bodystructure_args(list_args, str))
-			return FALSE;
+		if (!imap_arg_get_list(&args[1], &list_args)) {
+			*error_r = "Child bodystructure list expected";
+			return -1;
+		}
+		if (imap_parse_bodystructure_args(list_args, str, error_r) < 0)
+			return -1;
 
 		str_append(str, ") ");
-		if (!imap_arg_get_atom(&args[2], &value))
-			return FALSE;
+		if (!imap_arg_get_atom(&args[2], &value)) {
+			*error_r = "Text lines expected";
+			return -1;
+		}
 		str_append(str, value);
 	}
-
-	return TRUE;
+	return 0;
 }
 
-bool imap_body_parse_from_bodystructure(const char *bodystructure,
-					string_t *dest)
+int imap_body_parse_from_bodystructure(const char *bodystructure,
+				       string_t *dest, const char **error_r)
 {
 	struct istream *input;
 	struct imap_parser *parser;
 	const struct imap_arg *args;
+	bool fatal;
 	int ret;
 
 	input = i_stream_create_from_data(bodystructure, strlen(bodystructure));
@@ -710,12 +729,16 @@
 	parser = imap_parser_create(input, NULL, (size_t)-1);
 	ret = imap_parser_finish_line(parser, 0, IMAP_PARSE_FLAG_NO_UNESCAPE |
 				      IMAP_PARSE_FLAG_LITERAL_TYPE, &args);
-	ret = ret > 0 && imap_parse_bodystructure_args(args, dest);
-
-	if (!ret)
-		i_error("Error parsing IMAP bodystructure: %s", bodystructure);
+	if (ret < 0) {
+		*error_r = t_strdup_printf("IMAP parser failed: %s",
+					   imap_parser_get_error(parser, &fatal));
+	} else if (ret == 0) {
+		*error_r = "Empty bodystructure";
+	} else {
+		ret = imap_parse_bodystructure_args(args, dest, error_r);
+	}
 
 	imap_parser_unref(&parser);
 	i_stream_destroy(&input);
-	return ret;
+	return ret <= 0 ? -1 : 0;
 }
diff -r c436a6c3f7d2 -r 6acd8b149709 src/lib-imap/imap-bodystructure.h
--- a/src/lib-imap/imap-bodystructure.h	Sat Sep 15 15:46:01 2012 +0300
+++ b/src/lib-imap/imap-bodystructure.h	Sat Sep 15 16:13:02 2012 +0300
@@ -16,8 +16,9 @@
 void imap_bodystructure_write(const struct message_part *part,
 			      string_t *dest, bool extended);
 
-/* Return BODY part from BODYSTRUCTURE */
-bool imap_body_parse_from_bodystructure(const char *bodystructure,
-					string_t *dest);
+/* Get BODY part from BODYSTRUCTURE and write it to dest.
+   Returns 0 if ok, -1 if bodystructure wasn't valid. */
+int imap_body_parse_from_bodystructure(const char *bodystructure,
+				       string_t *dest, const char **error_r);
 
 #endif
diff -r c436a6c3f7d2 -r 6acd8b149709 src/lib-storage/index/index-mail.c
--- a/src/lib-storage/index/index-mail.c	Sat Sep 15 15:46:01 2012 +0300
+++ b/src/lib-storage/index/index-mail.c	Sat Sep 15 16:13:02 2012 +0300
@@ -1035,6 +1035,7 @@
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
 	const struct mail_cache_field *cache_fields = mail->ibox->cache_fields;
+	const char *error;
 	string_t *str;
 
 	switch (field) {
@@ -1071,12 +1072,15 @@
 			str_truncate(str, 0);
 
 			if (imap_body_parse_from_bodystructure(
-						data->bodystructure, str))
-				data->body = str_c(str);
-			else {
+					data->bodystructure, str, &error) < 0) {
 				/* broken, continue.. */
+				mail_storage_set_critical(_mail->box->storage,
+					"Invalid BODYSTRUCTURE %s: %s",
+					data->bodystructure, error);
 				mail_set_cache_corrupted(_mail,
 					MAIL_FETCH_IMAP_BODYSTRUCTURE);
+			} else {
+				data->body = str_c(str);
 			}
 		}
 


More information about the dovecot-cvs mailing list