From e2e92dd68ea8e6910c6737af3bd8e613ca052517 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 6 Dec 2007 22:47:44 +0100
Subject: [PATCH] Added support for reading an entire stringlist into memory.
 Also fixed various identical bugs in stringlist-related error handling.

---
 src/lib-sieve/ext-envelope.c                  |  9 ++++--
 src/lib-sieve/plugins/imapflags/cmd-addflag.c |  5 +--
 .../plugins/imapflags/cmd-removeflag.c        |  5 +--
 src/lib-sieve/plugins/imapflags/cmd-setflag.c |  5 +--
 src/lib-sieve/plugins/imapflags/tag-flags.c   |  5 +--
 src/lib-sieve/sieve-code.c                    | 32 +++++++++++++++++--
 src/lib-sieve/sieve-code.h                    | 27 ++++++++++------
 src/lib-sieve/tst-address.c                   |  9 ++++--
 src/lib-sieve/tst-exists.c                    | 10 +++---
 src/lib-sieve/tst-header.c                    |  9 ++++--
 10 files changed, 84 insertions(+), 32 deletions(-)

diff --git a/src/lib-sieve/ext-envelope.c b/src/lib-sieve/ext-envelope.c
index aa0e902e5..49351e675 100644
--- a/src/lib-sieve/ext-envelope.c
+++ b/src/lib-sieve/ext-envelope.c
@@ -206,6 +206,7 @@ static bool ext_envelope_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
+	bool result = TRUE;
 	const struct sieve_comparator *cmp = &i_octet_comparator;
 	const struct sieve_match_type *mtch = &is_match_type;
 	const struct sieve_address_part *addrp = &all_address_part;
@@ -241,7 +242,8 @@ static bool ext_envelope_opcode_execute
 	/* Iterate through all requested headers to match */
 	hdr_item = NULL;
 	matched = FALSE;
-	while ( !matched && sieve_coded_stringlist_next_item(hdr_list, &hdr_item) && hdr_item != NULL ) {
+	while ( !matched && (result=sieve_coded_stringlist_next_item(hdr_list, &hdr_item)) 
+		&& hdr_item != NULL ) {
 		const char *const *fields;
 			
 		if ( ext_envelope_get_fields(renv->msgdata, str_c(hdr_item), &fields) >= 0 ) {	
@@ -258,7 +260,8 @@ static bool ext_envelope_opcode_execute
 
 	t_pop();
 	
-	sieve_interpreter_set_test_result(renv->interp, matched);
+	if ( result )
+		sieve_interpreter_set_test_result(renv->interp, matched);
 	
-	return TRUE;
+	return result;
 }
diff --git a/src/lib-sieve/plugins/imapflags/cmd-addflag.c b/src/lib-sieve/plugins/imapflags/cmd-addflag.c
index 1a2c9b192..11b25e831 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-addflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-addflag.c
@@ -68,6 +68,7 @@ static bool cmd_addflag_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
+	bool result = TRUE;
 	string_t *flag_item;
 	struct sieve_coded_stringlist *flag_list;
 	
@@ -82,7 +83,7 @@ static bool cmd_addflag_opcode_execute
 	}
 	
 	/* Iterate through all requested headers to match */
-	while ( sieve_coded_stringlist_next_item(flag_list, &flag_item) && 
+	while ( (result=sieve_coded_stringlist_next_item(flag_list, &flag_item)) && 
 		flag_item != NULL ) {
 		ext_imapflags_add_flags(renv->interp, flag_item);
 	}
@@ -91,5 +92,5 @@ static bool cmd_addflag_opcode_execute
 	
 	printf("  FLAGS: %s\n", ext_imapflags_get_flags_string(renv->interp));
 	
-	return TRUE;
+	return result;
 }
diff --git a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
index 8f7268dc0..7ced98c6b 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-removeflag.c
@@ -70,6 +70,7 @@ static bool cmd_removeflag_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
+	bool result = TRUE;
 	string_t *flag_item;
 	struct sieve_coded_stringlist *flag_list;
 	
@@ -84,7 +85,7 @@ static bool cmd_removeflag_opcode_execute
 	}
 	
 	/* Iterate through all requested headers to match */
