dovecot-2.0-pigeonhole: body extension: fixed handling of :conte...

pigeonhole at rename-it.nl pigeonhole at rename-it.nl
Sat Sep 17 10:05:05 EEST 2011


details:   http://hg.rename-it.nl/dovecot-2.0-pigeonhole/rev/f3a4ddd68bc8
changeset: 1532:f3a4ddd68bc8
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Wed Sep 14 17:17:15 2011 +0200
description:
body extension: fixed handling of :content message/rfc822.

diffstat:

 src/lib-sieve/plugins/body/ext-body-common.c |  88 +++++++++++++++++++++++------
 tests/extensions/body/content.svtest         |  19 +++++-
 2 files changed, 86 insertions(+), 21 deletions(-)

diffs (222 lines):

diff -r 5459f69f6aa2 -r f3a4ddd68bc8 src/lib-sieve/plugins/body/ext-body-common.c
--- a/src/lib-sieve/plugins/body/ext-body-common.c	Tue Sep 13 22:42:18 2011 +0200
+++ b/src/lib-sieve/plugins/body/ext-body-common.c	Wed Sep 14 17:17:15 2011 +0200
@@ -61,12 +61,14 @@
 	i_assert( wanted_types != NULL );
 
 	for (; *wanted_types != NULL; wanted_types++) {
-		const char *wanted_subtype = strchr(*wanted_types, '/');
+		const char *wanted_subtype;
 
 		if (**wanted_types == '\0') {
 			/* empty string matches everything */
 			return TRUE;
 		}
+
+		wanted_subtype = strchr(*wanted_types, '/');
 		if (wanted_subtype == NULL) {
 			/* match only main type */
 			if (strlen(*wanted_types) == type_len &&
@@ -112,7 +114,7 @@
 
 		/* Add new item to the result */
 		return_part = array_append_space(&ctx->return_body_parts);
-		
+
 		/* Depending on whether a decoded body part is requested, the appropriate
 		 * cache item is read. If it is missing, this function fails and the cache 
 		 * needs to be completed by ext_body_parts_add_missing().
@@ -134,7 +136,7 @@
 }
 
 static void ext_body_part_save
-(struct ext_body_message_context *ctx, struct message_part *part,
+(struct ext_body_message_context *ctx,
 	struct ext_body_part_cached *body_part, bool decoded)
 {
 	buffer_t *buf = ctx->tmp_buffer;
@@ -154,8 +156,6 @@
 	if ( !decoded ) {
 		body_part->raw_body = part_data;
 		body_part->raw_body_size = part_size;
-		printf("%ld <=> %ld\n", (long) buf->used - 1, (long) part->body_size.physical_size);
-		i_assert(buf->used - 1 == part->body_size.physical_size);
 	} else {
 		body_part->decoded_body = part_data;
 		body_part->decoded_body_size = part_size;
@@ -195,7 +195,7 @@
 (const struct sieve_message_data *msgdata, struct ext_body_message_context *ctx, 
 	const char * const *content_types, bool decode_to_plain)
 {
-	struct ext_body_part_cached *body_part = NULL;
+	struct ext_body_part_cached *body_part = NULL, *header_part = NULL;
 	struct message_parser_ctx *parser;
 	struct message_decoder_context *decoder;
 	struct message_block block, decoded;
@@ -214,25 +214,50 @@
 	/* Get the message stream */
 	if ( mail_get_stream(msgdata->mail, NULL, NULL, &input) < 0 )
 		return FALSE;
-		
+	//if (mail_get_parts(msgdata->mail, &parts) < 0)
+	//	return FALSE;
+
 	buffer_set_used_size(ctx->tmp_buffer, 0);
 	
 	/* Initialize body decoder */
-	decoder = decode_to_plain ? message_decoder_init(FALSE) : NULL;
-	
+	decoder = decode_to_plain ? message_decoder_init(FALSE) : NULL;	
+
+	//parser = message_parser_init_from_parts(parts, input, 0, 0);
 	parser = message_parser_init(ctx->pool, input, 0, 0);
+
 	while ( (ret = message_parser_parse_next_block(parser, &block)) > 0 ) {
+
 		if ( block.part != prev_part ) {
+			bool message_rfc822 = FALSE;
+
 			/* Save previous body part */
-			if ( body_part != NULL && save_body ) {
-				ext_body_part_save(ctx, prev_part, body_part, decoder != NULL);
+			if ( body_part != NULL ) {
+				/* Treat message/rfc822 separately; headers become content */
+				if ( block.part->parent == prev_part &&
+					strcmp(body_part->content_type, "message/rfc822") == 0 ) {
+					message_rfc822 = TRUE;
+				} else {
+					if ( save_body ) 
+						ext_body_part_save(ctx, body_part, decoder != NULL);
+				}
 			}
-			
+
 			/* Start processing next */
+			body_part = array_idx_modifiable(&ctx->cached_body_parts, idx);
+			body_part->content_type = "text/plain";
+
+			/* If this is message/rfc822 content retain the enveloping part for
+			 * storing headers as content.
+			 */
+			if ( message_rfc822 ) {
+				i_assert(idx > 0);
+				header_part = array_idx_modifiable(&ctx->cached_body_parts, idx-1);
+			} else {
+				header_part = NULL;
+			}
+
 			prev_part = block.part;
-			body_part = array_idx_modifiable(&ctx->cached_body_parts, idx);
-			idx++;
-			body_part->content_type = "text/plain";
+			idx++;	
 		}
 		
 		if ( block.hdr != NULL || block.size == 0 ) {
@@ -244,6 +269,12 @@
 
 			/* Check for end of headers */
 			if ( block.hdr == NULL ) {
+				/* Save headers for message/rfc822 part */
+				if ( header_part != NULL ) {
+					ext_body_part_save(ctx, header_part, decoder != NULL);
+					header_part = NULL;
+				}
+	
 				/* Save bodies only if we have a wanted content-type */
 				save_body = _is_wanted_content_type
 					(content_types, body_part->content_type);
@@ -255,9 +286,22 @@
 			 */
 			if ( block.hdr->eoh )
 				body_part->have_body = TRUE;
+			else if ( header_part != NULL ) {
+				/* Save message/rfc822 header as part content */
+				if ( block.hdr->continued ) {
+					buffer_append(ctx->tmp_buffer, block.hdr->value, block.hdr->value_len);
+				} else {
+					buffer_append(ctx->tmp_buffer, block.hdr->name, block.hdr->name_len);
+					buffer_append(ctx->tmp_buffer, block.hdr->middle, block.hdr->middle_len);
+					buffer_append(ctx->tmp_buffer, block.hdr->value, block.hdr->value_len);
+				}
+				if ( !block.hdr->no_newline ) {
+					buffer_append(ctx->tmp_buffer, "\r\n", 2);
+				}
+			}
 				
 			/* We're interested of only Content-Type: header */
-			if ( strcasecmp(block.hdr->name, "Content-Type" ) != 0)
+			if ( strcasecmp(block.hdr->name, "Content-Type" ) != 0 )
 				continue;
 
 			/* Header can have folding whitespace. Acquire the full value before 
@@ -289,8 +333,11 @@
 	}
 
 	/* Save last body part if necessary */
-	if ( body_part != NULL && save_body )
-		ext_body_part_save(ctx, prev_part, body_part, decoder != NULL);
+	if ( header_part != NULL ) {
+		ext_body_part_save(ctx, header_part, decoder != NULL);
+	} else if ( body_part != NULL && save_body ) {
+		ext_body_part_save(ctx, body_part, decoder != NULL);
+	}
 
 	/* Try to fill the return_body_parts array once more */
 	have_all = ext_body_get_return_parts(ctx, content_types, decode_to_plain);
@@ -310,7 +357,6 @@
 static struct ext_body_message_context *ext_body_get_context
 (const struct sieve_extension *this_ext, struct sieve_message_context *msgctx)
 {
-	pool_t pool = sieve_message_context_pool(msgctx);
 	struct ext_body_message_context *ctx;
 	
 	/* Get message context (contains cached message body information) */
@@ -319,8 +365,12 @@
 	
 	/* Create it if it does not exist already */
 	if ( ctx == NULL ) {
+		pool_t pool;
+
+		pool = sieve_message_context_pool(msgctx);
 		ctx = p_new(pool, struct ext_body_message_context, 1);	
 		ctx->pool = pool;
+
 		p_array_init(&ctx->cached_body_parts, pool, 8);
 		p_array_init(&ctx->return_body_parts, pool, 8);
 		ctx->tmp_buffer = buffer_create_dynamic(pool, 1024*64);
diff -r 5459f69f6aa2 -r f3a4ddd68bc8 tests/extensions/body/content.svtest
--- a/tests/extensions/body/content.svtest	Tue Sep 13 22:42:18 2011 +0200
+++ b/tests/extensions/body/content.svtest	Wed Sep 14 17:17:15 2011 +0200
@@ -204,7 +204,8 @@
 Content-Type: message/rfc822
 
 From: Someone Else
-Subject: hello request
+Subject: Hello, this is an elaborate request for you to finally say hello
+ already!
 
 Please say Hello
 
@@ -313,6 +314,20 @@
  *  matches the :content specification.
  */
 
-/* FIXME */
+test "Content-Type: message/rfc822" {
+	if not body :content "message/rfc822" :contains
+		"From: Someone Else" {
+		test_fail "missed raw message/rfc822 from header";
+	}
 
+	if not body :content "message/rfc822" :is text:
+From: Someone Else
+Subject: Hello, this is an elaborate request for you to finally say hello
+ already!
+.
+	{
+		test_fail "header content does not match exactly";
+	}
+}
 
+


More information about the dovecot-cvs mailing list