dovecot-2.2: lib-imap: Added support for parsing IMAP BODYSTRUCT...

dovecot at dovecot.org dovecot at dovecot.org
Sat Sep 15 19:00:53 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/d1f084a39708
changeset: 15057:d1f084a39708
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Sep 15 18:58:48 2012 +0300
description:
lib-imap: Added support for parsing IMAP BODYSTRUCTURE and writing out a modified version.

diffstat:

 src/lib-imap/Makefile.am               |    5 +
 src/lib-imap/imap-bodystructure.c      |  483 +++++++++++++++++++++++++-------
 src/lib-imap/imap-bodystructure.h      |   28 +
 src/lib-imap/test-imap-bodystructure.c |  143 +++++++++
 4 files changed, 551 insertions(+), 108 deletions(-)

diffs (truncated from 807 to 300 lines):

diff -r 6acd8b149709 -r d1f084a39708 src/lib-imap/Makefile.am
--- a/src/lib-imap/Makefile.am	Sat Sep 15 16:13:02 2012 +0300
+++ b/src/lib-imap/Makefile.am	Sat Sep 15 18:58:48 2012 +0300
@@ -41,6 +41,7 @@
 pkginc_lib_HEADERS = $(headers)
 
 test_programs = \
+	test-imap-bodystructure \
 	test-imap-match \
 	test-imap-parser \
 	test-imap-url \
@@ -53,6 +54,10 @@
 	../lib-test/libtest.la \
 	../lib/liblib.la
 
+test_imap_bodystructure_SOURCES = test-imap-bodystructure.c
+test_imap_bodystructure_LDADD = imap-bodystructure.lo imap-envelope.lo imap-quote.lo imap-parser.lo imap-arg.lo ../lib-mail/libmail.la $(test_libs)
+test_imap_bodystructure_DEPENDENCIES = imap-bodystructure.lo imap-envelope.lo imap-quote.lo imap-parser.lo imap-arg.lo ../lib-mail/libmail.la $(test_libs)
+
 test_imap_match_SOURCES = test-imap-match.c
 test_imap_match_LDADD = imap-match.lo $(test_libs)
 test_imap_match_DEPENDENCIES = imap-match.lo $(test_libs)
diff -r 6acd8b149709 -r d1f084a39708 src/lib-imap/imap-bodystructure.c
--- a/src/lib-imap/imap-bodystructure.c	Sat Sep 15 16:13:02 2012 +0300
+++ b/src/lib-imap/imap-bodystructure.c	Sat Sep 15 18:58:48 2012 +0300
@@ -18,21 +18,7 @@
 #define EMPTY_BODYSTRUCTURE \
         "(\"text\" \"plain\" ("DEFAULT_CHARSET") NIL NIL \"7bit\" 0 0)"
 
-struct message_part_body_data {
-	pool_t pool;
-	const char *content_type, *content_subtype;
-	const char *content_type_params;
-	const char *content_transfer_encoding;
-	const char *content_id;
-	const char *content_description;
-	const char *content_disposition;
-	const char *content_disposition_params;
-	const char *content_md5;
-	const char *content_language;
-	const char *content_location;
-
-	struct message_part_envelope_data *envelope;
-};
+#define NVL(str, nullstr) ((str) != NULL ? (str) : (nullstr))
 
 static void parse_content_type(struct message_part_body_data *data,
 			       struct message_header_line *hdr)
@@ -290,39 +276,21 @@
 	}
 }
 
-static void part_write_body_multipart(const struct message_part *part,
-				      string_t *str, bool extended)
+static void
+imap_bodystructure_write_siblings(const struct message_part *part,
+				  string_t *dest, bool extended)
 {
-	struct message_part_body_data *data = part->context;
+	for (; part != NULL; part = part->next) {
+		str_append_c(dest, '(');
+		imap_bodystructure_write(part, dest, extended);
+		str_append_c(dest, ')');
+	}
+}
 
-	if (part->children != NULL)
-		imap_bodystructure_write(part->children, str, extended);
-	else {
-		/* no parts in multipart message,
-		   that's not allowed. write a single
-		   0-length text/plain structure */
-		str_append(str, EMPTY_BODYSTRUCTURE);
-	}
-
-	str_append_c(str, ' ');
-	if (data->content_subtype != NULL)
-		str_append(str, data->content_subtype);
-	else
-		str_append(str, "\"x-unknown\"");
-
-	if (!extended)
-		return;
-
-	/* BODYSTRUCTURE data */
-	str_append_c(str, ' ');
-	if (data->content_type_params == NULL)
-		str_append(str, "NIL");
-	else {
-		str_append_c(str, '(');
-		str_append(str, data->content_type_params);
-		str_append_c(str, ')');
-	}
-
+static void
+part_write_bodystructure_data_common(struct message_part_body_data *data,
+				     string_t *str)
+{
 	str_append_c(str, ' ');
 	if (data->content_disposition == NULL)
 		str_append(str, "NIL");
@@ -351,16 +319,48 @@
 	}
 
 	str_append_c(str, ' ');
