From: Stephan Bosch Date: Sun, 29 Oct 2017 22:37:47 +0000 (+0100) Subject: lib-smtp: address: Created SMTP address detail parsing function from message_detail_a... X-Git-Tag: 2.3.0.rc1~376 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=61ae3dd363d32db75d2c3effaab4ba093ce0f245;p=thirdparty%2Fdovecot%2Fcore.git lib-smtp: address: Created SMTP address detail parsing function from message_detail_address_parse(). --- diff --git a/src/lib-smtp/smtp-address.c b/src/lib-smtp/smtp-address.c index d29eb2649f..77342082ef 100644 --- a/src/lib-smtp/smtp-address.c +++ b/src/lib-smtp/smtp-address.c @@ -309,6 +309,9 @@ int smtp_address_parse_mailbox(pool_t pool, if (error_r != NULL) *error_r = NULL; + if (error_r != NULL) + *error_r = NULL; + if ((mailbox == NULL || *mailbox == '\0')) { if ((flags & SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY) == 0) { if (error_r != NULL) @@ -438,6 +441,55 @@ int smtp_address_parse_username(pool_t pool, const char *username, return 1; } +void smtp_address_detail_parse(pool_t pool, const char *delimiters, + struct smtp_address *address, const char **username_r, + char *delim_r, const char **detail_r) +{ + const char *localpart = address->localpart; + const char *user, *p; + size_t idx; + + user = localpart; + *detail_r = ""; + *delim_r = '\0'; + + /* first character that matches the recipient_delimiter */ + idx = strcspn(localpart, delimiters); + p = (localpart[idx] != '\0' ? &localpart[idx] : NULL); + + if (p != NULL) { + *delim_r = *p; + /* user+detail */ + user = p_strdup_until(pool, localpart, p); + *detail_r = p+1; + } + + if (address->domain == NULL) + *username_r = user; + else if (strchr(user, '@') == NULL ) { + /* username is just glued to the domain... no SMTP escaping */ + *username_r = p_strconcat(pool, + user, "@", address->domain, NULL); + } else { + struct smtp_address uaddr; + + /* username contains '@'; apply escaping */ + smtp_address_init(&uaddr, user, address->domain); + if (pool->datastack_pool) + *username_r = smtp_address_encode(&uaddr); + else + *username_r = p_strdup(pool, smtp_address_encode(&uaddr)); + } +} + +void smtp_address_detail_parse_temp(const char *delimiters, + struct smtp_address *address, const char **username_r, + char *delim_r, const char **detail_r) +{ + smtp_address_detail_parse(pool_datastack_create(), delimiters, + address, username_r, delim_r, detail_r); +} + /* * SMTP address construction */ diff --git a/src/lib-smtp/smtp-address.h b/src/lib-smtp/smtp-address.h index 01b499ad06..18703d86a3 100644 --- a/src/lib-smtp/smtp-address.h +++ b/src/lib-smtp/smtp-address.h @@ -48,6 +48,15 @@ int smtp_address_parse_username(pool_t pool, const char *username, struct smtp_address **address_r, const char **error_r) ATTR_NULL(3, 4); +/* Parse address+detail@domain into address@domain and detail + using given delimiters. Returns used delimiter. */ +void smtp_address_detail_parse(pool_t poo, const char *delimiters, + struct smtp_address *address, const char **username_r, + char *delim_r, const char **detail_r); +void smtp_address_detail_parse_temp(const char *delimiters, + struct smtp_address *address, const char **username_r, + char *delim_r, const char **detail_r); + /* * SMTP address construction */ diff --git a/src/lib-smtp/test-smtp-address.c b/src/lib-smtp/test-smtp-address.c index c0a22bd596..2ae59deed7 100644 --- a/src/lib-smtp/test-smtp-address.c +++ b/src/lib-smtp/test-smtp-address.c @@ -732,6 +732,76 @@ static void test_smtp_username_parse_invalid(void) } T_END; } +/* + * Address detail parsing + */ + +struct address_detail_parse_test { + const char *delimiters; + const char *address; + const char *username; + const char *detail; + char delim; +}; + +static const struct address_detail_parse_test +address_detail_parse_tests[] = { + { "", "test", "test", "", '\0' }, + { "", "test+address", "test+address", "", '\0' }, + { "", "\"test:address\"", "test:address", "", '\0' }, + { "", "\"test-address:another+delim\"", "test-address:another+delim", "", '\0' }, + { "", "test@domain", "test@domain", "", '\0' }, + { "", "test+address@domain", "test+address@domain", "", '\0' }, + { "", "\"test:address\"@domain", "test:address@domain", "", '\0' }, + { "", "\"test-address:another+delim\"@domain", "test-address:another+delim@domain", "", '\0' }, + + { "+-:", "test", "test", "", '\0' }, + { "+-:", "test+address", "test", "address", '+' }, + { "+-:", "\"test:address\"", "test", "address", ':' }, + { "+-:", "\"test-address:another+delim\"", "test", "address:another+delim", '-' }, + { "+-:", "test@domain", "test@domain", "", '\0' }, + { "+-:", "test+address@domain", "test@domain", "address", '+' }, + { "+-:", "\"test:address\"@domain", "test@domain", "address", ':' }, + { "+-:", "\"test-address:another+delim\"@domain", "test@domain", "address:another+delim", '-' } +}; + +unsigned int addresss_detail_parse_test_count = + N_ELEMENTS(address_detail_parse_tests); + +static void test_smtp_address_detail_parse(void) +{ + unsigned int i; + + + for (i = 0; i < N_ELEMENTS(address_detail_parse_tests); i++) T_BEGIN { + const struct address_detail_parse_test *test = + &address_detail_parse_tests[i]; + struct smtp_address *address; + const char *username, *detail, *error; + char delim; + int ret; + + test_begin(t_strdup_printf( + "smtp address detail parsing [%d]", i)); + + ret = smtp_address_parse_path(pool_datastack_create(), test->address, + SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART | + SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL, + &address, &error); + test_out_reason("address parse", ret > 0, error); + + if (!test_has_failed()) { + smtp_address_detail_parse_temp(test->delimiters, address, + &username, &delim, &detail); + test_assert(strcmp(username, test->username) == 0); + test_assert(strcmp(detail, test->detail) == 0); + test_assert(delim == test->delim); + } + + test_end(); + } T_END; +} + /* * Tests */ @@ -745,6 +815,7 @@ int main(void) test_smtp_mailbox_parse_invalid, test_smtp_path_parse_invalid, test_smtp_username_parse_invalid, + test_smtp_address_detail_parse, NULL }; return test_run(test_functions);