From a2f1ad80472d29b90774d8ce8895cf49dc256586 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 29 Nov 2007 14:20:10 +0100
Subject: [PATCH] Added basic execution support to copy extension. Not
 completely functional yet.

---
 src/lib-sieve/cmd-keep.c              |  8 ++-
 src/lib-sieve/cmd-redirect.c          |  9 ++-
 src/lib-sieve/ext-fileinto.c          |  9 ++-
 src/lib-sieve/plugins/copy/ext-copy.c | 34 +++++++++-
 src/lib-sieve/sieve-actions.c         |  5 +-
 src/lib-sieve/sieve-actions.h         |  3 +-
 src/lib-sieve/sieve-binary.c          | 17 +++++
 src/lib-sieve/sieve-binary.h          |  2 +
 src/lib-sieve/sieve-code.c            | 18 +-----
 src/lib-sieve/sieve-common.h          |  1 +
 src/lib-sieve/sieve-interpreter.c     | 31 +++++++++
 src/lib-sieve/sieve-interpreter.h     |  5 ++
 src/lib-sieve/sieve-result.c          | 91 +++++++++++++++++----------
 src/lib-sieve/sieve-result.h          | 14 +++--
 14 files changed, 185 insertions(+), 62 deletions(-)

diff --git a/src/lib-sieve/cmd-keep.c b/src/lib-sieve/cmd-keep.c
index 7a59bc212..7c5930908 100644
--- a/src/lib-sieve/cmd-keep.c
+++ b/src/lib-sieve/cmd-keep.c
@@ -65,14 +65,18 @@ static bool opc_keep_execute
 	const struct sieve_runtime_env *renv ATTR_UNUSED, 
 	sieve_size_t *address ATTR_UNUSED)
 {	
+	struct sieve_side_effects_list *slist = NULL;
 	bool added = FALSE;
 	
 	printf(">> KEEP\n");
 	
+	if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) )
+		return FALSE;
+	
 	if ( renv->mailenv != NULL && renv->mailenv->inbox != NULL )
-		added = sieve_act_store_add_to_result(renv,	renv->mailenv->inbox);
+		added = sieve_act_store_add_to_result(renv,	slist, renv->mailenv->inbox);
 	else
-		added = sieve_act_store_add_to_result(renv,	"INBOX");
+		added = sieve_act_store_add_to_result(renv,	slist, "INBOX");
 	
 	if ( added ) 
 		sieve_result_cancel_implicit_keep(renv->result);
diff --git a/src/lib-sieve/cmd-redirect.c b/src/lib-sieve/cmd-redirect.c
index e6c802fae..9325e8305 100644
--- a/src/lib-sieve/cmd-redirect.c
+++ b/src/lib-sieve/cmd-redirect.c
@@ -117,6 +117,9 @@ static bool cmd_redirect_opcode_dump
 {
 	printf("REDIRECT\n");
 
+	if ( !sieve_interpreter_handle_optional_operands(renv, address, NULL) )
+		return FALSE;
+
 	return 
 		sieve_opr_string_dump(renv->sbin, address);
 }
@@ -129,10 +132,14 @@ static bool cmd_redirect_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
+	struct sieve_side_effects_list *slist = NULL;
 	struct act_redirect_context *act;
 	string_t *redirect;
 	pool_t pool;
 
