From 16f2ef46260b2923dbf1b89bf173981acae3064e Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 29 Nov 2007 21:50:58 +0100
Subject: [PATCH] The :flags tag introduced by the imapflags extension now
 attaches side-effects to the appropriate action commands.

---
 src/lib-sieve/plugins/copy/ext-copy.c         |   1 +
 .../plugins/imapflags/ext-imapflags.c         |  21 ++-
 src/lib-sieve/plugins/imapflags/tag-flags.c   | 152 +++++++++++++++++-
 src/lib-sieve/sieve-actions.h                 |   5 +
 src/lib-sieve/sieve-interpreter.c             |  11 +-
 5 files changed, 183 insertions(+), 7 deletions(-)

diff --git a/src/lib-sieve/plugins/copy/ext-copy.c b/src/lib-sieve/plugins/copy/ext-copy.c
index d1b23be25..476032804 100644
--- a/src/lib-sieve/plugins/copy/ext-copy.c
+++ b/src/lib-sieve/plugins/copy/ext-copy.c
@@ -70,6 +70,7 @@ const struct sieve_side_effect copy_side_effect = {
 	
 	&ext_copy_side_effect,
 	0,
+	NULL,
 	seff_copy_print,
 	NULL, NULL,
 	seff_copy_post_commit, 
diff --git a/src/lib-sieve/plugins/imapflags/ext-imapflags.c b/src/lib-sieve/plugins/imapflags/ext-imapflags.c
index d08a91f23..e97123673 100644
--- a/src/lib-sieve/plugins/imapflags/ext-imapflags.c
+++ b/src/lib-sieve/plugins/imapflags/ext-imapflags.c
@@ -3,7 +3,7 @@
  *
  * Authors: Stephan Bosch
  * Specification: draft-ietf-sieve-imapflags-05
- * Implementation: flag managesiement works, not stored though. 
+ * Implementation: flag management works, not stored though. 
  * Status: under development
  *
  */
@@ -16,6 +16,7 @@
 
 #include "sieve-code.h"
 #include "sieve-extensions.h"
+#include "sieve-actions.h"
 #include "sieve-commands.h"
 #include "sieve-validator.h"
 #include "sieve-generator.h"
@@ -30,6 +31,7 @@ static bool ext_imapflags_load(int ext_id);
 static bool ext_imapflags_validator_load(struct sieve_validator *validator);
 static bool ext_imapflags_interpreter_load
 	(struct sieve_interpreter *interpreter);
+static bool ext_imapflags_binary_load(struct sieve_binary *sbin);
 
 /* Commands */
 
@@ -61,7 +63,8 @@ const struct sieve_extension imapflags_extension = {
 	"imap4flags", 
 	ext_imapflags_load,
 	ext_imapflags_validator_load, 
-	NULL, NULL,
+	NULL, 
+	ext_imapflags_binary_load,
 	ext_imapflags_interpreter_load, 
 	SIEVE_EXT_DEFINE_OPCODES(imapflags_opcodes), 
 	NULL
@@ -74,6 +77,8 @@ static bool ext_imapflags_load(int ext_id)
 	return TRUE;
 }
 
+extern const struct sieve_side_effect_extension imapflags_seffect_extension;
+
 /* Load extension into validator */
 
 static bool ext_imapflags_validator_load
@@ -95,6 +100,18 @@ static bool ext_imapflags_validator_load
 	return TRUE;
 }
 
+/*
+ * Binary context
+ */
+
+static bool ext_imapflags_binary_load(struct sieve_binary *sbin)
+{
+	sieve_side_effect_extension_set(sbin, ext_imapflags_my_id, 
+		&imapflags_seffect_extension);
+
+	return TRUE;
+}
+
 /*
  * Interpreter context
  */
