From 5523de35762160214ea3f1405416959a15ce9bc2 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Wed, 23 Dec 2009 12:27:38 +0100
Subject: [PATCH] Include extension: implemented global variables namespace.

---
 TODO                                          |   1 -
 src/lib-sieve/plugins/include/cmd-global.c    |   2 +-
 .../plugins/include/ext-include-common.c      |   5 +-
 .../plugins/include/ext-include-variables.c   | 104 ++++++++++++++++++
 .../plugins/include/ext-include-variables.h   |   7 ++
 src/lib-sieve/plugins/include/ext-include.c   |  16 ++-
 6 files changed, 126 insertions(+), 9 deletions(-)

diff --git a/TODO b/TODO
index ce91b4ae3..1bc9ae1a8 100644
--- a/TODO
+++ b/TODO
@@ -13,7 +13,6 @@ Current activities:
 Next (in order of descending priority/precedence):
 
 * Update include extension to latest draft:
-	- Implement global namespace
 	- Allow placing the global command anywhere in the script
 	- Implement required ManageSieve behavior
 * Implement mechanism for implicitly including an account's aliases in the
diff --git a/src/lib-sieve/plugins/include/cmd-global.c b/src/lib-sieve/plugins/include/cmd-global.c
index b8952547e..8a5f5322d 100644
--- a/src/lib-sieve/plugins/include/cmd-global.c
+++ b/src/lib-sieve/plugins/include/cmd-global.c
@@ -128,7 +128,7 @@ static bool cmd_global_validate
 			if ( !sieve_command_is(prev, cmd_import) && 
 				!sieve_command_is(prev, cmd_export) ) {
 				sieve_command_validate_error(valdtr, cmd,
-					"the DEPRICATED %s command can only be placed at top level "
+					"the DEPRECATED %s command can only be placed at top level "
 					"at the beginning of the file after any require or "
 					"import/export commands",
 					sieve_command_identifier(cmd));
diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c
index ce0a7f716..9f9ba6742 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.c
+++ b/src/lib-sieve/plugins/include/ext-include-common.c
@@ -464,7 +464,8 @@ bool ext_include_generate_include
 		/* Validate */
 		if ( !sieve_validate(ast, ehandler) ) {
 			sieve_command_generate_error(gentr, cmd, 
-				"failed to validate included script '%s'", str_sanitize(script_name, 80));
+				"failed to validate included script '%s'", 
+				str_sanitize(script_name, 80));
 	 		sieve_ast_unref(&ast);
 	 		return FALSE;
 	 	}
@@ -487,7 +488,9 @@ bool ext_include_generate_include
 			
 			if ( sbin != NULL )		
 				(void) sieve_binary_block_set_active(sbin, this_block_id, NULL); 	
+
 			sieve_generator_free(&subgentr);
+
 		} else {
 			sieve_sys_error("include: failed to activate binary  block %d for "
 				"generating code for the included script", inc_block_id);
diff --git a/src/lib-sieve/plugins/include/ext-include-variables.c b/src/lib-sieve/plugins/include/ext-include-variables.c
index a0fb7c8b8..c9083627a 100644
--- a/src/lib-sieve/plugins/include/ext-include-variables.c
+++ b/src/lib-sieve/plugins/include/ext-include-variables.c
@@ -150,3 +150,107 @@ bool ext_include_variables_dump
 
 	return TRUE;
 }