+	if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) )
+		return FALSE;
+
 	t_push();
 
 	if ( !sieve_opr_string_read(renv->sbin, address, &redirect) ) {
@@ -147,7 +154,7 @@ static bool cmd_redirect_opcode_execute
 	act = p_new(pool, struct act_redirect_context, 1);
 	act->to_address = p_strdup(pool, str_c(redirect));
 	
-	if ( sieve_result_add_action(renv, &act_redirect, (void *) act) )
+	if ( sieve_result_add_action(renv, &act_redirect, slist, (void *) act) )
 		sieve_result_cancel_implicit_keep(renv->result);
 	
 	t_pop();
diff --git a/src/lib-sieve/ext-fileinto.c b/src/lib-sieve/ext-fileinto.c
index 2f9433679..1789151a8 100644
--- a/src/lib-sieve/ext-fileinto.c
+++ b/src/lib-sieve/ext-fileinto.c
@@ -132,6 +132,9 @@ static bool ext_fileinto_opcode_dump
 {
 	printf("FILEINTO\n");
 
+	if ( !sieve_interpreter_handle_optional_operands(renv, address, NULL) )
+		return FALSE;
+
 	return 
 		sieve_opr_string_dump(renv->sbin, address);
 }
@@ -144,7 +147,11 @@ static bool ext_fileinto_opcode_execute
 (const struct sieve_opcode *opcode ATTR_UNUSED,
 	const struct sieve_runtime_env *renv, sieve_size_t *address)
 {
+	struct sieve_side_effects_list *slist = NULL; 
 	string_t *folder;
+	
+	if ( !sieve_interpreter_handle_optional_operands(renv, address, &slist) )
+		return FALSE;
 
 	t_push();
 
@@ -155,7 +162,7 @@ static bool ext_fileinto_opcode_execute
 
 	printf(">> FILEINTO \"%s\"\n", str_c(folder));
 
-	if ( sieve_act_store_add_to_result(renv, str_c(folder)) )
+	if ( sieve_act_store_add_to_result(renv, slist, str_c(folder)) )
 		sieve_result_cancel_implicit_keep(renv->result);
 
 	t_pop();
diff --git a/src/lib-sieve/plugins/copy/ext-copy.c b/src/lib-sieve/plugins/copy/ext-copy.c
index 1655ae9c9..11c21d738 100644
--- a/src/lib-sieve/plugins/copy/ext-copy.c
+++ b/src/lib-sieve/plugins/copy/ext-copy.c
@@ -52,13 +52,25 @@ static bool ext_copy_load(int ext_id)
 
 const struct sieve_side_effect_extension ext_copy_side_effect;
 
+bool seff_copy_pre_execute
+	(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
+		const struct sieve_action_exec_env *aenv, void **se_context, 
+		void *tr_context);
+bool seff_copy_post_commit
+		(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
+			const struct sieve_action_exec_env *aenv, void *se_context,
+			void *tr_context);
+
 const struct sieve_side_effect copy_side_effect = {
 	"copy",
 	&act_store,
 	
 	&ext_copy_side_effect,
 	0,
-	NULL, NULL, NULL, NULL
+	seff_copy_pre_execute, 
+	NULL, 
+	seff_copy_post_commit, 
+	NULL
 };
 
 const struct sieve_side_effect_extension ext_copy_side_effect = {
@@ -108,6 +120,26 @@ static const struct sieve_argument copy_tag = {
 	tag_copy_generate
 };
 
+/* Side effect execution */
+
+bool seff_copy_pre_execute
+(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
+	const struct sieve_action_exec_env *aenv, void **se_context, 
+	void *tr_context)
+{
+	printf("        + implicit keep preserved\n");
+	return TRUE;
+}
+
+bool seff_copy_post_commit
+	(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
+		const struct sieve_action_exec_env *aenv, void *se_context,
+		void *tr_context)
+{	
+	printf("        + implicit keep restored\n");
+	return TRUE;
+}
+
 /* Load extension into validator */
 static bool ext_copy_validator_load(struct sieve_validator *validator)
 {
diff --git a/src/lib-sieve/sieve-actions.c b/src/lib-sieve/sieve-actions.c
index 6a00bf1f3..1d41439d6 100644
--- a/src/lib-sieve/sieve-actions.c
+++ b/src/lib-sieve/sieve-actions.c
@@ -153,7 +153,8 @@ const struct sieve_action act_store = {
 };
 
 bool sieve_act_store_add_to_result
-(const struct sieve_runtime_env *renv, const char *folder)
+(const struct sieve_runtime_env *renv, 
+	struct sieve_side_effects_list *seffects, const char *folder)
 {
 	pool_t pool;
 	struct act_store_context *act;
@@ -163,7 +164,7 @@ bool sieve_act_store_add_to_result
 	act = p_new(pool, struct act_store_context, 1);
 	act->folder = p_strdup(pool, folder);
 
-	return sieve_result_add_action(renv, &act_store, (void *) act);
+	return sieve_result_add_action(renv, &act_store, seffects, (void *) act);
 }
 
 /* Store action implementation */
diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h
index cdf12ff7a..75058cf4c 100644
--- a/src/lib-sieve/sieve-actions.h
+++ b/src/lib-sieve/sieve-actions.h
@@ -115,7 +115,8 @@ struct act_store_transaction {
 };
 
 bool sieve_act_store_add_to_result
-	(const struct sieve_runtime_env *renv, const char *folder);
+	(const struct sieve_runtime_env *renv, 
+		struct sieve_side_effects_list *seffects, const char *folder);
 
 		
 #endif /* __SIEVE_ACTIONS_H */
diff --git a/src/lib-sieve/sieve-binary.c b/src/lib-sieve/sieve-binary.c
index ea47008f6..e27c5e6c4 100644
--- a/src/lib-sieve/sieve-binary.c
+++ b/src/lib-sieve/sieve-binary.c
@@ -289,9 +289,26 @@ bool sieve_binary_read_byte
 		return TRUE;
 	}
 	
+	*byte_val = 0;
 	return FALSE;
 }
 
+bool sieve_binary_read_code
+	(struct sieve_binary *binary, sieve_size_t *address, int *code) 
+{	
+	if ( ADDR_BYTES_LEFT(binary, address) >= 1 ) {
+		if ( code != NULL )
+			*code = ADDR_CODE_AT(binary, address);
+		ADDR_JUMP(address, 1);
+			
+		return TRUE;
+	}
+	
+	*code = 0;
+	return FALSE;
+}
+
+
 bool sieve_binary_read_offset
 	(struct sieve_binary *binary, sieve_size_t *address, int *offset) 
 {
diff --git a/src/lib-sieve/sieve-binary.h b/src/lib-sieve/sieve-binary.h
index 8f2fafc2f..cd1a6f043 100644
--- a/src/lib-sieve/sieve-binary.h
+++ b/src/lib-sieve/sieve-binary.h
@@ -71,6 +71,8 @@ sieve_size_t sieve_binary_emit_ext_opcode_id
 /* Literals */
 bool sieve_binary_read_byte
 	(struct sieve_binary *binary, sieve_size_t *address, unsigned int *byte_val);
+bool sieve_binary_read_code
+	(struct sieve_binary *binary, sieve_size_t *address, int *code);
 bool sieve_binary_read_offset
 	(struct sieve_binary *binary, sieve_size_t *address, int *offset);
 bool sieve_binary_read_integer
diff --git a/src/lib-sieve/sieve-code.c b/src/lib-sieve/sieve-code.c
index 371d4fb6c..5714624f6 100644
--- a/src/lib-sieve/sieve-code.c
+++ b/src/lib-sieve/sieve-code.c
@@ -140,22 +140,8 @@ bool sieve_operand_optional_present(struct sieve_binary *sbin, sieve_size_t *add
 
 bool sieve_operand_optional_read(struct sieve_binary *sbin, sieve_size_t *address, int *id_code)
 {
-	unsigned int id;
-
-	while ( sieve_binary_read_byte(sbin, address, &id) ) {
-		*id_code = (int) id;
-		
-		if ( *id_code == SIEVE_OPT_SIDE_EFFECT ) {
-			const struct sieve_side_effect *seffect = 
-				sieve_opr_side_effect_read(sbin, address);
-
-			printf("SIDE_EFFECT!!!\n");
-			if ( seffect == NULL ) return FALSE;
-			
-			printf("        : SIDE_EFFECT: %s\n", seffect->name);
-		} else 
-			return TRUE;
-	}
+	if ( sieve_binary_read_code(sbin, address, id_code) ) 
+		return TRUE;
 	
 	*id_code = 0;
 
diff --git a/src/lib-sieve/sieve-common.h b/src/lib-sieve/sieve-common.h
index 92bba80e7..e717a566a 100644
--- a/src/lib-sieve/sieve-common.h
+++ b/src/lib-sieve/sieve-common.h
@@ -73,6 +73,7 @@ struct sieve_address_part;
 
 /* sieve-result.h */
 struct sieve_result;
+struct sieve_side_effects_list;
 
 /* sieve-actions.h */
 struct sieve_action_exec_env;
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 691fb7f4c..3e4af48f3 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -9,6 +9,7 @@
 
 #include "sieve-extensions.h"
 #include "sieve-commands-private.h"
+#include "sieve-actions.h"
 #include "sieve-generator.h"
 #include "sieve-binary.h"
 #include "sieve-result.h"
@@ -166,6 +167,36 @@ bool sieve_interpreter_read_offset_operand
 {
 	return sieve_binary_read_offset(interp->runenv.sbin, &(interp->pc), offset);
 }
+
+bool sieve_interpreter_handle_optional_operands
+	(const struct sieve_runtime_env *renv, sieve_size_t *address,
+		struct sieve_side_effects_list **list)
+{
+	int opt_code;
+	
+	if ( sieve_operand_optional_present(renv->sbin, address) ) {
+		while ( opt_code != 0 ) {
+			if ( !sieve_operand_optional_read(renv->sbin, address, &opt_code) )
+				return FALSE;
+
+			if ( opt_code == SIEVE_OPT_SIDE_EFFECT ) {
+				if ( list != NULL && *list == NULL ) 
+					*list = sieve_side_effects_list_create(renv->result);
+					
+				const struct sieve_side_effect *seffect = 
+					sieve_opr_side_effect_read(renv->sbin, address);
+
+				if ( seffect == NULL ) return FALSE;
+			
+				printf("        : SIDE_EFFECT: %s\n", seffect->name);
+				
+				if ( list != NULL )
+					sieve_side_effects_list_add(*list, seffect, NULL);
+			}
+		}
+	}
+	return TRUE;
+}
  
 /* Code Dump */
 
diff --git a/src/lib-sieve/sieve-interpreter.h b/src/lib-sieve/sieve-interpreter.h
index 5d4e0a5f8..8f37fb63b 100644
--- a/src/lib-sieve/sieve-interpreter.h
+++ b/src/lib-sieve/sieve-interpreter.h
@@ -50,6 +50,11 @@ inline const void *sieve_interpreter_extension_get_context
 
 bool sieve_interpreter_read_offset_operand
 	(struct sieve_interpreter *interp, int *offset);
+	
+struct sieve_result_action;
+bool sieve_interpreter_handle_optional_operands
+	(const struct sieve_runtime_env *renv, sieve_size_t *address,
+		struct sieve_side_effects_list **list);
 
 /* Code dump (debugging purposes) */
 
diff --git a/src/lib-sieve/sieve-result.c b/src/lib-sieve/sieve-result.c
index 2e1dabadc..ae5d8043e 100644
--- a/src/lib-sieve/sieve-result.c
+++ b/src/lib-sieve/sieve-result.c
@@ -7,14 +7,20 @@
 #include "sieve-result.h"
 
 #include <stdio.h>
-
 struct sieve_result_action {
 	struct sieve_result *result;
 	const struct sieve_action *action;
 	void *context;
 	void *tr_context;
 	bool success;
+	
+	struct sieve_side_effects_list *seffects;
+	
 	struct sieve_result_action *prev, *next; 
+};
+
+struct sieve_side_effects_list {
+	struct sieve_result *result;
 
 	struct sieve_result_side_effect *first_effect;
 	struct sieve_result_side_effect *last_effect;
@@ -81,7 +87,8 @@ void sieve_result_cancel_implicit_keep(struct sieve_result *result)
 
 bool sieve_result_add_action
 (const struct sieve_runtime_env *renv,
-	const struct sieve_action *action, void *context)		
+	const struct sieve_action *action, struct sieve_side_effects_list *seffects,
+	void *context)		
 {
 	struct sieve_result *result = renv->result;
 	struct sieve_result_action *raction;
@@ -119,6 +126,7 @@ bool sieve_result_add_action
 	raction->context = context;
 	raction->tr_context = NULL;
 	raction->success = FALSE;
+	raction->seffects = seffects;
 	
 	/* Add */
 	if ( result->first_action == NULL ) {
@@ -136,33 +144,6 @@ bool sieve_result_add_action
 	return TRUE;
 }	
 
-bool sieve_result_add_side_effect
-(struct sieve_result_action *raction, const struct sieve_side_effect *seffect, 
-	void *context)		
-{
-	struct sieve_result_side_effect *reffect;
-	
-	/* Create new action object */
-	reffect = p_new(raction->result->pool, struct sieve_result_side_effect, 1);
-	reffect->seffect = seffect;
-	reffect->context = context;
-	
-	/* Add */
-	if ( raction->first_effect == NULL ) {
-		raction->first_effect = reffect;
-		raction->last_effect = reffect;
-		reffect->prev = NULL;
-		reffect->next = NULL;
-	} else {
-		raction->last_effect->next = reffect;
-		reffect->prev = raction->last_effect;
-		raction->last_effect = reffect;
-		reffect->next = NULL;
-	}	
-	
-	return TRUE;
-}	
-
 bool sieve_result_print(struct sieve_result *result)
 {
 	struct sieve_result_action *rac = result->first_action;
@@ -225,7 +206,7 @@ bool sieve_result_execute
 				rac->context : rac->tr_context;
 		
 		/* Execute pre-execute event of side effects */
-		rsef = rac->first_effect;
+		rsef = rac->seffects != NULL ? rac->seffects->first_effect : NULL;
 		while ( rsef != NULL ) {
 			sef = rsef->seffect;
 			if ( sef->pre_execute != NULL ) 
@@ -241,7 +222,7 @@ bool sieve_result_execute
 		}
 		
 		/* Execute pre-execute event of side effects */
-		rsef = rac->first_effect;
+		rsef = rac->seffects != NULL ? rac->seffects->first_effect : NULL;
 		while ( rsef != NULL ) {
 			sef = rsef->seffect;
 			if ( sef->post_execute != NULL ) 
@@ -273,7 +254,7 @@ bool sieve_result_execute
 				commit_ok = act->commit(act, &result->action_env, context) && commit_ok;
 	
 			/* Execute post_commit event of side effects */
-			rsef = rac->first_effect;
+			rsef = rac->seffects != NULL ? rac->seffects->first_effect : NULL;
 			while ( rsef != NULL ) {
 				sef = rsef->seffect;
 				if ( sef->post_commit != NULL ) 
@@ -286,7 +267,7 @@ bool sieve_result_execute
 				act->rollback(act, &result->action_env, context, rac->success);
 				
 			/* Rollback side effects */
-			rsef = rac->first_effect;
+			rsef = rac->seffects != NULL ? rac->seffects->first_effect : NULL;
 			while ( rsef != NULL ) {
 				sef = rsef->seffect;
 				if ( sef->rollback != NULL ) 
@@ -303,3 +284,47 @@ bool sieve_result_execute
 	
 	return commit_ok;
 }
+
+/*
+ * Side effects list
+ */
+struct sieve_side_effects_list *sieve_side_effects_list_create
+	(struct sieve_result *result)
+{
+	struct sieve_side_effects_list *list = 
+		p_new(result->pool, struct sieve_side_effects_list, 1);
+	
+	list->result = result;
+	list->first_effect = NULL;
+	list->last_effect = NULL;
+	
+	return list;
+};
+
+void sieve_side_effects_list_add
+(struct sieve_side_effects_list *list, const struct sieve_side_effect *seffect, 
+	void *context)		
+{
+	struct sieve_result_side_effect *reffect;
+	
+	/* Create new action object */
+	reffect = p_new(list->result->pool, struct sieve_result_side_effect, 1);
+	reffect->seffect = seffect;
+	reffect->context = context;
+	
+	/* Add */
+	if ( list->first_effect == NULL ) {
+		list->first_effect = reffect;
+		list->last_effect = reffect;
+		reffect->prev = NULL;
+		reffect->next = NULL;
+	} else {
+		list->last_effect->next = reffect;
+		reffect->prev = list->last_effect;
+		list->last_effect = reffect;
+		reffect->next = NULL;
+	}	
+}	
+
+
+
diff --git a/src/lib-sieve/sieve-result.h b/src/lib-sieve/sieve-result.h
index f32266846..8927048e1 100644
--- a/src/lib-sieve/sieve-result.h
+++ b/src/lib-sieve/sieve-result.h
@@ -4,8 +4,8 @@
 #include "sieve-common.h"
 
 struct sieve_result;
-
 struct sieve_result_action;
+struct sieve_side_effects_list;
 
 struct sieve_result *sieve_result_create(void);
 void sieve_result_ref(struct sieve_result *result); 
@@ -13,10 +13,8 @@ void sieve_result_unref(struct sieve_result **result);
 inline pool_t sieve_result_pool(struct sieve_result *result);
 
 bool sieve_result_add_action
-(const struct sieve_runtime_env *renv, const struct sieve_action *action, 
-	void *context);	
-bool sieve_result_add_side_effect
-(struct sieve_result_action *raction, const struct sieve_side_effect *seffect, 
+(const struct sieve_runtime_env *renv,
+	const struct sieve_action *action, struct sieve_side_effects_list *seffects,
 	void *context);
 
 bool sieve_result_print(struct sieve_result *result);
@@ -26,5 +24,11 @@ void sieve_result_cancel_implicit_keep(struct sieve_result *result);
 bool sieve_result_execute
 	(struct sieve_result *result, const struct sieve_message_data *msgdata,
 		const struct sieve_mail_environment *menv);
+		
+struct sieve_side_effects_list *sieve_side_effects_list_create
+	(struct sieve_result *result);
+void sieve_side_effects_list_add
+(struct sieve_side_effects_list *list, const struct sieve_side_effect *seffect, 
+	void *context);
 
 #endif
-- 
GitLab