From 031af6a259c38f3f5bba68935033c9b4727f26a3 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 25 Dec 2008 23:26:59 +0100
Subject: [PATCH] Enotify: implemented notify_method_capability test.

---
 Makefile.am                                   |  2 +
 TODO                                          |  1 -
 .../plugins/enotify/ext-enotify-common.c      | 95 +++++++++++++------
 .../plugins/enotify/ext-enotify-common.h      |  4 +
 src/lib-sieve/plugins/enotify/ntfy-mailto.c   | 23 ++++-
 .../plugins/enotify/sieve-ext-enotify.h       |  3 +
 .../enotify/tst-notify-method-capability.c    | 35 +++----
 .../enotify/notify_method_capability.svtest   | 12 +++
 ...thod.svtest => valid_notify_method.svtest} |  8 +-
 9 files changed, 127 insertions(+), 56 deletions(-)
 create mode 100644 tests/extensions/enotify/notify_method_capability.svtest
 rename tests/extensions/enotify/{valid-notify-method.svtest => valid_notify_method.svtest} (77%)

diff --git a/Makefile.am b/Makefile.am
index 832e2806e..33444572f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,6 +24,8 @@ if BUILD_ENOTIFY
 ENOTIFY_TESTS = \
 	tests/extensions/enotify/basic.svtest \
 	tests/extensions/enotify/encodeurl.svtest \
+	tests/extensions/enotify/valid_notify_method.svtest \
+	tests/extensions/enotify/notify_method_capability.svtest \
 	tests/extensions/enotify/errors.svtest \
 	tests/extensions/enotify/execute.svtest
 endif
diff --git a/TODO b/TODO
index 807c5b9ff..f9ca65dda 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,6 @@
 Current:
 
 * Implement enotify extension:
-	- Implement notify_method_capability test (currently skeleton)
 	- Implement parsing :options argument
 	- Check whether handling of error conditions matches the standard
 	- Limit the number of notifications generated (on a per-method basis)
diff --git a/src/lib-sieve/plugins/enotify/ext-enotify-common.c b/src/lib-sieve/plugins/enotify/ext-enotify-common.c
index c9756a333..c26a801a5 100644
--- a/src/lib-sieve/plugins/enotify/ext-enotify-common.c
+++ b/src/lib-sieve/plugins/enotify/ext-enotify-common.c
@@ -196,10 +196,42 @@ bool ext_enotify_compile_check_arguments
 /*
  * Runtime operand checking
  */
+ 
+bool ext_enotify_runtime_method_validate
+(const struct sieve_runtime_env *renv, unsigned int source_line,
+	string_t *method_uri)
+{
+	const struct sieve_enotify_method *method;
+	const char *uri = str_c(method_uri);
+	const char *scheme;
+	
+	if ( (scheme=ext_enotify_uri_scheme_parse(&uri)) == NULL )
+		return FALSE;
+	
+	if ( (method=ext_enotify_method_find(scheme)) == NULL )
+		return FALSE;
+	
+	if ( method->runtime_check_operands != NULL ) {
+		struct sieve_enotify_log nlog;
+		
+		memset(&nlog, 0, sizeof(nlog));
+		nlog.location = sieve_error_script_location(renv->script, source_line);
+		nlog.ehandler = sieve_interpreter_get_error_handler(renv->interp);
+		nlog.prefix = "valid_notify_method test";
 
-const struct sieve_enotify_method *ext_enotify_runtime_check_operands
+		if ( method->runtime_check_operands
+			(&nlog, str_c(method_uri), uri, NULL, NULL, NULL, NULL) )
+			return TRUE;
+		
+		return FALSE;
+	}
+
+	return TRUE;
+}
+ 
+static const struct sieve_enotify_method *ext_enotify_get_method
 (const struct sieve_runtime_env *renv, unsigned int source_line,
-	string_t *method_uri, string_t *message, string_t *from, void **context)
+	string_t *method_uri, const char **uri_body_r)
 {
 	const struct sieve_enotify_method *method;
 	const char *uri = str_c(method_uri);
@@ -219,39 +251,48 @@ const struct sieve_enotify_method *ext_enotify_runtime_check_operands
 				"invalid notify method '%s'", scheme);
 		return NULL;
 	}