-	while ( sieve_coded_stringlist_next_item(flag_list, &flag_item) && 
+	while ( (result=sieve_coded_stringlist_next_item(flag_list, &flag_item)) && 
 		flag_item != NULL ) {
 		ext_imapflags_remove_flags(renv->interp, flag_item);
 	}
@@ -93,5 +94,5 @@ static bool cmd_removeflag_opcode_execute
 	
 	printf("  FLAGS: %s\n", ext_imapflags_get_flags_string(renv->interp));
 	
-	return TRUE;
+	return result;
 }
diff --git a/src/lib-sieve/plugins/imapflags/cmd-setflag.c b/src/lib-sieve/plugins/imapflags/cmd-setflag.c
index 85ea7560e..3ac022bfb 100644
--- a/src/lib-sieve/plugins/imapflags/cmd-setflag.c
+++ b/src/lib-sieve/plugins/imapflags/cmd-setflag.c
@@ -67,6 +67,7 @@ static bool cmd_setflag_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
+	bool result = TRUE;
 	string_t *flag_item;
 	struct sieve_coded_stringlist *flag_list;
 	
@@ -81,7 +82,7 @@ static bool cmd_setflag_opcode_execute
 	}
 		
 	/* Iterate through all requested headers to match */
-	while ( sieve_coded_stringlist_next_item(flag_list, &flag_item) && 
+	while ( (result=sieve_coded_stringlist_next_item(flag_list, &flag_item)) && 
 		flag_item != NULL ) {
 		ext_imapflags_set_flags(renv->interp, flag_item);
 	}
@@ -90,6 +91,6 @@ static bool cmd_setflag_opcode_execute
 	
 	printf("  FLAGS: %s\n", ext_imapflags_get_flags_string(renv->interp));
 	
-	return TRUE;
+	return result;
 }
 