+
+/*
+ * Global variables namespace
+ */
+
+bool vnspc_global_variables_validate
+	(struct sieve_validator *valdtr, const struct sieve_variables_namespace *nspc,
+		struct sieve_ast_argument *arg, struct sieve_command *cmd, 
+		ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, 
+		bool assignment);
+bool vnspc_global_variables_generate
+	(const struct sieve_codegen_env *cgenv, 
+		const struct sieve_variables_namespace *nspc,
+		struct sieve_ast_argument *arg, struct sieve_command *cmd, void *var_data);
+
+static const struct sieve_variables_namespace_def global_variables_namespace = {
+	SIEVE_OBJECT("global", NULL, 0),
+	vnspc_global_variables_validate,  
+	vnspc_global_variables_generate,
+	NULL, NULL
+};
+
+
+bool vnspc_global_variables_validate
+(struct sieve_validator *valdtr, 
+	const struct sieve_variables_namespace *nspc, struct sieve_ast_argument *arg,
+	struct sieve_command *cmd ATTR_UNUSED, 
+	ARRAY_TYPE(sieve_variable_name) *var_name, void **var_data, 
+	bool assignment ATTR_UNUSED)
+{
+	const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc);
+	struct sieve_ast *ast = arg->ast;
+	struct ext_include_ast_context *ctx = 
+		ext_include_get_ast_context(this_ext, ast);
+	struct sieve_variable *var = NULL;
+	const struct sieve_variable_name *name_element;
+	const char *variable;
+
+	/* Sanity safeguard */	
+	i_assert ( ctx->global_vars != NULL );
+
+	/* Check variable name */
+
+	if ( array_count(var_name) != 2 ) {
+		sieve_argument_validate_error(valdtr, arg, 
+			"invalid variable name within global namespace: "
+			"encountered sub-namespace");
+		return FALSE;
+	}
+
+	name_element = array_idx(var_name, 1);
+	if ( name_element->num_variable >= 0 ) {
+		sieve_argument_validate_error(valdtr, arg, 
+			"invalid variable name within global namespace: "
+			"encountered numeric variable name");
+		return FALSE;
+	}
+	
+	variable = str_c(name_element->identifier);
+
+	/* Get/Declare the variable in the global scope */
+
+	var = sieve_variable_scope_get_variable(ctx->global_vars, variable, TRUE);
+
+	if ( var == NULL ) {
+		sieve_argument_validate_error(valdtr, arg, 
+			"(implicit) declaration of new global variable '%s' exceeds the limit "
+			"(max variables: %u)", variable, 
+			SIEVE_VARIABLES_MAX_SCOPE_SIZE);
+		return FALSE;
+	}
+	
+	*var_data = (void *) var;
+
+	return TRUE;
+}
+
+bool vnspc_global_variables_generate
+(const struct sieve_codegen_env *cgenv, 
+	const struct sieve_variables_namespace *nspc,	
+	struct sieve_ast_argument *arg ATTR_UNUSED,	
+	struct sieve_command *cmd ATTR_UNUSED, void *var_data)
+{
+	const struct sieve_extension *this_ext = SIEVE_OBJECT_EXTENSION(nspc);
+	struct ext_include_context *ectx = ext_include_get_context(this_ext);
+
+	struct sieve_variable *var = (struct sieve_variable *) var_data;
+	
+	sieve_variables_opr_variable_emit(cgenv->sbin, ectx->var_ext, var);
+
+	return TRUE;
+}
+
+void ext_include_variables_global_namespace_init
+(const struct sieve_extension *this_ext, struct sieve_validator *valdtr)
+{
+	struct ext_include_context *ectx = ext_include_get_context(this_ext);
+
+	sieve_variables_namespace_register
+		(ectx->var_ext, valdtr, this_ext, &global_variables_namespace);
+}
+
+
+
diff --git a/src/lib-sieve/plugins/include/ext-include-variables.h b/src/lib-sieve/plugins/include/ext-include-variables.h
index 231ed2c1d..382a2bd85 100644
--- a/src/lib-sieve/plugins/include/ext-include-variables.h
+++ b/src/lib-sieve/plugins/include/ext-include-variables.h
@@ -30,6 +30,13 @@ bool ext_include_variables_load
 		struct sieve_variable_scope **global_vars_r);
 bool ext_include_variables_dump
 	(struct sieve_dumptime_env *denv, struct sieve_variable_scope *global_vars);
+
+/*
+ * Validation
+ */
+
+void ext_include_variables_global_namespace_init
+	(const struct sieve_extension *this_ext, struct sieve_validator *valdtr);
 		
 #endif /* __EXT_INCLUDE_VARIABLES_H */
 
diff --git a/src/lib-sieve/plugins/include/ext-include.c b/src/lib-sieve/plugins/include/ext-include.c
index 90b40ad80..4ab6cfaac 100644
--- a/src/lib-sieve/plugins/include/ext-include.c
+++ b/src/lib-sieve/plugins/include/ext-include.c
@@ -31,6 +31,7 @@
 
 #include "ext-include-common.h"
 #include "ext-include-binary.h"
+#include "ext-include-variables.h"
 
 /* 
  * Operations 
@@ -102,16 +103,19 @@ static void ext_include_unload
 }
 
 static bool ext_include_validator_load
-(const struct sieve_extension *ext, struct sieve_validator *validator)
+(const struct sieve_extension *ext, struct sieve_validator *valdtr)
 {
 	/* Register new commands */
-	sieve_validator_register_command(validator, ext, &cmd_include);
-	sieve_validator_register_command(validator, ext, &cmd_return);
-	sieve_validator_register_command(validator, ext, &cmd_global);
+	sieve_validator_register_command(valdtr, ext, &cmd_include);
+	sieve_validator_register_command(valdtr, ext, &cmd_return);
+	sieve_validator_register_command(valdtr, ext, &cmd_global);
 
 	/* DEPRICATED */
-	sieve_validator_register_command(validator, ext, &cmd_import);
-	sieve_validator_register_command(validator, ext, &cmd_export);
+	sieve_validator_register_command(valdtr, ext, &cmd_import);
+	sieve_validator_register_command(valdtr, ext, &cmd_export);
+
+	/* Initialize global variables namespace */
+	ext_include_variables_global_namespace_init(ext, valdtr);
 
 	return TRUE;
 }	
-- 
GitLab