dovecot-2.1-pigeonhole: Fixed interaction of Sieve include exten...

pigeonhole at rename-it.nl pigeonhole at rename-it.nl
Sat Dec 17 16:05:42 EET 2011


details:   http://hg.rename-it.nl/dovecot-2.1-pigeonhole/rev/c67b7a0aec7b
changeset: 1581:c67b7a0aec7b
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sat Dec 17 15:04:59 2011 +0100
description:
Fixed interaction of Sieve include extension with ManageSieve.
Upon upload, the include extension is more lenient towards circular includes and missing scripts as required by RFC.
The script is now also verified upon SETACTIVE when it was not active before.
However, this new SETACTIVE behavior is not optimal for the situation where the active script was updated with
PUTSCRIPT and contains an nonexistent include (ignored during upload). This can still cause runtime errors, since
an already active script is not verified again during SETACTIVE.

diffstat:

 TODO                                               |   7 +-
 src/lib-sieve/plugins/include/cmd-include.c        |  64 ++++++++++++++------
 src/lib-sieve/plugins/include/ext-include-common.c |  39 ++++++++----
 src/lib-sieve/plugins/include/ext-include-common.h |   2 +-
 src/lib-sieve/sieve-commands.h                     |   2 +
 src/lib-sieve/sieve-generator.c                    |   4 +-
 src/lib-sieve/sieve-generator.h                    |   5 +-
 src/lib-sieve/sieve-types.h                        |  12 +++-
 src/lib-sieve/sieve.c                              |   7 +-
 src/lib-sievestorage/sieve-storage-save.c          |  18 ++++++
 src/lib-sievestorage/sieve-storage-save.h          |   3 +
 src/lib-sievestorage/sieve-storage-script.c        |  32 +++++++++-
 src/lib-sievestorage/sieve-storage-script.h        |   2 +
 src/managesieve/cmd-putscript.c                    |  11 ++-
 src/managesieve/cmd-setactive.c                    |  73 ++++++++++++++++++++---
 15 files changed, 218 insertions(+), 63 deletions(-)

diffs (truncated from 641 to 300 lines):

diff -r f566e0fce176 -r c67b7a0aec7b TODO
--- a/TODO	Sat Dec 17 14:47:23 2011 +0100
+++ b/TODO	Sat Dec 17 15:04:59 2011 +0100
@@ -1,7 +1,7 @@
 Current activities:
 
-* Build a sieve tool to filter an entire existing mailbox through a Sieve 
-  script.
+* Update include extension to latest draft (v13 currently):
+	- Implement :optional tag.
 
 Parallel plugin-based efforts:
 
@@ -15,9 +15,6 @@
 Next (mostly in order of descending priority/precedence):
 
 * Implement index extension
-* Update include extension to latest draft (v10 currently):
-	- Implement :optional tag.
-	- Implement required ManageSieve behavior
 * Add normalize() method to comparators to normalize the string before matching
   (for efficiency).
 * Improve error handling. 
diff -r f566e0fce176 -r c67b7a0aec7b src/lib-sieve/plugins/include/cmd-include.c
--- a/src/lib-sieve/plugins/include/cmd-include.c	Sat Dec 17 14:47:23 2011 +0100
+++ b/src/lib-sieve/plugins/include/cmd-include.c	Sat Dec 17 15:04:59 2011 +0100
@@ -203,7 +203,8 @@
 		(struct cmd_include_context_data *) cmd->data;
 	struct sieve_script *script;
 	const char *script_path, *script_name;
