return ctx.first_addr;
}
+static int
+message_address_parse_path_real(pool_t pool, const unsigned char *data,
+ size_t size, struct message_address **addr_r)
+{
+ struct message_address_parser_context ctx;
+ int ret;
+
+ i_zero(&ctx);
+ *addr_r = NULL;
+
+ rfc822_parser_init(&ctx.parser, data, size, NULL);
+ ctx.pool = pool;
+ ctx.str = t_str_new(128);
+
+ if (rfc822_skip_lwsp(&ctx.parser) <= 0)
+ return -1;
+ if ((ret=parse_angle_addr(&ctx)) < 0 ||
+ (ctx.addr.mailbox != NULL && ctx.addr.domain == NULL)) {
+ ctx.addr.invalid_syntax = TRUE;
+ ret = -1;
+ }
+ add_address(&ctx);
+ *addr_r = ctx.first_addr;
+ return (ret < 0 ? -1 : 0);
+}
+
struct message_address *
message_address_parse(pool_t pool, const unsigned char *data, size_t size,
unsigned int max_addresses, bool fill_missing)
return addr;
}
+int message_address_parse_path(pool_t pool, const unsigned char *data,
+ size_t size, struct message_address **addr_r)
+{
+ int ret;
+
+ if (pool->datastack_pool) {
+ return message_address_parse_path_real(pool, data, size, addr_r);
+ }
+ T_BEGIN {
+ ret = message_address_parse_path_real(pool, data, size, addr_r);
+ } T_END;
+ return ret;
+}
+
void message_address_write(string_t *str, const struct message_address *addr)
{
const char *tmp;
if (addr == NULL)
return;
+ /* <> path */
+ if (addr->mailbox == NULL && addr->domain == NULL) {
+ i_assert(addr->next == NULL);
+ str_append(str, "<>");
+ return;
+ }
+
/* a) mailbox@domain
b) name <@route:mailbox@domain>
c) group: .. ; */
test_end();
}
+static int
+test_parse_path(const char *input, const struct message_address **addr_r)
+{
+ struct message_address *addr;
+ int ret;
+
+ /* duplicate the input (without trailing NUL) so valgrind notices
+ if there's any out-of-bounds access */
+ size_t input_len = strlen(input);
+ unsigned char *input_dup = i_malloc(input_len);
+ memcpy(input_dup, input, input_len);
+ ret = message_address_parse_path(pool_datastack_create(),
+ input_dup, input_len, &addr);
+ i_free(input_dup);
+ *addr_r = addr;
+ return ret;
+}
+
+static void test_message_address_path(void)
+{
+ static const struct test {
+ const char *input;
+ const char *wanted_output;
+ struct message_address addr;
+ } tests[] = {
+ { "<>", NULL,
+ { NULL, NULL, NULL, NULL, NULL, FALSE } },
+ { " < > ", "<>",
+ { NULL, NULL, NULL, NULL, NULL, FALSE } },
+ { "<user@domain>", NULL,
+ { NULL, NULL, NULL, "user", "domain", FALSE } },
+ { " <user@domain> ", "<user@domain>",
+ { NULL, NULL, NULL, "user", "domain", FALSE } },
+ { "<\"user\"@domain>", "<user@domain>",
+ { NULL, NULL, NULL, "user", "domain", FALSE } },
+ { "<\"user name\"@domain>", NULL,
+ { NULL, NULL, NULL, "user name", "domain", FALSE } },
+ { "<\"user@na\\\\me\"@domain>", NULL,
+ { NULL, NULL, NULL, "user@na\\me", "domain", FALSE } },
+ { "<\"user\\\"name\"@domain>", NULL,
+ { NULL, NULL, NULL, "user\"name", "domain", FALSE } },
+ { "<\"\"@domain>", NULL,
+ { NULL, NULL, NULL, "", "domain", FALSE } },
+ };
+ const struct message_address *addr;
+ string_t *str;
+ const char *wanted_string;
+ unsigned int i;
+
+ test_begin("message address path parsing");
+ str = t_str_new(128);
+
+ for (i = 0; i < N_ELEMENTS(tests); i++) {
+ const struct test *test = &tests[i];
+ const struct message_address *test_wanted_addr;
+ int ret;
+
+ test_wanted_addr = &test->addr;
+ ret = test_parse_path(test->input, &addr);
+ test_assert_idx(ret == 0, i);
+ test_assert_idx(addr != NULL && addr->next == NULL &&
+ cmp_addr(addr, test_wanted_addr), i);
+
+ /* test the address alone */
+ str_truncate(str, 0);
+ message_address_write(str, addr);
+ if (test->wanted_output != NULL)
+ wanted_string = test->wanted_output;
+ else
+ wanted_string = test->input;
+ test_assert_idx(strcmp(str_c(str), wanted_string) == 0, i);
+ }
+ test_end();
+}
+
int main(void)
{
static void (*const test_functions[])(void) = {
test_message_address,
+ test_message_address_path,
NULL
};
return test_run(test_functions);