diff --git a/src/lib-sieve/plugins/imapflags/tag-flags.c b/src/lib-sieve/plugins/imapflags/tag-flags.c
index 2d4ba5d0d..ea9257486 100644
--- a/src/lib-sieve/plugins/imapflags/tag-flags.c
+++ b/src/lib-sieve/plugins/imapflags/tag-flags.c
@@ -1,6 +1,10 @@
 #include "lib.h"
+#include "array.h"
 
+#include "sieve-extensions.h"
 #include "sieve-commands.h"
+#include "sieve-actions.h"
+#include "sieve-result.h"
 #include "sieve-validator.h" 
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
@@ -9,14 +13,57 @@
 
 static bool tag_flags_validate
 	(struct sieve_validator *validator,	struct sieve_ast_argument **arg, 
-	struct sieve_command_context *cmd);
+		struct sieve_command_context *cmd);
+static bool tag_flags_generate
+	(struct sieve_generator *generator, struct sieve_ast_argument *arg,
+		struct sieve_command_context *cmd);
 
 /* Tag */
 
 const struct sieve_argument tag_flags = { 
 	"flags", NULL, 
 	tag_flags_validate, 
-	NULL, NULL 
+	NULL, 
+	tag_flags_generate 
+};
+
+/* Side effect */
+
+const struct sieve_side_effect_extension ext_flags_side_effect;
+
+bool seff_flags_read
+	(const struct sieve_side_effect *seffect, 
+		const struct sieve_runtime_env *renv, sieve_size_t *address,
+		void **se_context);
+void seff_flags_print
+	(const struct sieve_side_effect *seffect,	const struct sieve_action *action, 
+		void *se_context, bool *keep);
+bool seff_flags_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_flags_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, bool *keep);
+
+const struct sieve_side_effect flags_side_effect = {
+	"flags",
+	&act_store,
+	
+	&ext_flags_side_effect,
+	0,
+	seff_flags_read,
+	seff_flags_print,
+	NULL, NULL,
+	seff_flags_post_commit, 
+	NULL
+};
+
+const struct sieve_side_effect_extension imapflags_seffect_extension = {
+	&imapflags_extension,
+
+	SIEVE_EXT_DEFINE_SIDE_EFFECT(flags_side_effect)
 };
 
 /* Tag validation */
@@ -28,7 +75,7 @@ static bool tag_flags_validate
 	struct sieve_ast_argument *tag = *arg;
 
 	/* Detach the tag itself */
-	*arg = sieve_ast_arguments_detach(*arg,1);
+	*arg = sieve_ast_argument_next(*arg);
 	
 	/* Check syntax:
 	 *   :flags <list-of-flags: string-list>
@@ -38,8 +85,107 @@ static bool tag_flags_validate
 		return FALSE;
 	}
 	
+	tag->parameters = *arg;
+	
 	/* Detach parameter */
 	*arg = sieve_ast_arguments_detach(*arg,1);
 
 	return TRUE;
 }
