- char *p;
-
- for (; addr; addr = addr->next)
- if (!addr->group && addr->mailbox && strchr (addr->mailbox, '@') == NULL) {
- p = p_new(char, m_strlen(addr->mailbox) + m_strlen(host) + 2);
- sprintf (p, "%s@%s", addr->mailbox, host); /* __SPRINTF_CHECKED__ */
- p_delete(&addr->mailbox);
- addr->mailbox = p;
+ struct rfc822_parse_ctx ctx = { NULL, "", 0, "", 0 };
+ int ws_pending = 0;
+ address_t **last;
+
+ last = address_list_last(&top);
+
+ for (;;) {
+ ws_pending = ISSPACE(*s);
+ s = skipspaces(s);
+
+ switch (*s) {
+ case '\0':
+ if (ctx.phraselen) {
+ terminate_buffer(ctx.phrase);
+ terminate_buffer(ctx.comment);
+ last = add_addrspec(last, &ctx);
+ } else
+ if (ctx.commentlen && ctx.cur && !ctx.cur->personal) {
+ terminate_buffer(ctx.comment);
+ ctx.cur->personal = m_strdup(ctx.comment);
+ }
+ return top;
+
+ default:
+ if (ctx.phraselen && ctx.phraselen < sizeof(ctx.phrase) - 1 && ws_pending)
+ ctx.phrase[ctx.phraselen++] = ' ';
+ s = next_token(s, ctx.phrase, &ctx.phraselen, sizeof(ctx.phrase) - 1);
+ if (!s) {
+ address_delete(&top);
+ return NULL;
+ }
+ continue;
+
+ case '(':
+ if (ctx.commentlen && ctx.commentlen < sizeof(ctx.comment) - 1)
+ ctx.comment[ctx.commentlen++] = ' ';
+ s = next_token(s, ctx.comment, &ctx.commentlen, sizeof(ctx.comment) - 1);
+ if (!s) {
+ address_delete (&top);
+ return NULL;
+ }
+ continue;
+
+ case ',':
+ if (ctx.phraselen) {
+ terminate_buffer(ctx.phrase);
+ last = add_addrspec(last, &ctx);
+ } else
+ if (ctx.commentlen && ctx.cur && !ctx.cur->personal) {
+ terminate_buffer(ctx.comment);
+ ctx.cur->personal = m_strdup(ctx.comment);
+ }
+ break;
+
+ case ':':
+ terminate_buffer(ctx.phrase);
+ *last = address_new();
+ (*last)->mailbox = m_strdup(ctx.phrase);
+ (*last)->group = 1;
+ last = &(*last)->next;
+ break;
+
+ case ';':
+ if (ctx.phraselen) {
+ terminate_buffer(ctx.phrase);
+ last = add_addrspec(last, &ctx);
+ } else
+ if (ctx.commentlen && ctx.cur && !ctx.cur->personal) {
+ terminate_buffer(ctx.comment);
+ ctx.cur->personal = m_strdup(ctx.comment);
+ }
+
+ /* add group terminator */
+ *last = address_new();
+ return top;
+
+ case '<':
+ terminate_buffer(ctx.phrase);
+ ctx.cur = address_new ();
+ if (ctx.phraselen) {
+ /* if we get something like "Michael R. Elkins" remove the quotes */
+ rfc822_dequote_comment(ctx.phrase);
+ ctx.cur->personal = m_strdup(ctx.phrase);
+ }
+
+ s = parse_address(skipspaces(s + 1), &ctx);
+ if (!s || *s != '>' || !ctx.cur->mailbox) {
+ address_delete(&top);
+ address_delete(&ctx.cur);
+ return NULL;
+ }
+
+ *last = ctx.cur;
+ break;
+ }
+
+ ctx.commentlen = 0;
+ ctx.phraselen = 0;
+ s++;