From d76b84ac7a631e7cfc371726f559cf2630f6ecea Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Sat, 18 Apr 2009 10:10:21 +0200
Subject: [PATCH] Improved error message for unknown Sieve extension to account
 for core commands included as an extension.

---
 src/lib-sieve/cmd-require.c        |  4 +--
 src/lib-sieve/sieve-validator.c    | 39 +++++++++++++++++++++++++-----
 src/lib-sieve/sieve-validator.h    |  4 +--
 tests/compile/errors.svtest        |  2 +-
 tests/compile/errors/require.sieve |  3 +++
 5 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/src/lib-sieve/cmd-require.c b/src/lib-sieve/cmd-require.c
index 1f3e12941..a54f24740 100644
--- a/src/lib-sieve/cmd-require.c
+++ b/src/lib-sieve/cmd-require.c
@@ -57,7 +57,7 @@ static bool cmd_require_validate
 	if ( sieve_ast_argument_type(arg) == SAAT_STRING ) {
 		/* Single string */
 		const struct sieve_extension *ext = sieve_validator_extension_load
-			(validator, arg, sieve_ast_argument_str(arg));	
+			(validator, cmd, arg, sieve_ast_argument_str(arg));	
 
 		if ( ext == NULL ) result = FALSE;
 		
@@ -67,7 +67,7 @@ static bool cmd_require_validate
 		
 		while ( stritem != NULL ) {
 			const struct sieve_extension *ext = sieve_validator_extension_load
-				(validator, stritem, sieve_ast_strlist_str(stritem));
+				(validator, cmd, stritem, sieve_ast_strlist_str(stritem));
 
 			if ( ext == NULL ) result = FALSE;
 	
diff --git a/src/lib-sieve/sieve-validator.c b/src/lib-sieve/sieve-validator.c
index ffc6b8d71..cec3c0fe0 100644
--- a/src/lib-sieve/sieve-validator.c
+++ b/src/lib-sieve/sieve-validator.c
@@ -511,8 +511,8 @@ static const struct sieve_argument *sieve_validator_find_tag_by_identifier
  */
 
 const struct sieve_extension *sieve_validator_extension_load
-(struct sieve_validator *valdtr, struct sieve_ast_argument *ext_arg, 
-	string_t *ext_name) 
+(struct sieve_validator *valdtr, struct sieve_command_context *cmd,
+	struct sieve_ast_argument *ext_arg, string_t *ext_name) 
 {
 	int ext_id;
 	struct sieve_validator_extension_reg *reg;
@@ -521,7 +521,8 @@ const struct sieve_extension *sieve_validator_extension_load
 
 	if ( str_len(ext_name) > 128 ) {
 		sieve_argument_validate_error(valdtr, ext_arg, 
-			"unsupported sieve capability '%s' (name is impossibly long)", 
+			"%s %s: unknown Sieve capability '%s' (name is impossibly long)",
+			cmd->command->identifier, sieve_command_type_name(cmd->command),
 			str_sanitize(name, 128));
 		return NULL;
 	}
@@ -529,8 +530,32 @@ const struct sieve_extension *sieve_validator_extension_load
 	ext = sieve_extension_get_by_name(name); 
 	
 	if ( ext == NULL ) {
-		sieve_argument_validate_error(valdtr, ext_arg, 
-			"unsupported sieve capability '%s'", name);
+		unsigned int i;
+		bool core_test = FALSE;
+		bool core_command = FALSE;
+
+		for ( i = 0; !core_command && i < sieve_core_commands_count; i++ ) {
+			if ( strcasecmp(sieve_core_commands[i]->identifier, name) == 0 )
+				core_command = TRUE;
+		}
+
+		for ( i = 0; !core_test && i < sieve_core_tests_count; i++ ) {
+			if ( strcasecmp(sieve_core_tests[i]->identifier, name) == 0 )
+				core_test = TRUE;
+		}
+
+		if ( core_test || core_command ) {
+			sieve_argument_validate_error(valdtr, ext_arg,
+                "%s %s: '%s' is not known as a Sieve capability, "
+				"but it is known as a Sieve %s that is always available",
+                cmd->command->identifier, sieve_command_type_name(cmd->command),
+                name, ( core_test ? "test" : "command" ));
+		} else {
+			sieve_argument_validate_error(valdtr, ext_arg,
+				"%s %s: unknown Sieve capability '%s'", 
+				cmd->command->identifier, sieve_command_type_name(cmd->command),
+				name);
+		}
 		return NULL;
 	}
 	
@@ -538,7 +563,9 @@ const struct sieve_extension *sieve_validator_extension_load
 
 	if ( ext->validator_load != NULL && !ext->validator_load(valdtr) ) {
 		sieve_argument_validate_error(valdtr, ext_arg, 
-			"failed to load sieve capability '%s'", ext->name);
+			"%s %s: failed to load Sieve capability '%s'",
+			cmd->command->identifier, sieve_command_type_name(cmd->command),
+			ext->name);
 		return NULL;
 	}
 
diff --git a/src/lib-sieve/sieve-validator.h b/src/lib-sieve/sieve-validator.h
index ca8b59fd3..7b0fab3cd 100644
--- a/src/lib-sieve/sieve-validator.h
+++ b/src/lib-sieve/sieve-validator.h
@@ -128,8 +128,8 @@ struct sieve_validator_extension {
 };
 
 const struct sieve_extension *sieve_validator_extension_load
-	(struct sieve_validator *validator, struct sieve_ast_argument *ext_arg, 
-		string_t *ext_name); 
+	(struct sieve_validator *validator, struct sieve_command_context *cmd,
+		struct sieve_ast_argument *ext_arg, string_t *ext_name); 
 
 void sieve_validator_extension_register
 	(struct sieve_validator *valdtr, 
diff --git a/tests/compile/errors.svtest b/tests/compile/errors.svtest
index 99e48332f..7bbfc6c6c 100644
--- a/tests/compile/errors.svtest
+++ b/tests/compile/errors.svtest
@@ -181,7 +181,7 @@ test "Require errors (FIXME: count only)" {
 		test_fail "compile should have failed.";
 	}
 
-	if not test_error :count "eq" :comparator "i;ascii-numeric" "12" {
+	if not test_error :count "eq" :comparator "i;ascii-numeric" "15" {
 		test_fail "wrong number of errors reported";
 	}	
 }
diff --git a/tests/compile/errors/require.sieve b/tests/compile/errors/require.sieve
index 93508ad58..9670bf1b7 100644
--- a/tests/compile/errors/require.sieve
+++ b/tests/compile/errors/require.sieve
@@ -19,6 +19,9 @@ require 45;
 # Invalid extensions (3 errors)
 require ["_frop", "_friep", "_frml"];
 
+# Core commands required
+require ["redirect", "keep", "discard"];
+
 # Invalid arguments
 require "dovecot.test" true;
 
-- 
GitLab