+
+	*uri_body_r = uri;
 	
-	if ( method->runtime_check_operands != NULL ) {
+	return method;
+}
+
+const char *ext_enotify_runtime_get_method_capability
+(const struct sieve_runtime_env *renv, unsigned int source_line,
+	string_t *method_uri, const char *capability)
+{
+	const struct sieve_enotify_method *method;
+	const char *uri;
+	
+	/* Get method */
+	method = ext_enotify_get_method(renv, source_line, method_uri, &uri);
+	if ( method == NULL ) return NULL;
+	
+	if ( method->runtime_get_method_capability != NULL ) {
 		struct sieve_enotify_log nlog;
 		
 		memset(&nlog, 0, sizeof(nlog));
 		nlog.location = sieve_error_script_location(renv->script, source_line);
 		nlog.ehandler = sieve_interpreter_get_error_handler(renv->interp);
-		nlog.prefix = "notify action";
+		nlog.prefix = "notify_method_capability test";
 
-		if ( method->runtime_check_operands(&nlog, str_c(method_uri), uri, message, 
-			from, sieve_result_pool(renv->result), context) )
-			return method;
-		
-		return NULL;
+		return method->runtime_get_method_capability
+			(&nlog, str_c(method_uri), uri, capability);
 	}
 
-	*context = NULL;	
-	return method;
+	return NULL;
 }
 
-bool ext_enotify_runtime_method_validate
+const struct sieve_enotify_method *ext_enotify_runtime_check_operands
 (const struct sieve_runtime_env *renv, unsigned int source_line,
-	string_t *method_uri)
+	string_t *method_uri, string_t *message, string_t *from, void **context)
 {
 	const struct sieve_enotify_method *method;
-	const char *uri = str_c(method_uri);
-	const char *scheme;
+	const char *uri;
 	
-	if ( (scheme=ext_enotify_uri_scheme_parse(&uri)) == NULL )
-		return FALSE;
-	
-	if ( (method=ext_enotify_method_find(scheme)) == NULL )
-		return FALSE;
+	/* Get method */
+	method = ext_enotify_get_method(renv, source_line, method_uri, &uri);
+	if ( method == NULL ) return NULL;
 	
 	if ( method->runtime_check_operands != NULL ) {
 		struct sieve_enotify_log nlog;
@@ -259,19 +300,19 @@ bool ext_enotify_runtime_method_validate
 		memset(&nlog, 0, sizeof(nlog));
 		nlog.location = sieve_error_script_location(renv->script, source_line);
 		nlog.ehandler = sieve_interpreter_get_error_handler(renv->interp);
-		nlog.prefix = NULL;
+		nlog.prefix = "notify action";
 
-		if ( method->runtime_check_operands
-			(&nlog, str_c(method_uri), uri, NULL, NULL, NULL, NULL) )
-			return TRUE;
+		if ( method->runtime_check_operands(&nlog, str_c(method_uri), uri, message, 
+			from, sieve_result_pool(renv->result), context) )
+			return method;
 		
-		return FALSE;
+		return NULL;
 	}
 
-	return TRUE;
+	*context = NULL;	
+	return method;
 }
 
-
 /*
  * Method logging
  */
diff --git a/src/lib-sieve/plugins/enotify/ext-enotify-common.h b/src/lib-sieve/plugins/enotify/ext-enotify-common.h
index 95c2bf0aa..99012e210 100644
--- a/src/lib-sieve/plugins/enotify/ext-enotify-common.h
+++ b/src/lib-sieve/plugins/enotify/ext-enotify-common.h
@@ -77,6 +77,10 @@ bool ext_enotify_compile_check_arguments
 /*
  * Runtime
  */