-	enum sieve_error error = TRUE;
+	enum sieve_error error = SIEVE_ERROR_NONE;
+	bool include = TRUE;
 	
 	/* Check argument */
 	if ( !sieve_validate_positional_argument
@@ -251,18 +252,33 @@
 			sieve_validator_error_handler(valdtr), &error);
 
 	if ( script == NULL ) {
-		if ( error == SIEVE_ERROR_NOT_FOUND ) {
-			sieve_argument_validate_error(valdtr, arg, 
-				"included %s script '%s' does not exist", 
-				ext_include_script_location_name(ctx_data->location),
-				str_sanitize(script_name, 80));
+		if ( error != SIEVE_ERROR_NOT_FOUND ) {
+			return FALSE;
+		} else {
+			enum sieve_compile_flags cpflags =
+				sieve_validator_compile_flags(valdtr);
+
+			if ( (cpflags & SIEVE_COMPILE_FLAG_UPLOADED) != 0 ) {
+				sieve_argument_validate_warning(valdtr, arg, 
+					"included %s script '%s' does not exist (ignored during upload)", 
+					ext_include_script_location_name(ctx_data->location),
+					str_sanitize(script_name, 80));
+				include = FALSE;
+			} else {
+				sieve_argument_validate_error(valdtr, arg, 
+					"included %s script '%s' does not exist", 
+					ext_include_script_location_name(ctx_data->location),
+					str_sanitize(script_name, 80));
+				return FALSE;
+			}
 		}
-		return FALSE;
 	}
 
-	ext_include_ast_link_included_script(cmd->ext, cmd->ast_node->ast, script);		
-	ctx_data->script = script;
-		
+	if ( include ) {
+		ext_include_ast_link_included_script(cmd->ext, cmd->ast_node->ast, script);		
+		ctx_data->script = script;
+	}
+	
 	arg = sieve_ast_arguments_detach(arg, 1);
 	
 	return TRUE;
@@ -279,18 +295,26 @@
 		(struct cmd_include_context_data *) cmd->data;
 	const struct ext_include_script_info *included;
 	unsigned int flags = ctx_data->include_once;
+	int ret;
 
-	/* Compile (if necessary) and include the script into the binary.
-	 * This yields the id of the binary block containing the compiled byte code.  
+	/* Upon upload ctx_data->script may be NULL if the script was not found. We
+	 * don't emit any code for this include command in that case.
 	 */
-	if ( !ext_include_generate_include
-		(cgenv, cmd, ctx_data->location, ctx_data->script, &included,
-			ctx_data->include_once) )
- 		return FALSE;
- 		
- 	(void)sieve_operation_emit(cgenv->sblock, cmd->ext, &include_operation);
-	(void)sieve_binary_emit_unsigned(cgenv->sblock, included->id); 
-	(void)sieve_binary_emit_byte(cgenv->sblock, flags); 
+	if ( ctx_data->script != NULL ) {
+		/* Compile (if necessary) and include the script into the binary.
+		 * This yields the id of the binary block containing the compiled byte code.  
+		 */
+		if ( (ret=ext_include_generate_include
+			(cgenv, cmd, ctx_data->location, ctx_data->script, &included,
+				ctx_data->include_once)) < 0 )
+	 		return FALSE;
+	 		
+		if ( ret > 0 ) {
+		 	(void)sieve_operation_emit(cgenv->sblock, cmd->ext, &include_operation);
+			(void)sieve_binary_emit_unsigned(cgenv->sblock, included->id); 
+			(void)sieve_binary_emit_byte(cgenv->sblock, flags);
+		}
+	}
  	 		
 	return TRUE;
 }
diff -r f566e0fce176 -r c67b7a0aec7b src/lib-sieve/plugins/include/ext-include-common.c
--- a/src/lib-sieve/plugins/include/ext-include-common.c	Sat Dec 17 14:47:23 2011 +0100
+++ b/src/lib-sieve/plugins/include/ext-include-common.c	Sat Dec 17 15:04:59 2011 +0100
@@ -462,7 +462,7 @@
  * Including a script during code generation 
  */
 
-bool ext_include_generate_include
+int ext_include_generate_include
 (const struct sieve_codegen_env *cgenv, struct sieve_command *cmd,
 	enum ext_include_script_location location, struct sieve_script *script, 
 	const struct ext_include_script_info **included_r, bool once)
