From f32edce23ecb2ba0ca6387a2aec57856bd05f543 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Tue, 20 Nov 2007 12:29:58 +0100
Subject: [PATCH] Made regex match complaint about comparators other than
 i;octet or i;ascii-casemap

---
 src/lib-sieve/plugins/regex/ext-regex.c       | 37 ++++++++++++++++++-
 .../plugins/regex/regex-errors.sieve          |  9 +++++
 src/lib-sieve/sieve-commands.h                | 11 ++++--
 src/lib-sieve/sieve-comparators.c             |  7 ++++
 src/lib-sieve/sieve-comparators.h             |  8 +++-
 src/lib-sieve/sieve-validator.c               |  3 +-
 6 files changed, 67 insertions(+), 8 deletions(-)
 create mode 100644 src/lib-sieve/plugins/regex/regex-errors.sieve

diff --git a/src/lib-sieve/plugins/regex/ext-regex.c b/src/lib-sieve/plugins/regex/ext-regex.c
index ab8ae3d0c..829d3d30e 100644
--- a/src/lib-sieve/plugins/regex/ext-regex.c
+++ b/src/lib-sieve/plugins/regex/ext-regex.c
@@ -13,7 +13,10 @@
 #include "sieve-code.h"
 #include "sieve-extensions.h"
 #include "sieve-commands.h"
+
+#include "sieve-comparators.h"
 #include "sieve-match-types.h"
+
 #include "sieve-validator.h"
 #include "sieve-generator.h"
 #include "sieve-interpreter.h"
@@ -53,13 +56,17 @@ static bool ext_regex_load(int ext_id)
 
 extern const struct sieve_match_type_extension regex_match_extension;
 
+bool mtch_regex_validate_context
+(struct sieve_validator *validator, struct sieve_ast_argument *arg,
+    struct sieve_match_type_context *ctx);
+
 const struct sieve_match_type regex_match_type = {
 	"regex",
 	SIEVE_MATCH_TYPE_CUSTOM,
 	&regex_match_extension,
 	0,
 	NULL,
-	NULL,
+	mtch_regex_validate_context,
 	NULL
 };
 
@@ -69,6 +76,34 @@ const struct sieve_match_type_extension regex_match_extension = {
 	NULL
 };
 
+/* Validation */
+
+bool mtch_regex_validate_context
+(struct sieve_validator *validator, struct sieve_ast_argument *arg,
+	struct sieve_match_type_context *ctx)
+{
+	struct sieve_ast_argument *carg = 
+		sieve_command_first_argument(ctx->command_ctx);
+
+	while ( carg != NULL ) {
+		if ( carg != arg && carg->argument == &comparator_tag ) {
+			if (!sieve_comparator_tag_is(carg, &i_ascii_casemap_comparator) &&
+				!sieve_comparator_tag_is(carg, &i_octet_comparator) )
+			{
+				sieve_command_validate_error(validator, ctx->command_ctx, 
+					"regex match type only supports i;octet and i;ascii-casemap comparators" );
+				return FALSE;	
+			}
+
+			return TRUE;
+		}
+	
+		carg = sieve_ast_argument_next(carg);
+	}
+
+	return TRUE;
+}
+
 /* Load extension into validator */
 
 static bool ext_regex_validator_load(struct sieve_validator *validator)
diff --git a/src/lib-sieve/plugins/regex/regex-errors.sieve b/src/lib-sieve/plugins/regex/regex-errors.sieve
new file mode 100644
index 000000000..10b8b6a65
--- /dev/null
+++ b/src/lib-sieve/plugins/regex/regex-errors.sieve
@@ -0,0 +1,9 @@
+require "regex";
+require "comparator-i;ascii-numeric";
+
+if address :regex :comparator "i;ascii-numeric" "from" "sirius(\\+.*)?@drunksnipers\\.com" {
+	keep;
+	stop;
+}
+
+discard;
diff --git a/src/lib-sieve/sieve-commands.h b/src/lib-sieve/sieve-commands.h
index 30c7c6ae4..bc41804e8 100644
--- a/src/lib-sieve/sieve-commands.h
+++ b/src/lib-sieve/sieve-commands.h
@@ -83,14 +83,17 @@ struct sieve_command_context *sieve_command_context_create
 const char *sieve_command_type_name(const struct sieve_command *command);		
 		
 #define sieve_command_validate_error(validator, context, ...) \