-	if (data->content_location == NULL)
+	str_append(str, NVL(data->content_location, "NIL"));
+}
+
+static void part_write_body_multipart(const struct message_part *part,
+				      string_t *str, bool extended)
+{
+	struct message_part_body_data *data = part->context;
+
+	if (part->children != NULL)
+		imap_bodystructure_write_siblings(part->children, str, extended);
+	else {
+		/* no parts in multipart message,
+		   that's not allowed. write a single
+		   0-length text/plain structure */
+		str_append(str, EMPTY_BODYSTRUCTURE);
+	}
+
+	str_append_c(str, ' ');
+	if (data->content_subtype != NULL)
+		str_append(str, data->content_subtype);
+	else
+		str_append(str, "\"x-unknown\"");
+
+	if (!extended)
+		return;
+
+	/* BODYSTRUCTURE data */
+	str_append_c(str, ' ');
+	if (data->content_type_params == NULL)
 		str_append(str, "NIL");
-	else
-		str_append(str, data->content_location);
+	else {
+		str_append_c(str, '(');
+		str_append(str, data->content_type_params);
+		str_append_c(str, ')');
+	}
+
+	part_write_bodystructure_data_common(data, str);
 }
 
 static void part_write_body(const struct message_part *part,
 			    string_t *str, bool extended)
 {
-#define NVL(str, nullstr) ((str) != NULL ? (str) : (nullstr))
 	struct message_part_body_data *data = part->context;
 	bool text;
 
@@ -410,19 +410,20 @@
 	} else if (part->flags & MESSAGE_PART_FLAG_MESSAGE_RFC822) {
 		/* message/rfc822 contains envelope + body + line count */
 		struct message_part_body_data *child_data;
-                struct message_part_envelope_data *env_data;
 
 		i_assert(part->children != NULL);
 		i_assert(part->children->next == NULL);
 
                 child_data = part->children->context;
-		env_data = child_data->envelope;
 
 		str_append(str, " (");
-		imap_envelope_write_part_data(env_data, str);
+		if (child_data->envelope_str != NULL)
+			str_append(str, child_data->envelope_str);
+		else
+			imap_envelope_write_part_data(child_data->envelope, str);
 		str_append(str, ") ");
 
-		imap_bodystructure_write(part->children, str, extended);
+		imap_bodystructure_write_siblings(part->children, str, extended);
 		str_printfa(str, " %u", part->body_size.lines);
 	}
 
@@ -435,40 +436,7 @@
 	   ("body" "language" "params") "location" */
 	str_append_c(str, ' ');
 	str_append(str, NVL(data->content_md5, "NIL"));
-
-	str_append_c(str, ' ');
-	if (data->content_disposition == NULL)
-		str_append(str, "NIL");
-	else {
-		str_append_c(str, '(');
-		str_append(str, data->content_disposition);
-		str_append_c(str, ' ');
-
-		if (data->content_disposition_params == NULL)
-			str_append(str, "NIL");
-		else {
-			str_append_c(str, '(');
-			str_append(str, data->content_disposition_params);
-			str_append_c(str, ')');
-		}
-
-		str_append_c(str, ')');
-	}
-
-	str_append_c(str, ' ');
-	if (data->content_language == NULL)
-		str_append(str, "NIL");
-	else {
-		str_append_c(str, '(');
-		str_append(str, data->content_language);
-		str_append_c(str, ')');
-	}
-
-	str_append_c(str, ' ');
-	if (data->content_location == NULL)
-		str_append(str, "NIL");
-	else
-		str_append(str, data->content_location);
+	part_write_bodystructure_data_common(data, str);
 }
 
 bool imap_bodystructure_is_plain_7bit(const struct message_part *part)
@@ -515,22 +483,10 @@
 void imap_bodystructure_write(const struct message_part *part,
 			      string_t *dest, bool extended)
 {
-	i_assert(part->parent != NULL || part->next == NULL);
-
-	while (part != NULL) {
-		if (part->parent != NULL)
-			str_append_c(dest, '(');
-
-		if (part->flags & MESSAGE_PART_FLAG_MULTIPART)
-			part_write_body_multipart(part, dest, extended);
-		else
-			part_write_body(part, dest, extended);
-
-		if (part->parent != NULL)
-			str_append_c(dest, ')');
-
-		part = part->next;
-	}
+	if (part->flags & MESSAGE_PART_FLAG_MULTIPART)
+		part_write_body_multipart(part, dest, extended);
+	else
+		part_write_body(part, dest, extended);
 }
 
 static bool str_append_nstring(string_t *str, const struct imap_arg *arg)
@@ -566,12 +522,27 @@
 	return TRUE;
 }
 
+static bool
+get_nstring(const struct imap_arg *arg, pool_t pool, string_t *tmpstr,
+	    const char **value_r)
+{
+	if (arg->type == IMAP_ARG_NIL) {
+		*value_r = NULL;
+		return TRUE;
+	}
+
+	str_truncate(tmpstr, 0);
+	if (!str_append_nstring(tmpstr, arg))
+		return FALSE;
+	*value_r = p_strdup(pool, str_c(tmpstr));
+	return TRUE;
+}
+
 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_nstring(str, args)) {
 			if (!imap_arg_get_list(args, &children)) {
@@ -579,14 +550,308 @@
 				i_unreached();
 			}
 
+			str_append_c(str, '(');
 			imap_write_list(children, str);
+			str_append_c(str, ')');
 		}
 		args++;
 
 		if (!IMAP_ARG_IS_EOL(args))
 			str_append_c(str, ' ');
 	}
-	str_append_c(str, ')');
+}
+
+static int imap_write_nstring_list(const struct imap_arg *args, string_t *str)
+{
+	str_truncate(str, 0);
+	while (!IMAP_ARG_IS_EOL(args)) {
+		if (!str_append_nstring(str, &args[0]))
+			return -1;
+		str_append_c(str, ' ');


More information about the dovecot-cvs mailing list