Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-mail/rfc822-address.c @ 91:dc0891523276 HEAD
bugfix for sync fix
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 29 Aug 2002 01:42:00 +0300 |
parents | 3b1985cbc908 |
children | d6105a8a6ca9 |
line wrap: on
line source
/* Copyright (C) 2002 Timo Sirainen */ #include "lib.h" #include "temp-string.h" #include "rfc822-tokenize.h" #include "rfc822-address.h" static Rfc822Address *new_address(Pool pool, Rfc822Address ***next_addr) { Rfc822Address *addr; addr = p_new(pool, Rfc822Address, 1); **next_addr = addr; *next_addr = &addr->next; return addr; } static int read_until(const Rfc822Token *tokens, const char *stop_tokens, TempString *comment) { int i, pos; /* find the stop token */ for (i = 0; tokens[i].token != 0; i++) { if (strchr(stop_tokens, tokens[i].token) != NULL) break; if (tokens[i].token == '(') { /* save comment */ if (comment->len > 0) t_string_append_c(comment, ' '); pos = comment->len; t_string_append_n(comment, tokens[i].ptr, tokens[i].len); string_remove_escapes(comment->str + pos); comment->len = strlen(comment->str); } } return i; } static void read_until_get(const Rfc822Token **tokens, const char *stop_tokens, TempString *phrase, TempString *comment) { const char *value; int count; count = read_until(*tokens, stop_tokens, comment); if (count > 0) { value = rfc822_tokens_get_value(*tokens, count, FALSE); t_string_append(phrase, value); *tokens += count; } } Rfc822Address *rfc822_address_parse(Pool pool, const char *str) { Rfc822Address *first_addr, **next_addr, *addr; TempString *mailbox, *domain, *route, *name, *comment, *next_phrase; const Rfc822Token *tokens; const char *list, *value; int ingroup, stop, count, spaces; if (str == NULL || *str == '\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) */ tokens = rfc822_tokenize(str, NULL, NULL, NULL); t_push(); mailbox = t_string_new(128); domain = t_string_new(128); route = t_string_new(128); name = t_string_new(128); comment = t_string_new(128); ingroup = FALSE; list = ",@<:"; next_phrase = mailbox; stop = FALSE; while (!stop) { count = read_until(tokens, list, comment); if (count > 0) { /* put spaces around tokens if we're parsing name */ spaces = tokens[count].token == '<' || next_phrase == name; if (spaces && next_phrase->len > 0) t_string_append_c(next_phrase, ' '); value = rfc822_tokens_get_value(tokens, count, spaces); t_string_append(next_phrase, value); tokens += count; } switch (tokens->token) { case 0: case ',': case ';': /* end of address */ if (mailbox->len > 0 || domain->len > 0 || route->len > 0 || name->len > 0) { addr = new_address(pool, &next_addr); addr->mailbox = p_strdup(pool, mailbox->str); addr->domain = domain->len == 0 ? NULL : p_strdup(pool, domain->str); addr->route = route->len == 0 ? NULL : p_strdup(pool, route->str); addr->name = next_phrase == name ? p_strdup(pool, name->str) : p_strdup(pool, comment->str); } if (ingroup && tokens->token == ';') { /* end of group - add end of group marker */ ingroup = FALSE; (void)new_address(pool, &next_addr); } if (tokens->token == 0) { stop = TRUE; break; } list = ingroup ? ",@<;" : ",@<:"; t_string_truncate(mailbox, 0); t_string_truncate(domain, 0); t_string_truncate(route, 0); t_string_truncate(name, 0); t_string_truncate(comment, 0); tokens++; next_phrase = mailbox; break; case '@': /* domain part comes next */ tokens++; next_phrase = domain; list = ingroup ? ",<;" : ",<"; break; case '<': /* route-addr */ tokens++; /* mailbox/domain name so far has actually been the real name */ t_string_append(name, mailbox->str); if (domain->len > 0) { t_string_append_c(name, '@'); t_string_append(name, domain->str); } t_string_truncate(mailbox, 0); t_string_truncate(domain, 0); read_until_get(&tokens, "@>", mailbox, NULL); if (tokens->token == '@' && mailbox->len == 0) { /* route is given */ tokens++; read_until_get(&tokens, ":>", route, NULL); if (tokens->token == ':') { /* mailbox comes next */ tokens++; read_until_get(&tokens, "@>", mailbox, NULL); } } if (tokens->token == '@') { tokens++; read_until_get(&tokens, ">", domain, NULL); } if (tokens->token == '>') tokens++; next_phrase = name; list = ingroup ? ",;" : ","; break; case ':': /* beginning of group */ addr = new_address(pool, &next_addr); addr->name = p_strdup(pool, mailbox->str); t_string_truncate(mailbox, 0); tokens++; ingroup = TRUE; list = ",@<;"; break; } } if (ingroup) (void)new_address(pool, &next_addr); t_pop(); return first_addr; }