From dd6875f5cda6343733a27f1d41dd3d41d6098156 Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Wed, 26 Sep 2012 21:51:46 +0200
Subject: [PATCH] lib-sieve: date extension: Generate warning when invalid date
 part is specified.

---
 src/lib-sieve/plugins/date/ext-date-common.c | 23 +++++++++------
 src/lib-sieve/plugins/date/ext-date-common.h |  6 ++--
 src/lib-sieve/plugins/date/tst-date.c        | 30 ++++++++++++++++----
 3 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/src/lib-sieve/plugins/date/ext-date-common.c b/src/lib-sieve/plugins/date/ext-date-common.c
index 936b24c53..ff3fa1290 100644
--- a/src/lib-sieve/plugins/date/ext-date-common.c
+++ b/src/lib-sieve/plugins/date/ext-date-common.c
@@ -282,23 +282,28 @@ static const struct ext_date_part *date_parts[] = {
 
 unsigned int date_parts_count = N_ELEMENTS(date_parts);
 
-const char *ext_date_part_extract
-(const char *part, struct tm *tm, int zone_offset)
+const struct ext_date_part *ext_date_part_find(const char *part)
 {
 	unsigned int i;
 
 	for ( i = 0; i < date_parts_count; i++ ) {
 		if ( strcasecmp(date_parts[i]->identifier, part) == 0 ) {
-			if ( date_parts[i]->get_string != NULL )
-				return date_parts[i]->get_string(tm, zone_offset);
-
-			return NULL;
+			return date_parts[i];
 		}
 	}
 
 	return NULL;
 }
 
+const char *ext_date_part_extract
+(const struct ext_date_part *dpart, struct tm *tm, int zone_offset)
+{
+	if ( dpart == NULL || dpart->get_string == NULL )
+		return NULL;
+
+	return dpart->get_string(tm, zone_offset);
+}
+
 /*
  * Date part implementations
  */
@@ -486,7 +491,7 @@ struct ext_date_stringlist {
 
 	struct sieve_stringlist *field_values;
 	int time_zone;
-	const char *date_part;
+	const struct ext_date_part *date_part;
 
 	time_t local_time;
 	int local_zone;
@@ -496,7 +501,7 @@ struct ext_date_stringlist {
 
 struct sieve_stringlist *ext_date_stringlist_create
 (const struct sieve_runtime_env *renv, struct sieve_stringlist *field_values,
-	int time_zone, const char *date_part)
+	int time_zone, const struct ext_date_part *dpart)
 {
 	struct ext_date_stringlist *strlist;
 
@@ -507,7 +512,7 @@ struct sieve_stringlist *ext_date_stringlist_create
 	strlist->strlist.reset = ext_date_stringlist_reset;
 	strlist->field_values = field_values;
 	strlist->time_zone = time_zone;
-	strlist->date_part = date_part;
+	strlist->date_part = dpart;
 
 	strlist->local_time = ext_date_get_current_date(renv, &strlist->local_zone);
 
diff --git a/src/lib-sieve/plugins/date/ext-date-common.h b/src/lib-sieve/plugins/date/ext-date-common.h
index 918d9f57c..a0a6dd352 100644
--- a/src/lib-sieve/plugins/date/ext-date-common.h
+++ b/src/lib-sieve/plugins/date/ext-date-common.h
@@ -60,8 +60,10 @@ struct ext_date_part {
 	const char *(*get_string)(struct tm *tm, int zone_offset);
 };
 
+const struct ext_date_part *ext_date_part_find(const char *part);
+
 const char *ext_date_part_extract
-	(const char *part, struct tm *tm, int zone_offset);
+	(const struct ext_date_part *dpart, struct tm *tm, int zone_offset);
 
 /*
  * Date stringlist
@@ -74,7 +76,7 @@ enum ext_date_timezone_special {
 
 struct sieve_stringlist *ext_date_stringlist_create
 (const struct sieve_runtime_env *renv, struct sieve_stringlist *field_values,
-	int time_zone, const char *date_part);
+	int time_zone, const struct ext_date_part *dpart);
 
 
 
diff --git a/src/lib-sieve/plugins/date/tst-date.c b/src/lib-sieve/plugins/date/tst-date.c
index d84581276..981ba943f 100644
--- a/src/lib-sieve/plugins/date/tst-date.c
+++ b/src/lib-sieve/plugins/date/tst-date.c
@@ -260,7 +260,7 @@ static bool tst_date_validate
 			return FALSE;
 
 		if ( !sieve_command_verify_headers_argument(valdtr, arg) )
-    	    return FALSE;
+			return FALSE;
 
 		arg = sieve_ast_argument_next(arg);
 	}
@@ -275,6 +275,16 @@ static bool tst_date_validate
 	if ( !sieve_validator_argument_activate(valdtr, tst, arg, FALSE) )
 		return FALSE;
 
+	if ( sieve_argument_is_string_literal(arg) ) {
+		const char * part = sieve_ast_argument_strc(arg);
+
+		if ( ext_date_part_find(part) == NULL ) {
+			sieve_argument_validate_warning
+				(valdtr, arg, "specified date part `%s' is not known",
+					str_sanitize(part, 80));
+		}
+	}
+
 	arg = sieve_ast_argument_next(arg);
 
 	/* Check key list */
@@ -349,7 +359,7 @@ static bool tst_date_operation_dump
 			if ( !sieve_opr_string_dump_ex(denv, address, "zone", "ORIGINAL") )
 				return FALSE;
 			break;
-    default:
+		default:
 			return FALSE;
 		}
 	}
@@ -381,6 +391,7 @@ static int tst_date_operation_execute
 	struct sieve_stringlist *hdr_list = NULL, *hdr_value_list;
 	struct sieve_stringlist *value_list, *key_list;
 	bool zone_specified = FALSE, zone_literal = TRUE;
+	const struct ext_date_part *dpart;
 	int time_zone;
 	int match, ret;
 
@@ -433,11 +444,19 @@ static int tst_date_operation_execute
 	} else if ( !ext_date_parse_timezone(str_c(zone), &time_zone) ) {
 		if ( !zone_literal )
 			sieve_runtime_warning(renv, NULL,
-				"specified :zone argument '%s' is not a valid timezone "
+				"specified :zone argument `%s' is not a valid timezone "
 				"(using local zone)", str_sanitize(str_c(zone), 40));
 		time_zone = EXT_DATE_TIMEZONE_LOCAL;
 	}
 