@@ -470,7 +470,7 @@
 	const struct sieve_extension *this_ext = cmd->ext;
 	struct ext_include_context *ext_ctx =
 		(struct ext_include_context *)this_ext->context;
-	bool result = TRUE;
+	int result = 1;
 	struct sieve_ast *ast;
 	struct sieve_binary *sbin = cgenv->sbin;
 	struct sieve_generator *gentr = cgenv->gentr;
@@ -488,14 +488,14 @@
 	 * already. 
 	 */
 	if ( sieve_get_errors(ehandler) > 0 )
-		return FALSE;
+		return -1;
 		
 	/* Limit nesting level */
 	if ( ctx->nesting_depth >= ext_ctx->max_nesting_depth ) {
 		sieve_command_generate_error
 			(gentr, cmd, "cannot nest includes deeper than %d levels",
 				ext_ctx->max_nesting_depth);
-		return FALSE;
+		return -1;
 	}
 	
 	/* Check for circular include */
@@ -503,9 +503,18 @@
 		pctx = ctx;
 		while ( pctx != NULL ) {
 			if ( sieve_script_equals(pctx->script, script) ) {
+				/* Just drop circular include when uploading inactive script;
+				 * not an error
+				 */
+				if ( (cgenv->flags & SIEVE_COMPILE_FLAG_UPLOADED) != 0 && 
+					(cgenv->flags & SIEVE_COMPILE_FLAG_ACTIVATED) == 0 ) {
+					sieve_command_generate_warning
+						(gentr, cmd, "circular include (ignored during upload)");
+					return 0;
+				}
+
 				sieve_command_generate_error(gentr, cmd, "circular include");
-				
-				return FALSE;
+				return -1;
 			}
 		
 			pctx = pctx->parent;
@@ -520,7 +529,7 @@
 	{	
 		struct sieve_binary_block *inc_block;
 		const char *script_name = sieve_script_name(script);
-		enum sieve_compile_flags cpflags = 0;
+		enum sieve_compile_flags cpflags = cgenv->flags;
 
 		/* Check whether include limit is exceeded */
 		if ( ext_include_binary_script_get_count(binctx) >= 
@@ -528,7 +537,7 @@
 	 		sieve_command_generate_error(gentr, cmd, 
 	 			"failed to include script '%s': no more than %u includes allowed", 
 				str_sanitize(script_name, 80), ext_ctx->max_includes);
-	 		return FALSE;			
+	 		return -1;
 		}
 		
 		/* No, allocate a new block in the binary and mark the script as included.
@@ -541,13 +550,15 @@
 		if ( (ast = sieve_parse(script, ehandler, NULL)) == NULL ) {
 	 		sieve_command_generate_error(gentr, cmd, 
 	 			"failed to parse included script '%s'", str_sanitize(script_name, 80));
-	 		return FALSE;
+	 		return -1;
 		}
 		
 		/* Included scripts inherit global variable scope */
 		(void)ext_include_create_ast_context(this_ext, ast, cmd->ast_node->ast);
 
-		if ( location != EXT_INCLUDE_LOCATION_GLOBAL )
+		if ( location == EXT_INCLUDE_LOCATION_GLOBAL )
+				cpflags &= ~SIEVE_RUNTIME_FLAG_NOGLOBAL;
+		else
 				cpflags |= SIEVE_RUNTIME_FLAG_NOGLOBAL;
 
 		/* Validate */
@@ -556,7 +567,7 @@
 				"failed to validate included script '%s'", 
 				str_sanitize(script_name, 80));
 	 		sieve_ast_unref(&ast);
-	 		return FALSE;
+	 		return -1;
 	 	}
 
 		/* Generate 
@@ -564,14 +575,14 @@
 		 * FIXME: It might not be a good idea to recurse code generation for 
 		 * included scripts.
 		 */
