dovecot-2.2: lib-mail: Added support for struct message_part <->...

dovecot at dovecot.org dovecot at dovecot.org
Thu Apr 17 14:13:34 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/e5635fc0710f
changeset: 17238:e5635fc0710f
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Apr 17 16:09:52 2014 +0200
description:
lib-mail: Added support for struct message_part <-> index number translations.

diffstat:

 src/lib-mail/Makefile.am              |   6 ++
 src/lib-mail/message-parser.c         |   4 +-
 src/lib-mail/message-part-serialize.c |   4 +-
 src/lib-mail/message-part.c           |  40 +++++++++++++++
 src/lib-mail/message-part.h           |  11 ++++
 src/lib-mail/test-message-part.c      |  93 +++++++++++++++++++++++++++++++++++
 6 files changed, 156 insertions(+), 2 deletions(-)

diffs (232 lines):

diff -r 63f12bb366b0 -r e5635fc0710f src/lib-mail/Makefile.am
--- a/src/lib-mail/Makefile.am	Thu Apr 17 16:04:13 2014 +0200
+++ b/src/lib-mail/Makefile.am	Thu Apr 17 16:09:52 2014 +0200
@@ -24,6 +24,7 @@
 	message-header-parser.c \
 	message-id.c \
 	message-parser.c \
+	message-part.c \
 	message-part-serialize.c \
 	message-search.c \
 	message-size.c \
@@ -77,6 +78,7 @@
 	test-message-header-parser \
 	test-message-id \
 	test-message-parser \
+	test-message-part \
 	test-quoted-printable \
 	test-rfc2231-parser
 
@@ -151,6 +153,10 @@
 test_message_parser_LDADD = message-parser.lo message-header-parser.lo message-size.lo rfc822-parser.lo rfc2231-parser.lo $(test_libs)
 test_message_parser_DEPENDENCIES = $(test_deps)
 
+test_message_part_SOURCES = test-message-part.c
+test_message_part_LDADD = message-part.lo message-parser.lo message-header-parser.lo message-size.lo rfc822-parser.lo rfc2231-parser.lo $(test_libs)
+test_message_part_DEPENDENCIES = $(test_deps)
+
 test_quoted_printable_SOURCES = test-quoted-printable.c
 test_quoted_printable_LDADD = quoted-printable.lo $(test_libs)
 test_quoted_printable_DEPENDENCIES = $(test_deps)
diff -r 63f12bb366b0 -r e5635fc0710f src/lib-mail/message-parser.c
--- a/src/lib-mail/message-parser.c	Thu Apr 17 16:04:13 2014 +0200
+++ b/src/lib-mail/message-parser.c	Thu Apr 17 16:09:52 2014 +0200
@@ -163,10 +163,12 @@
 static struct message_part *
 message_part_append(pool_t pool, struct message_part *parent)
 {
-	struct message_part *part, **list;
+	struct message_part *p, *part, **list;
 
 	part = p_new(pool, struct message_part, 1);
 	part->parent = parent;
+	for (p = parent; p != NULL; p = p->parent)
+		p->children_count++;
 
 	/* set child position */
 	part->physical_pos =
diff -r 63f12bb366b0 -r e5635fc0710f src/lib-mail/message-part-serialize.c
--- a/src/lib-mail/message-part-serialize.c	Thu Apr 17 16:04:13 2014 +0200
+++ b/src/lib-mail/message-part-serialize.c	Thu Apr 17 16:09:52 2014 +0200
@@ -123,7 +123,7 @@
 			      unsigned int siblings,
 			      struct message_part **part_r)
 {
-	struct message_part *part, *first_part, **next_part;
+	struct message_part *p, *part, *first_part, **next_part;
 	unsigned int children_count;
 	uoff_t pos;
 	bool root = parent == NULL;
@@ -135,6 +135,8 @@
 
 		part = p_new(ctx->pool, struct message_part, 1);
 		part->parent = parent;
+		for (p = parent; p != NULL; p = p->parent)
+			p->children_count++;
 
 		if (!read_next(ctx, &part->flags, sizeof(part->flags)))
 			return FALSE;
diff -r 63f12bb366b0 -r e5635fc0710f src/lib-mail/message-part.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-mail/message-part.c	Thu Apr 17 16:09:52 2014 +0200
@@ -0,0 +1,40 @@
+/* Copyright (c) 2014 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "message-part.h"
+
+unsigned int message_part_to_idx(const struct message_part *part)
+{
+	const struct message_part *p;
+	unsigned int n;
+
+	if (part->parent == NULL) {
+		/* root */
+		return 0;
+	}
+	for (n = 0, p = part->parent->children; p != part; p = p->next, n++)
+		;
+	return n + 1 + message_part_to_idx(part->parent);
+}
+
+static struct message_part *
+message_sub_part_by_idx(struct message_part *parts,
+			unsigned int idx)
+{
+	struct message_part *part = parts;
+
+	for (; part != NULL && idx > 0; part = part->next) {
+		if (part->children_count >= idx)
+			return message_sub_part_by_idx(part->children, idx-1);
+		idx -= part->children_count + 1;
+	}
+	return part;
+}
+
+struct message_part *
+message_part_by_idx(struct message_part *parts, unsigned int idx);
+{
+	i_assert(parts->parent == NULL);
+
+	return message_sub_part_by_idx(parts, idx);
+}
diff -r 63f12bb366b0 -r e5635fc0710f src/lib-mail/message-part.h
--- a/src/lib-mail/message-part.h	Thu Apr 17 16:04:13 2014 +0200
+++ b/src/lib-mail/message-part.h	Thu Apr 17 16:09:52 2014 +0200
@@ -31,8 +31,19 @@
 	struct message_size header_size;
 	struct message_size body_size;
 