+	if ( (dpart=ext_date_part_find(str_c(date_part))) == NULL ) {
+		sieve_runtime_warning(renv, NULL,
+			"specified date part argument `%s' is not known",
+			str_sanitize(str_c(date_part), 40));
+		sieve_interpreter_set_test_result(renv->interp, FALSE);
+		return SIEVE_EXEC_OK;
+	}
+
 	/*
 	 * Perform test
 	 */
@@ -449,7 +468,7 @@ static int tst_date_operation_execute
 		/* Create value stringlist */
 		hdr_value_list = sieve_message_header_stringlist_create(renv, hdr_list, FALSE);
 		value_list = ext_date_stringlist_create
-			(renv, hdr_value_list, time_zone, str_c(date_part));
+			(renv, hdr_value_list, time_zone, dpart);
 
 	} else if ( sieve_operation_is(op, currentdate_operation) ) {
 		/* Use time stamp recorded at the time the script first started */
@@ -457,8 +476,7 @@ static int tst_date_operation_execute
 		sieve_runtime_trace(renv, SIEVE_TRLVL_TESTS, "currentdatedate test");
 
 		/* Create value stringlist */
-		value_list = ext_date_stringlist_create
-			(renv, NULL, time_zone, str_c(date_part));
+		value_list = ext_date_stringlist_create(renv, NULL, time_zone, dpart);
 	} else {
 		i_unreached();
 	}
-- 
GitLab