From 7175f000f0c8336b1f555891396594a04c7ffa6d Mon Sep 17 00:00:00 2001
From: Aaron Lindsay <aaron@aclindsay.com>
Date: Tue, 22 Mar 2016 10:13:19 -0400
Subject: [PATCH] subaddress: Support multiple recipient_delimiters

The recipient_delimiter is treated as multiple one-character delimiters
rather than one multi-character delimiter if more than one character is
supplied.

Based on a patch by: Lennart Weller <lhw@ring0.de>
---
 src/lib-sieve/plugins/subaddress/ext-subaddress.c | 14 +++++----
 tests/extensions/subaddress/config.svtest         | 38 ++++++++++++++---------
 2 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/src/lib-sieve/plugins/subaddress/ext-subaddress.c b/src/lib-sieve/plugins/subaddress/ext-subaddress.c
index c0e4a1a..656c4cc 100644
--- a/src/lib-sieve/plugins/subaddress/ext-subaddress.c
+++ b/src/lib-sieve/plugins/subaddress/ext-subaddress.c
@@ -143,8 +143,10 @@ static const char *subaddress_user_extract_from
 	struct ext_subaddress_config *config =
 		(struct ext_subaddress_config *) addrp->object.ext->context;
 	const char *delim;
+	size_t idx;
 
-	delim = strstr(address->local_part, config->delimiter);
+	idx = strcspn(address->local_part, config->delimiter);
+	delim = address->local_part[idx] != '\0' ? address->local_part + idx : NULL;
 
 	if ( delim == NULL ) return address->local_part;
 
@@ -157,14 +159,14 @@ static const char *subaddress_detail_extract_from
 	struct ext_subaddress_config *config =
 		(struct ext_subaddress_config *) addrp->object.ext->context;
 	const char *delim;
+	size_t idx;
 
-	if ( (delim=strstr(address->local_part, config->delimiter)) == NULL )
-		return NULL;
-
-	delim += strlen(config->delimiter);
+	idx = strcspn(address->local_part, config->delimiter);
+	delim = address->local_part[idx] != '\0' ? address->local_part + idx + 1: NULL;
 
 	/* Just to be sure */
-	if ( delim > (address->local_part + strlen(address->local_part)) )
+	if ( delim == NULL ||
+			delim > (address->local_part + strlen(address->local_part)) )
 		return NULL;
 
 	return delim;
diff --git a/tests/extensions/subaddress/config.svtest b/tests/extensions/subaddress/config.svtest
index ed833c3..071aa12 100644
--- a/tests/extensions/subaddress/config.svtest
+++ b/tests/extensions/subaddress/config.svtest
@@ -11,8 +11,8 @@ Test!
 .
 ;
 
-test_set "envelope.to" "friep++frop@dovecot.example.net";
-test_set "envelope.from" "list--request@lists.dovecot.example.net";
+test_set "envelope.to" "friep+-frop@dovecot.example.net";
+test_set "envelope.from" "list_request@lists.dovecot.example.net";
 
 test "Delimiter default" {
 	if not address :is :user "from" "stephan" {
@@ -37,41 +37,49 @@ test "Delimiter \"-\"" {
 	}
 }
 
-test "Delimiter \"++\"" {
-	test_config_set "recipient_delimiter" "++";
+test "Delimiter \"+-\"" {
+	test_config_set "recipient_delimiter" "+-";
 	test_config_reload :extension "subaddress";
 
 	if not envelope :is :user "to" "friep" {
 		test_fail "wrong user part extracted";
 	}
 
-	if not envelope :is :detail "to" "frop" {
+	if not envelope :is :detail "to" "-frop" {
 		test_fail "wrong detail part extracted";
 	}
 }
 
-test "Delimiter \"--\"" {
-	test_config_set "recipient_delimiter" "--";
+test "Delimiter \"-+\"" {
+	test_config_set "recipient_delimiter" "-+";
 	test_config_reload :extension "subaddress";
 
-	if not envelope :is :user "from" "list" {
+	if not envelope :is :user "to" "friep" {
 		test_fail "wrong user part extracted";
 	}
 
-	if not envelope :is :detail "from" "request" {
+	if not envelope :is :detail "to" "-frop" {
 		test_fail "wrong detail part extracted";
 	}
 }
 
-test "Delimiter \"+-\"" {
-	test_config_set "recipient_delimiter" "+-";
+test "Delimiter \"+-_\"" {
+	test_config_set "recipient_delimiter" "+-_";
 	test_config_reload :extension "subaddress";
 
-	if envelope :is :user "from" "list" {
-		test_fail "user part extracted";
+	if not envelope :is :user "to" "friep" {
+		test_fail "wrong user part extracted";
+	}
+
+	if not envelope :is :detail "to" "-frop" {
+		test_fail "wrong detail part extracted";
 	}
 
-	if envelope :is :detail "from" "request" {
-		test_fail "detail part extracted";
+	if not envelope :is :user "from" "list" {
+		test_fail "wrong user part extracted";
+	}
+
+	if not envelope :is :detail "from" "request" {
+		test_fail "wrong detail part extracted";
 	}
 }
-- 
2.7.4