-	 	subgentr = sieve_generator_create(ast, ehandler);			
+	 	subgentr = sieve_generator_create(ast, ehandler, cpflags);			
 		ext_include_initialize_generator_context(cmd->ext, subgentr, ctx, script);
 			
 		if ( sieve_generator_run(subgentr, &inc_block) == NULL ) {
 			sieve_command_generate_error(gentr, cmd, 
 				"failed to generate code for included script '%s'", 
 				str_sanitize(script_name, 80));
-	 		result = FALSE;
+	 		result = -1;
 		}
 		
 		sieve_generator_free(&subgentr);
@@ -580,7 +591,7 @@
 		sieve_ast_unref(&ast);		
 	} 
 
-	if ( result ) *included_r = included;
+	if ( result > 0 ) *included_r = included;
 	
 	return result;
 }
diff -r f566e0fce176 -r c67b7a0aec7b src/lib-sieve/plugins/include/ext-include-common.h
--- a/src/lib-sieve/plugins/include/ext-include-common.h	Sat Dec 17 14:47:23 2011 +0100
+++ b/src/lib-sieve/plugins/include/ext-include-common.h	Sat Dec 17 15:04:59 2011 +0100
@@ -142,7 +142,7 @@
 	(const struct sieve_extension *this_ext, 
 		const struct sieve_codegen_env *cgenv);
 
-bool ext_include_generate_include
+int ext_include_generate_include
 	(const struct sieve_codegen_env *cgenv, struct sieve_command *cmd,
 		enum ext_include_script_location location, struct sieve_script *script, 
 		const struct ext_include_script_info **included_r, bool once);
diff -r f566e0fce176 -r c67b7a0aec7b src/lib-sieve/sieve-commands.h
--- a/src/lib-sieve/sieve-commands.h	Sat Dec 17 14:47:23 2011 +0100
+++ b/src/lib-sieve/sieve-commands.h	Sat Dec 17 15:04:59 2011 +0100
@@ -200,6 +200,8 @@
 
 #define sieve_command_generate_error(gentr, context, ...) \
 	sieve_generator_error(gentr, (context)->ast_node->source_line, __VA_ARGS__)
+#define sieve_command_generate_warning(gentr, context, ...) \
+	sieve_generator_warning(gentr, (context)->ast_node->source_line, __VA_ARGS__)
 
 /* Utility macros */
 
diff -r f566e0fce176 -r c67b7a0aec7b src/lib-sieve/sieve-generator.c
--- a/src/lib-sieve/sieve-generator.c	Sat Dec 17 14:47:23 2011 +0100
+++ b/src/lib-sieve/sieve-generator.c	Sat Dec 17 15:04:59 2011 +0100
@@ -76,7 +76,8 @@
 };
 
 struct sieve_generator *sieve_generator_create
-(struct sieve_ast *ast, struct sieve_error_handler *ehandler) 
+(struct sieve_ast *ast, struct sieve_error_handler *ehandler,
+	enum sieve_compile_flags flags) 
 {
 	pool_t pool;
 	struct sieve_generator *gentr;
@@ -91,6 +92,7 @@
 	sieve_error_handler_ref(ehandler);
 	
 	gentr->genenv.gentr = gentr;
+	gentr->genenv.flags = flags;
 	gentr->genenv.ast = ast;	
 	sieve_ast_ref(ast);
 
diff -r f566e0fce176 -r c67b7a0aec7b src/lib-sieve/sieve-generator.h
--- a/src/lib-sieve/sieve-generator.h	Sat Dec 17 14:47:23 2011 +0100
+++ b/src/lib-sieve/sieve-generator.h	Sat Dec 17 15:04:59 2011 +0100
@@ -16,6 +16,8 @@
 	struct sieve_generator *gentr;
 
 	struct sieve_instance *svinst;
+	enum sieve_compile_flags flags;
+


More information about the dovecot-cvs mailing list