diff --git a/src/lib-sieve/plugins/mime/tag-mime.c b/src/lib-sieve/plugins/mime/tag-mime.c index d88efeee13758cd0186ee01bfe919261f06d01ba..56bb3fff361ba00286b629de4052b1febc835935 100644 --- a/src/lib-sieve/plugins/mime/tag-mime.c +++ b/src/lib-sieve/plugins/mime/tag-mime.c @@ -699,6 +699,7 @@ static int svmo_mime_header_override struct ext_foreverypart_runtime_loop *sfploop; struct sieve_header_list *headers; struct sieve_stringlist *values; + int ret; sieve_runtime_trace(renv, SIEVE_TRLVL_MATCHING, "header mime override:"); @@ -713,13 +714,22 @@ static int svmo_mime_header_override } sfploop = ext_foreverypart_runtime_loop_get_current(renv); - if ( sfploop == NULL ) { - headers = sieve_message_header_list_create - (renv, *headers_r, mime_decode); - } else { + if ( sfploop != NULL ) { headers = sieve_mime_header_list_create (renv, *headers_r, &sfploop->part_iter, mime_decode, ctx->anychild); + } else if ( ctx->anychild ) { + struct sieve_message_part_iter part_iter; + + if ( (ret=sieve_message_part_iter_init + (&part_iter, renv)) <= 0 ) + return ret; + + headers = sieve_mime_header_list_create + (renv, *headers_r, &part_iter, mime_decode, TRUE); + } else { + headers = sieve_message_header_list_create + (renv, *headers_r, mime_decode); } values = &headers->strlist; diff --git a/src/lib-sieve/sieve-message.c b/src/lib-sieve/sieve-message.c index 95d0eb50a02b11cb32e36be1c44bc68e4e9e6c22..240edb24ff8c2a62c73c71b6d8aa12fc96f9cd45 100644 --- a/src/lib-sieve/sieve-message.c +++ b/src/lib-sieve/sieve-message.c @@ -1572,6 +1572,7 @@ int sieve_message_part_iter_init memset(iter, 0, sizeof(*iter)); iter->renv = renv; iter->index = 0; + iter->offset = 0; parts = array_get(&msgctx->cached_body_parts, &count); if (count == 0) @@ -1582,6 +1583,24 @@ int sieve_message_part_iter_init return SIEVE_EXEC_OK; } +void sieve_message_part_iter_subtree(struct sieve_message_part_iter *iter, + struct sieve_message_part_iter *subtree) +{ + const struct sieve_runtime_env *renv = iter->renv; + struct sieve_message_context *msgctx = renv->msgctx; + struct sieve_message_part *const *parts; + unsigned int count; + + *subtree = *iter; + + parts = array_get(&msgctx->cached_body_parts, &count); + if ( subtree->index >= count) + subtree->root = NULL; + else + subtree->root = parts[subtree->index]; + subtree->offset = subtree->index; +} + void sieve_message_part_iter_children(struct sieve_message_part_iter *iter, struct sieve_message_part_iter *child) { @@ -1593,10 +1612,11 @@ void sieve_message_part_iter_children(struct sieve_message_part_iter *iter, *child = *iter; parts = array_get(&msgctx->cached_body_parts, &count); - if ( child->index >= count || parts[child->index]->children == NULL) + if ( (child->index+1) >= count || parts[child->index]->children == NULL) child->root = NULL; - else + else child->root = parts[child->index++]; + child->offset = child->index; } struct sieve_message_part *sieve_message_part_iter_current @@ -1614,10 +1634,10 @@ struct sieve_message_part *sieve_message_part_iter_current if ( iter->index >= count ) return NULL; do { - if ( parts[iter->index] == iter->root->next || - parts[iter->index] == iter->root->parent ) { + if ( parts[iter->index] == iter->root->next ) + return NULL; + if ( parts[iter->index] == iter->root->parent ) return NULL; - } } while ( parts[iter->index]->epilogue && ++iter->index < count ); if ( iter->index >= count ) return NULL; @@ -1637,6 +1657,12 @@ struct sieve_message_part *sieve_message_part_iter_next return sieve_message_part_iter_current(iter); } +void sieve_message_part_iter_reset +(struct sieve_message_part_iter *iter) +{ + iter->index = iter->offset; +} + /* * MIME header list */ @@ -1658,14 +1684,14 @@ struct sieve_mime_header_list { struct sieve_stringlist *field_names; - struct sieve_message_part_iter *part_iter, child_iter; + struct sieve_message_part_iter part_iter; const char *header_name; const struct sieve_message_header *headers; unsigned int headers_index, headers_count; unsigned int mime_decode:1; - unsigned int children; + unsigned int children:1; }; struct sieve_header_list *sieve_mime_header_list_create @@ -1683,10 +1709,11 @@ struct sieve_header_list *sieve_mime_header_list_create hdrlist->hdrlist.strlist.reset = sieve_mime_header_list_reset; hdrlist->hdrlist.next_item = sieve_mime_header_list_next_item; hdrlist->field_names = field_names; - hdrlist->part_iter = part_iter; hdrlist->mime_decode = mime_decode; hdrlist->children = children; + sieve_message_part_iter_subtree(part_iter, &hdrlist->part_iter); + return &hdrlist->hdrlist; } @@ -1697,12 +1724,8 @@ static void sieve_mime_header_list_next_name { struct sieve_message_part *mpart; - if ( hdrlist->children ) { - sieve_message_part_iter_children - (hdrlist->part_iter, &hdrlist->child_iter); - } - - mpart = sieve_message_part_iter_current(hdrlist->part_iter); + sieve_message_part_iter_reset(&hdrlist->part_iter); + mpart = sieve_message_part_iter_current(&hdrlist->part_iter); if ( mpart != NULL && array_is_created(&mpart->headers) ) { hdrlist->headers = array_get @@ -1740,7 +1763,7 @@ static int sieve_mime_header_list_next_item if ( hdrlist->header_name != NULL && hdrlist->children ) { struct sieve_message_part *mpart; - mpart = sieve_message_part_iter_next(&hdrlist->child_iter); + mpart = sieve_message_part_iter_next(&hdrlist->part_iter); if ( mpart != NULL && array_is_created(&mpart->headers) ) { hdrlist->headers = array_get (&mpart->headers, &hdrlist->headers_count); diff --git a/src/lib-sieve/sieve-message.h b/src/lib-sieve/sieve-message.h index 39d3bf82cc0fb126cc49accfebfc0d1705b75c1e..254cb092c55dd112eab8343d023699cb1c86ee85 100644 --- a/src/lib-sieve/sieve-message.h +++ b/src/lib-sieve/sieve-message.h @@ -233,12 +233,14 @@ int sieve_message_body_get_raw struct sieve_message_part_iter { const struct sieve_runtime_env *renv; struct sieve_message_part *root; - unsigned int index; + unsigned int index, offset; }; int sieve_message_part_iter_init (struct sieve_message_part_iter *iter, const struct sieve_runtime_env *renv); +void sieve_message_part_iter_subtree(struct sieve_message_part_iter *iter, + struct sieve_message_part_iter *subtree); void sieve_message_part_iter_children(struct sieve_message_part_iter *iter, struct sieve_message_part_iter *child); @@ -247,6 +249,9 @@ struct sieve_message_part *sieve_message_part_iter_current struct sieve_message_part *sieve_message_part_iter_next (struct sieve_message_part_iter *iter); +void sieve_message_part_iter_reset +(struct sieve_message_part_iter *iter); + /* * MIME header list */ diff --git a/tests/extensions/mime/foreverypart.svtest b/tests/extensions/mime/foreverypart.svtest index b6fc279ede7958c0c45b2ea086d25ca802fffe2b..08907c92434b184e958543f465609147c2b76424 100644 --- a/tests/extensions/mime/foreverypart.svtest +++ b/tests/extensions/mime/foreverypart.svtest @@ -176,8 +176,3 @@ test "Double loop - include" { } } - - - - - diff --git a/tests/extensions/mime/header.svtest b/tests/extensions/mime/header.svtest index 2149352fafd1724cece5e81e3ce122045d2b9852..48cd9e4daabec9803604e2497dd1013008fcad67 100644 --- a/tests/extensions/mime/header.svtest +++ b/tests/extensions/mime/header.svtest @@ -379,4 +379,66 @@ test "Folded headers - foreverypart" { } } +/* + * Multipart anychild + */ + +test_set "message" text: +From: Hendrik <hendrik@example.com> +To: Harrie <harrie@example.com> +Date: Sat, 11 Oct 2010 00:31:44 +0200 +Subject: Harrie is een prutser +Content-Type: multipart/mixed; boundary=AA +X-Test: AA + +This is a multi-part message in MIME format. +--AA +Content-Type: multipart/mixed; boundary=BB +X-Test: BB + +This is a multi-part message in MIME format. +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test: CC + +Hello + +--BB +Content-Type: text/plain; charset="us-ascii" +X-Test: DD + +Hello again + +--BB-- +This is the end of MIME multipart. + +--AA +Content-Type: text/plain; charset="us-ascii" +X-Test: EE + +And again + +--AA-- +This is the end of MIME multipart. +. +; + +test "Multipart anychild" { + if not header :mime :anychild "X-Test" "AA" { + test_fail "No AA"; + } + if not header :mime :anychild "X-Test" "BB" { + test_fail "No BB"; + } + if not header :mime :anychild "X-Test" "CC" { + test_fail "No CC"; + } + if not header :mime :anychild "X-Test" "DD" { + test_fail "No DD"; + } + if not header :mime :anychild "X-Test" "EE" { + test_fail "No EE"; + } +} +