-	sieve_validator_error(validator, context->ast_node, __VA_ARGS__)
+	sieve_validator_error(validator, (context)->ast_node, __VA_ARGS__)
 #define sieve_command_pool(context) \
-	sieve_ast_node_pool(context->ast_node)
+	sieve_ast_node_pool((context)->ast_node)
+
+#define sieve_command_first_argument(context) \
+	sieve_ast_argument_first((context)->ast_node)
 	
 #define sieve_command_is_toplevel(context) \
-	( sieve_ast_node_type(sieve_ast_node_parent(context->ast_node)) == SAT_ROOT )
+	( sieve_ast_node_type(sieve_ast_node_parent((context)->ast_node)) == SAT_ROOT )
 #define sieve_command_is_first(context) \
-	( sieve_ast_node_prev(context->ast_node) == NULL )	
+	( sieve_ast_node_prev((context)->ast_node) == NULL )	
 
 struct sieve_command_context *sieve_command_prev_context	
 	(struct sieve_command_context *context); 
diff --git a/src/lib-sieve/sieve-comparators.c b/src/lib-sieve/sieve-comparators.c
index 2dfdf6e10..24a2a77ae 100644
--- a/src/lib-sieve/sieve-comparators.c
+++ b/src/lib-sieve/sieve-comparators.c
@@ -285,6 +285,13 @@ void sieve_comparators_link_tag
 	sieve_validator_register_tag(validator, cmd_reg, &comparator_tag, id_code); 	
 }
 
+inline bool sieve_comparator_tag_is
+(struct sieve_ast_argument *tag, const struct sieve_comparator *cmp)
+{
+	return (tag->argument == &comparator_tag && 
+		((const struct sieve_comparator *) tag->context) == cmp);
+}
+
 /* Code generation */
 
 static void opr_comparator_emit
diff --git a/src/lib-sieve/sieve-comparators.h b/src/lib-sieve/sieve-comparators.h
index 70ce48e55..4bd564511 100644
--- a/src/lib-sieve/sieve-comparators.h
+++ b/src/lib-sieve/sieve-comparators.h
@@ -47,13 +47,17 @@ struct sieve_comparator_extension {
 		(unsigned int code);
 };
 
+extern const struct sieve_argument comparator_tag;
+
 void sieve_comparators_link_tag
 	(struct sieve_validator *validator, 
 		struct sieve_command_registration *cmd_reg,	
 		unsigned int id_code);
+inline bool sieve_comparator_tag_is
+(struct sieve_ast_argument *tag, const struct sieve_comparator *cmp);
 
-const struct sieve_comparator i_octet_comparator;
-const struct sieve_comparator i_ascii_casemap_comparator;
+extern const struct sieve_comparator i_octet_comparator;
+extern const struct sieve_comparator i_ascii_casemap_comparator;
 
 void sieve_comparator_register
 	(struct sieve_validator *validator, 
diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c
index 5cb8997a6..715903ff4 100644
--- a/src/lib-sieve/sieve-validator.c
+++ b/src/lib-sieve/sieve-validator.c
@@ -465,7 +465,8 @@ static bool sieve_validate_command_arguments
 static bool sieve_validate_arguments_context
 (struct sieve_validator *validator, struct sieve_command_context *cmd)
 { 
-	struct sieve_ast_argument *arg = sieve_ast_argument_first(cmd->ast_node);
+	struct sieve_ast_argument *arg = 
+		sieve_command_first_argument(cmd);
 	
 	while ( arg != NULL ) {
 		const struct sieve_argument *argument = arg->argument;
-- 
GitLab