+	/* total number of message_parts under children */
+	unsigned int children_count;
 	enum message_part_flags flags;
 	void *context;
 };
 
+/* Return index number for the message part. The indexes are in the same order
+   as they exist in the flat RFC822 message. The root part is 0, its first
+   child is 1 and so on. */
+unsigned int message_part_to_idx(const struct message_part *part);
+/* Find message part by its index number, or return NULL if the index
+   doesn't exist. */
+struct message_part *
+message_part_by_idx(struct message_part *parts, unsigned int idx);
+
 #endif
diff -r 63f12bb366b0 -r e5635fc0710f src/lib-mail/test-message-part.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-mail/test-message-part.c	Thu Apr 17 16:09:52 2014 +0200
@@ -0,0 +1,93 @@
+/* Copyright (c) 2014 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "istream.h"
+#include "message-parser.h"
+#include "test-common.h"
+
+static const char test_msg[] =
+"From user at domain  Fri Feb 22 17:06:23 2008\n"
+"From: user at domain.org\n"
+"Date: Sat, 24 Mar 2007 23:00:00 +0200\n"
+"Mime-Version: 1.0\n"
+"Content-Type: multipart/mixed; boundary=\"foo bar\"\n"
+"\n"
+"Root MIME prologue\n"
+"\n"
+"--foo bar\n"
+"Content-Type: text/x-myown; charset=us-ascii\n"
+"\n"
+"hello\n"
+"\n"
+"--foo bar\n"
+"Content-Type: message/rfc822\n"
+"\n"
+"From: sub at domain.org\n"
+"Date: Sun, 12 Aug 2012 12:34:56 +0300\n"
+"Subject: submsg\n"
+"Content-Type: multipart/alternative; boundary=\"sub1\"\n"
+"\n"
+"Sub MIME prologue\n"
+"--sub1\n"
+"Content-Type: text/html\n"
+"\n"
+"<p>Hello world</p>\n"
+"\n"
+"--sub1\n"
+"Content-Type: text/plain\n"
+"\n"
+"Hello another world\n"
+"\n"
+"--sub1--\n"
+"Sub MIME epilogue\n"
+"\n"
+"--foo bar--\n"
+"Root MIME epilogue\n"
+"\n";
+#define TEST_MSG_LEN (sizeof(test_msg)-1)
+
+static void test_message_part_idx(void)
+{
+	struct message_parser_ctx *parser;
+	struct istream *input;
+	struct message_part *parts, *part, *prev_part;
+	struct message_block block;
+	unsigned int i;
+	pool_t pool;
+	int ret;
+
+	test_begin("message part indexes");
+	pool = pool_alloconly_create("message parser", 10240);
+	input = i_stream_create_from_data(test_msg, TEST_MSG_LEN);
+
+	parser = message_parser_init(pool, input, 0, 0);
+	while ((ret = message_parser_parse_next_block(parser, &block)) > 0) ;
+	test_assert(ret < 0);
+	test_assert(message_parser_deinit(&parser, &parts) == 0);
+
+	part = message_part_by_idx(parts, 0);
+	test_assert(part == parts);
+	test_assert(message_part_by_idx(parts, 1) == parts->children);
+
+	for (i = 1; i < 6; i++) {
+		prev_part = part;
+		part = message_part_by_idx(parts, i);
+		test_assert(part != NULL);
+		test_assert(message_part_to_idx(part) == i);
+		test_assert(prev_part->physical_pos < part->physical_pos);
+	}
+	test_assert(message_part_by_idx(parts, i) == NULL);
+
+	i_stream_unref(&input);
+	pool_unref(&pool);
+	test_end();
+}
+
+int main(void)
+{
+	static void (*test_functions[])(void) = {
+		test_message_part_idx,
+		NULL
+	};
+	return test_run(test_functions);
+}


More information about the dovecot-cvs mailing list