+ 
+const char *ext_enotify_runtime_get_method_capability
+	(const struct sieve_runtime_env *renv, unsigned int source_line,
+		string_t *method_uri, const char *capability);
 
 const struct sieve_enotify_method *ext_enotify_runtime_check_operands
 	(const struct sieve_runtime_env *renv, unsigned int source_line,
diff --git a/src/lib-sieve/plugins/enotify/ntfy-mailto.c b/src/lib-sieve/plugins/enotify/ntfy-mailto.c
index f83732726..854cd29e4 100644
--- a/src/lib-sieve/plugins/enotify/ntfy-mailto.c
+++ b/src/lib-sieve/plugins/enotify/ntfy-mailto.c
@@ -54,10 +54,12 @@ static bool ntfy_mailto_compile_check_uri
 		const char *uri_body);
 static bool ntfy_mailto_compile_check_from
 	(const struct sieve_enotify_log *nlog, string_t *from);
+static const char *ntfy_mailto_runtime_get_notify_capability
+	(const struct sieve_enotify_log *nlog, const char *uri, const char *uri_body, 
+		const char *capability);
 static bool ntfy_mailto_runtime_check_operands
-	(const struct sieve_enotify_log *nlog, const char *uri,
-		const char *uri_body, string_t *message, string_t *from, 
-		pool_t context_pool, void **context);
+	(const struct sieve_enotify_log *nlog, const char *uri,const char *uri_body, 
+		string_t *message, string_t *from, pool_t context_pool, void **context);
 static void ntfy_mailto_action_print
 	(const struct sieve_result_print_env *rpenv, 
 		const struct sieve_enotify_action *act);	