+
+/* Tag generation */
+
+static bool tag_flags_generate
+(struct sieve_generator *generator, struct sieve_ast_argument *arg,
+	struct sieve_command_context *cmd)
+{
+	struct sieve_ast_argument *param;
+  struct sieve_binary *sbin = sieve_generator_get_binary(generator);
+
+  if ( sieve_ast_argument_type(arg) != SAAT_TAG ) {
+      return FALSE;
+  }
+
+  sieve_opr_side_effect_emit(sbin, &flags_side_effect, ext_imapflags_my_id);
+
+	param = arg->parameters;
+	
+	/* Call the generation function for the argument */ 
+	if ( param->argument != NULL && param->argument->generate != NULL && 
+		!param->argument->generate(generator, param, cmd) ) 
+		return FALSE;
+	
+  return TRUE;
+}
+
+/* Side effect execution */
+
+bool seff_flags_read
+(const struct sieve_side_effect *seffect ATTR_UNUSED, 
+	const struct sieve_runtime_env *renv, sieve_size_t *address,
+	void **se_context)
+{
+	pool_t pool = sieve_result_pool(renv->result);
+	ARRAY_DEFINE(flags, const char *);
+	string_t *flag_item;
+	struct sieve_coded_stringlist *flag_list;
+	
+	p_array_init(&flags, pool, 2);
+	
+	t_push();
+	
+	/* Read key-list */
+	if ( (flag_list=sieve_opr_stringlist_read(renv->sbin, address)) == NULL ) {
+		t_pop();
+		return FALSE;
+	}
+	
+	/* Iterate through all requested headers to match */
+	flag_item = NULL;
+	while ( sieve_coded_stringlist_next_item(flag_list, &flag_item) && 
+		flag_item != NULL ) {
+		const char *flag = str_c(flag_item);
+		
+		array_append(&flags, &flag, 1);
+	}
+	
+	(void)array_append_space(&flags);
+	*se_context = (void **) array_idx(&flags, 0);
+
+	t_pop();
+	
+	return TRUE;
+}
+
+void seff_flags_print
+(const struct sieve_side_effect *seffect ATTR_UNUSED, 
+	const struct sieve_action *action ATTR_UNUSED, 
+	void *se_context ATTR_UNUSED, bool *keep)
+{
+	const char *const *flags = (const char *const *) se_context;
+	
+	printf("        + add flags:");
+
+	while ( *flags != NULL ) {
+		printf(" %s", *flags);
+		
+		flags++;
+	};
+	
+	printf("\n");
+
+	*keep = TRUE;
+}
+
+bool seff_flags_post_commit
+(const struct sieve_side_effect *seffect ATTR_UNUSED, 
+	const struct sieve_action *action, 
+	const struct sieve_action_exec_env *aenv ATTR_UNUSED, 
+	void *se_context ATTR_UNUSED,	void *tr_context ATTR_UNUSED, bool *keep)
+{	
+	i_info("implicit keep preserved after %s action.", action->name);
+	*keep = TRUE;
+	return TRUE;
+}
+
+
diff --git a/src/lib-sieve/sieve-actions.h b/src/lib-sieve/sieve-actions.h
index 57d804042..a36821be9 100644
--- a/src/lib-sieve/sieve-actions.h
+++ b/src/lib-sieve/sieve-actions.h
@@ -53,6 +53,11 @@ struct sieve_side_effect {
 	
 	const struct sieve_side_effect_extension *extension;
 	unsigned int ext_code;
+	
+	bool (*read)
+		(const struct sieve_side_effect *seffect ATTR_UNUSED, 
+			const struct sieve_runtime_env *renv, sieve_size_t *address,
+			void **se_context);
 
 	void (*print)
 		(const struct sieve_side_effect *seffect, const struct sieve_action *action, 
diff --git a/src/lib-sieve/sieve-interpreter.c b/src/lib-sieve/sieve-interpreter.c
index 3e4af48f3..9bf9b7332 100644
--- a/src/lib-sieve/sieve-interpreter.c
+++ b/src/lib-sieve/sieve-interpreter.c
@@ -180,6 +180,8 @@ bool sieve_interpreter_handle_optional_operands
 				return FALSE;
 
 			if ( opt_code == SIEVE_OPT_SIDE_EFFECT ) {
+				void *context = NULL;
+			
 				if ( list != NULL && *list == NULL ) 
 					*list = sieve_side_effects_list_create(renv->result);
 					
@@ -189,9 +191,14 @@ bool sieve_interpreter_handle_optional_operands
 				if ( seffect == NULL ) return FALSE;
 			
 				printf("        : SIDE_EFFECT: %s\n", seffect->name);
+
+				if ( list != NULL ) {
+					if ( seffect->read != NULL && !seffect->read
+						(seffect, renv, address, &context) )
+						return FALSE;
 				
-				if ( list != NULL )
-					sieve_side_effects_list_add(*list, seffect, NULL);
+					sieve_side_effects_list_add(*list, seffect, context);
+				}
 			}
 		}
 	}
-- 
GitLab