Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-mail/message-address.c @ 956:26cafa3dc09c HEAD
minor optimization
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 12 Jan 2003 01:49:45 +0200 |
parents | fd8888f6f037 |
children | 8028c4dcf38f |
line wrap: on
line source
/* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" #include "str.h" #include "message-tokenize.h" #include "message-address.h" static struct message_address * new_address(pool_t pool, struct message_address ***next_addr) { struct message_address *addr; addr = p_new(pool, struct message_address, 1); **next_addr = addr; *next_addr = &addr->next; return addr; } struct message_address * message_address_parse(pool_t pool, const unsigned char *data, size_t size) { static const enum message_token stop_tokens_init[] = { ',', '@', '<', ':', TOKEN_LAST }; static const enum message_token stop_tokens_group[] = { ',', '@', '<', ';', TOKEN_LAST }; static const enum message_token stop_tokens_domain[] = { ',', '<', TOKEN_LAST }; static const enum message_token stop_tokens_domain_group[] = { ',', '<', ';', TOKEN_LAST }; static const enum message_token stop_tokens_post_addr[] = { ',', TOKEN_LAST }; static const enum message_token stop_tokens_post_addr_group[] = { ',', ';', TOKEN_LAST }; static const enum message_token stop_tokens_addr_route[] = { ':', '>', TOKEN_LAST }; static const enum message_token stop_tokens_addr_mailbox[] = { '@', '>', TOKEN_LAST }; static const enum message_token stop_tokens_addr_domain[] = { '>', TOKEN_LAST }; struct message_address *first_addr, **next_addr, *addr; struct message_tokenizer *tok; const enum message_token *stop_tokens; enum message_token token; string_t *mailbox, *domain, *route, *name, *comment, *next_phrase; size_t len; int ingroup, stop; if (size == 0) return NULL; first_addr = NULL; next_addr = &first_addr; /* 1) name <@route:mailbox@domain>, ... 2) mailbox@domain (name), ... 3) group: name <box@domain>, box2@domain2 (name2), ... ;, ... ENVELOPE wants groups to be stored like (NIL, NIL, group, NIL), ..., (NIL, NIL, NIL, NIL) */ tok = message_tokenize_init(data, size, NULL, NULL); message_tokenize_skip_comments(tok, FALSE); t_push(); mailbox = t_str_new(128); domain = t_str_new(256); route = t_str_new(128); name = t_str_new(256); comment = t_str_new(256); ingroup = FALSE; len = 0; stop_tokens = stop_tokens_init; next_phrase = mailbox; stop = FALSE; while (!stop) { if (next_phrase == name && str_len(name) > 0) { /* continuing previously started name, separate it from us with space */ str_append_c(name, ' '); len = str_len(name); } else { len = 0; } message_tokenize_get_string(tok, next_phrase, comment, stop_tokens); if (next_phrase == name && len > 0 && len == str_len(name)) { /* nothing appeneded, remove the space */ str_truncate(name, len-1); } token = message_tokenize_get(tok); switch (token) { case TOKEN_LAST: case ',': case ';': /* end of address */ if (str_len(mailbox) > 0 || str_len(domain) > 0 || str_len(route) > 0 || str_len(name) > 0) { addr = new_address(pool, &next_addr); addr->mailbox = p_strdup(pool, str_c(mailbox)); addr->domain = str_len(domain) == 0 ? NULL : p_strdup(pool, str_c(domain)); addr->route = str_len(route) == 0 ? NULL : p_strdup(pool, str_c(route)); addr->name = next_phrase == name ? p_strdup(pool, str_c(name)) : p_strdup(pool, str_c(comment)); } if (ingroup && token == ';') { /* end of group - add end of group marker */ ingroup = FALSE; (void)new_address(pool, &next_addr); } if (token == TOKEN_LAST) { stop = TRUE; break; } stop_tokens = ingroup ? stop_tokens_group : stop_tokens_init; str_truncate(mailbox, 0); str_truncate(domain, 0); str_truncate(route, 0); str_truncate(name, 0); str_truncate(comment, 0); next_phrase = mailbox; break; case '@': /* domain part comes next */ next_phrase = domain; stop_tokens = ingroup ? stop_tokens_domain_group : stop_tokens_domain; break; case '<': /* route-addr */ /* mailbox/domain name so far has actually been the real name */ str_append_str(name, mailbox); str_truncate(mailbox, 0); if (str_len(domain) > 0) { str_append_c(name, '@'); str_append_str(name, domain); str_truncate(domain, 0); } /* mailbox */ message_tokenize_get_string(tok, mailbox, NULL, stop_tokens_addr_mailbox); if (message_tokenize_get(tok) == '@' && str_len(mailbox) == 0) { /* route is given */ message_tokenize_get_string(tok, route, NULL, stop_tokens_addr_route); if (message_tokenize_get(tok) == ':') { /* mailbox comes next */ message_tokenize_get_string(tok, mailbox, NULL, stop_tokens_addr_mailbox); } } if (message_tokenize_get(tok) == '@') { /* domain */ message_tokenize_get_string(tok, domain, NULL, stop_tokens_addr_domain); } token = message_tokenize_get(tok); i_assert(token == '>' || token == TOKEN_LAST); next_phrase = name; stop_tokens = ingroup ? stop_tokens_post_addr_group : stop_tokens_post_addr; break; case ':': /* beginning of group */ addr = new_address(pool, &next_addr); addr->name = p_strdup(pool, str_c(mailbox)); str_truncate(mailbox, 0); str_truncate(comment, 0); ingroup = TRUE; stop_tokens = stop_tokens_group; break; default: i_unreached(); break; } } if (ingroup) (void)new_address(pool, &next_addr); t_pop(); message_tokenize_deinit(tok); return first_addr; }