@@ -70,6 +72,7 @@ const struct sieve_enotify_method mailto_notify = {
 	ntfy_mailto_compile_check_uri,
 	NULL,
 	ntfy_mailto_compile_check_from,
+	ntfy_mailto_runtime_get_notify_capability,
 	ntfy_mailto_runtime_check_operands,
 	ntfy_mailto_action_print,
 	ntfy_mailto_action_execute
@@ -518,6 +521,20 @@ static bool ntfy_mailto_compile_check_from
  * Runtime
  */
  
+static const char *ntfy_mailto_runtime_get_notify_capability
+(const struct sieve_enotify_log *nlog ATTR_UNUSED, const char *uri ATTR_UNUSED, 
+	const char *uri_body, const char *capability)
+{
+	if ( !ntfy_mailto_parse_uri(NULL, uri_body, NULL, NULL, NULL, NULL) ) {
+		return NULL;
+	}
+	
+	if ( strcasecmp(capability, "online") == 0 ) 
+		return "maybe";
+	
+	return NULL;
+}
+ 
 static bool ntfy_mailto_runtime_check_operands
 	(const struct sieve_enotify_log *nlog, const char *uri ATTR_UNUSED,
 		const char *uri_body, string_t *message ATTR_UNUSED, string_t *from, 
diff --git a/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h b/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h
index 8836f9854..768907bd2 100644
--- a/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h
+++ b/src/lib-sieve/plugins/enotify/sieve-ext-enotify.h
@@ -52,6 +52,9 @@ struct sieve_enotify_method {
 		(const struct sieve_enotify_log *nlog, string_t *from);
 
 	/* Runtime */
+	const char *(*runtime_get_method_capability)
+		(const struct sieve_enotify_log *nlog, const char *uri, 
+			const char *uri_body, const char *capability);
 	bool (*runtime_check_operands)
 		(const struct sieve_enotify_log *nlog, const char *uri, 
 			const char *uri_body, string_t *message, string_t *from, 
diff --git a/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c b/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c
index ac331f55b..fd643e50d 100644
--- a/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c
+++ b/src/lib-sieve/plugins/enotify/tst-notify-method-capability.c
@@ -184,6 +184,7 @@ static int tst_notifymc_operation_execute
 	struct sieve_match_context *mctx;
 	string_t *notify_uri, *notify_capability;
 	struct sieve_coded_stringlist *key_list;
+	const char *cap_value;
 	bool matched;
 
 	/*
@@ -225,28 +226,22 @@ static int tst_notifymc_operation_execute
 
 	sieve_runtime_trace(renv, "NOTIFY_METHOD_CAPABILITY test");
 
-	/*mctx = sieve_match_begin(renv->interp, mtch, cmp, NULL, key_list); 	
+	cap_value = ext_enotify_runtime_get_method_capability
+		(renv, 0 /* FIXME */, notify_uri, str_c(notify_capability));
 
-	/* Iterate through all requested strings to match * /
-	matched = FALSE;
-	while ( result && !matched && 
-		(result=sieve_coded_stringlist_next_item(source, &src_item)) 
-		&& src_item != NULL ) {
-		const char *src = str_len(src_item) > 0 ? str_c(src_item) : NULL;
+	if ( cap_value != NULL ) {
+		mctx = sieve_match_begin(renv->interp, mtch, cmp, NULL, key_list); 	
 
-		if ( (mret=sieve_match_value
-			(mctx, src, str_len(src_item))) < 0 ) {
+		if ( (mret=sieve_match_value(mctx, cap_value, strlen(cap_value))) < 0 )
 			result = FALSE;
-			break;
-		}
-		
-		matched = ( mret > 0 );				
-	}
+		matched = ( mret > 0 );		
 
-	if ( (mret=sieve_match_end(mctx)) < 0 ) 
-		result = FALSE;
-	else
-		matched = ( mret > 0 || matched ); 	
+		if ( (mret=sieve_match_end(mctx)) < 0 ) 
+			result = FALSE;
+		matched = ( mret > 0 ) || matched;		
+	} else {
+		matched = FALSE;
+	}
 	
 	if ( result ) {
 		sieve_interpreter_set_test_result(renv->interp, matched);
@@ -254,7 +249,5 @@ static int tst_notifymc_operation_execute
 	}
 	
 	sieve_runtime_trace_error(renv, "invalid string list item");
-	return SIEVE_EXEC_BIN_CORRUPT;*/
-	
-	return SIEVE_EXEC_OK;
+	return SIEVE_EXEC_BIN_CORRUPT;
 }
diff --git a/tests/extensions/enotify/notify_method_capability.svtest b/tests/extensions/enotify/notify_method_capability.svtest
new file mode 100644
index 000000000..9cdb2bef0
--- /dev/null
+++ b/tests/extensions/enotify/notify_method_capability.svtest
@@ -0,0 +1,12 @@
+require "vnd.dovecot.testsuite";
+require "enotify";
+
+test "Mailto" {
+	if not notify_method_capability :is "mailto:stephan@rename-it.nl" "online" "maybe" {
+		test_fail "test should have matched";
+	}
+
+	if notify_method_capability :is "mailto:stephan@rename-it.nl" "online" "yes" {
+		test_fail "test should not have matched";
+	}
+}
diff --git a/tests/extensions/enotify/valid-notify-method.svtest b/tests/extensions/enotify/valid_notify_method.svtest
similarity index 77%
rename from tests/extensions/enotify/valid-notify-method.svtest
rename to tests/extensions/enotify/valid_notify_method.svtest
index 6ad92495d..505442fcc 100644
--- a/tests/extensions/enotify/valid-notify-method.svtest
+++ b/tests/extensions/enotify/valid_notify_method.svtest
@@ -2,28 +2,28 @@ require "vnd.dovecot.testsuite";
 
 require "enotify";
 
-test "Invalid header name" {
+test "Mailto: invalid header name" {
 	if valid_notify_method 
 		"mailto:stephan@rename-it.nl?header:=frop" {
 		test_fail "invalid uri accepted";
 	}
 }
 
-test "Invalid recipient" {
+test "Mailto: invalid recipient" {
 	if valid_notify_method 
 		"mailto:stephan%23rename-it.nl" {
 		test_fail "invalid uri accepted";
 	}
 }
 
-test "Invalid to header recipient" {
+test "Mailto: invalid to header recipient" {
 	if valid_notify_method
 		"mailto:stephan@rename-it.nl?to=nico%23vestingbar.nl" {
 		test_fail "invalid uri accepted";
 	}
 }
 
-test "Valid URI" {
+test "Mailto: valid URI" {
 	if not valid_notify_method
 		"mailto:stephan@rename-it.nl" {
 		test_fail "valid uri denied";
-- 
GitLab