diff --git a/src/lib-sieve/plugins/imapflags/tag-flags.c b/src/lib-sieve/plugins/imapflags/tag-flags.c
index 9a7bd3adb..663812402 100644
--- a/src/lib-sieve/plugins/imapflags/tag-flags.c
+++ b/src/lib-sieve/plugins/imapflags/tag-flags.c
@@ -138,6 +138,7 @@ static bool seff_flags_read_context
 	const struct sieve_runtime_env *renv, sieve_size_t *address,
 	void **se_context)
 {
+	bool result = TRUE;
 	pool_t pool = sieve_result_pool(renv->result);
 	struct seff_flags_context *ctx;
 	ARRAY_DEFINE(keywords, const char *);
@@ -157,7 +158,7 @@ static bool seff_flags_read_context
 	
 	/* Unpack */
 	flags_item = NULL;
-	while ( sieve_coded_stringlist_next_item(flag_list, &flags_item) && 
+	while ( (result=sieve_coded_stringlist_next_item(flag_list, &flags_item)) && 
 		flags_item != NULL ) {
 		const char *flag;
 		struct ext_imapflags_iter flit;
@@ -190,7 +191,7 @@ static bool seff_flags_read_context
 
 	t_pop();
 	
-	return TRUE;
+	return result;
 }
 
 static void seff_flags_print
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index d4beb28ad..ccbe3f98d 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -92,6 +92,32 @@ inline sieve_size_t sieve_coded_stringlist_get_current_offset
 	return strlist->current_offset;
 }
 
+bool sieve_coded_stringlist_read_all
+(struct sieve_coded_stringlist *strlist, pool_t pool,
+	const char * const **list_r)
+{
+	bool result = FALSE;
+	ARRAY_DEFINE(items, const char *);
+	string_t *item;
+	
+	sieve_coded_stringlist_reset(strlist);
+	
+	p_array_init(&items, pool, 4);
+	
+	item = NULL;
+	while ( (result=sieve_coded_stringlist_next_item(strlist, &item)) && 
+		item != NULL ) {
+		const char *stritem = p_strdup(pool, str_c(item));
+		
+		array_append(&items, &stritem, 1);
+	}
+	
+	(void)array_append_space(&items);
+	*list_r = array_idx(&items, 0);
+
+	return result;
+}
+
 /*
  * Operand functions
  */
@@ -481,6 +507,7 @@ struct sieve_coded_stringlist *sieve_opr_stringlist_read
 static bool opr_stringlist_dump
 	(const struct sieve_dumptime_env *denv, sieve_size_t *address) 
 {
+	bool result = TRUE;
 	struct sieve_coded_stringlist *strlist;
 	
 	if ( (strlist=opr_stringlist_read(denv->sbin, address)) != NULL ) {
@@ -493,14 +520,15 @@ static bool opr_stringlist_dump
 		sieve_code_mark_specific(denv,
 			sieve_coded_stringlist_get_current_offset(strlist));
 		sieve_code_descend(denv);
-		while ( sieve_coded_stringlist_next_item(strlist, &stritem) && stritem != NULL ) {	
+		while ( (result=sieve_coded_stringlist_next_item(strlist, &stritem)) && 
+			stritem != NULL ) {	
 			_dump_string(denv, stritem);
 			sieve_code_mark_specific(denv,
 				sieve_coded_stringlist_get_current_offset(strlist));  
 		}
 		sieve_code_ascend(denv);
 		
-		return TRUE;
+		return result;
 	}
 	
 	return FALSE;
diff --git a/src/lib-sieve/sieve-code.h b/src/lib-sieve/sieve-code.h
index 59a8430fc..7c9117445 100644
--- a/src/lib-sieve/sieve-code.h
+++ b/src/lib-sieve/sieve-code.h
@@ -1,9 +1,10 @@
 #ifndef __SIEVE_CODE_H
 #define __SIEVE_CODE_H
 
-#include <lib.h>
-#include <buffer.h>
-#include <array.h>
+#include "lib.h"
+#include "buffer.h"
+#include "mempool.h"
+#include "array.h"
 
 #include "sieve-common.h"
 
@@ -11,12 +12,20 @@
 
 struct sieve_coded_stringlist;
 
-bool sieve_coded_stringlist_next_item(struct sieve_coded_stringlist *strlist, string_t **str);
-void sieve_coded_stringlist_reset(struct sieve_coded_stringlist *strlist);
-
-inline int sieve_coded_stringlist_get_length(struct sieve_coded_stringlist *strlist);
-inline sieve_size_t sieve_coded_stringlist_get_end_address(struct sieve_coded_stringlist *strlist);
-inline sieve_size_t sieve_coded_stringlist_get_current_offset(struct sieve_coded_stringlist *strlist);
+bool sieve_coded_stringlist_next_item
+	(struct sieve_coded_stringlist *strlist, string_t **str);
+void sieve_coded_stringlist_reset
+	(struct sieve_coded_stringlist *strlist);
+bool sieve_coded_stringlist_read_all
+	(struct sieve_coded_stringlist *strlist, pool_t pool,
+		const char * const **list_r);
+
+inline int sieve_coded_stringlist_get_length
+	(struct sieve_coded_stringlist *strlist);
+inline sieve_size_t sieve_coded_stringlist_get_end_address
+	(struct sieve_coded_stringlist *strlist);
+inline sieve_size_t sieve_coded_stringlist_get_current_offset
+	(struct sieve_coded_stringlist *strlist);
 
 /* Operand: argument to an opcode */
 
diff --git a/src/lib-sieve/tst-address.c b/src/lib-sieve/tst-address.c
index bd418d84f..b7026648e 100644
--- a/src/lib-sieve/tst-address.c
+++ b/src/lib-sieve/tst-address.c
@@ -132,6 +132,7 @@ static bool tst_address_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {	
+	bool result = TRUE;
 	const struct sieve_comparator *cmp = &i_octet_comparator;
 	const struct sieve_match_type *mtch = &is_match_type;
 	const struct sieve_address_part *addrp = &all_address_part;
@@ -167,7 +168,8 @@ static bool tst_address_opcode_execute
 	/* Iterate through all requested headers to match */
 	hdr_item = NULL;
 	matched = FALSE;
-	while ( !matched && sieve_coded_stringlist_next_item(hdr_list, &hdr_item) && hdr_item != NULL ) {
+	while ( !matched && (result=sieve_coded_stringlist_next_item(hdr_list, &hdr_item)) 
+		&& hdr_item != NULL ) {
 		const char *const *headers;
 			
 		if ( mail_get_headers_utf8(renv->msgdata->mail, str_c(hdr_item), &headers) >= 0 ) {	
@@ -184,7 +186,8 @@ static bool tst_address_opcode_execute
 
 	t_pop();
 	
-	sieve_interpreter_set_test_result(renv->interp, matched);
+	if ( result )
+		sieve_interpreter_set_test_result(renv->interp, matched);
 	
-	return TRUE;
+	return result;
 }
diff --git a/src/lib-sieve/tst-exists.c b/src/lib-sieve/tst-exists.c
index 08b719a1f..f06d7359e 100644
--- a/src/lib-sieve/tst-exists.c
+++ b/src/lib-sieve/tst-exists.c
@@ -97,6 +97,7 @@ static bool tst_exists_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
+	bool result = TRUE;
 	struct sieve_coded_stringlist *hdr_list;
 	string_t *hdr_item;
 	bool matched;
@@ -114,8 +115,8 @@ static bool tst_exists_opcode_execute
 	/* Iterate through all requested headers to match */
 	hdr_item = NULL;
 	matched = FALSE;
-	while ( !matched && sieve_coded_stringlist_next_item(hdr_list, &hdr_item) && 
-		hdr_item != NULL ) {
+	while ( !matched && (result=sieve_coded_stringlist_next_item(hdr_list, &hdr_item)) 
+		&& hdr_item != NULL ) {
 		const char *const *headers;
 			
 		if ( mail_get_headers_utf8
@@ -127,7 +128,8 @@ static bool tst_exists_opcode_execute
 	
 	t_pop();
 	
-	sieve_interpreter_set_test_result(renv->interp, matched);
+	if ( result )
+		sieve_interpreter_set_test_result(renv->interp, matched);
 	
-	return TRUE;
+	return result;
 }
diff --git a/src/lib-sieve/tst-header.c b/src/lib-sieve/tst-header.c
index a1b2dd939..340b90e39 100644
--- a/src/lib-sieve/tst-header.c
+++ b/src/lib-sieve/tst-header.c
@@ -155,6 +155,7 @@ static bool tst_header_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED, 
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
+	bool result = TRUE;
 	int opt_code = 1;
 	const struct sieve_comparator *cmp = &i_octet_comparator;
 	const struct sieve_match_type *mtch = &is_match_type;
@@ -206,7 +207,8 @@ static bool tst_header_opcode_execute
 	/* Iterate through all requested headers to match */
 	hdr_item = NULL;
 	matched = FALSE;
-	while ( !matched && sieve_coded_stringlist_next_item(hdr_list, &hdr_item) && hdr_item != NULL ) {
+	while ( !matched && (result=sieve_coded_stringlist_next_item(hdr_list, &hdr_item)) 
+		&& hdr_item != NULL ) {
 		const char *const *headers;
 			
 		if ( mail_get_headers_utf8(renv->msgdata->mail, str_c(hdr_item), &headers) >= 0 ) {	
@@ -223,7 +225,8 @@ static bool tst_header_opcode_execute
 	
 	t_pop();
 	
-	sieve_interpreter_set_test_result(renv->interp, matched);
+	if ( result )
+		sieve_interpreter_set_test_result(renv->interp, matched);
 	
-	return TRUE;
+	return result;
 }
-- 
GitLab