turn charset into a lua package as well.
[apps/madmutt.git] / lib-mime / rfc822address.c
index 9009d40..c6b12ab 100644 (file)
  * please see the file GPL in the top level source directory.
  */
 
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-#include <lib-lib/mem.h>
-#include <lib-lib/str.h>
-#include <lib-lib/ascii.h>
-#include <lib-lib/macros.h>
+#include <lib-lib/lib-lib.h>
 
 #include "mutt_idna.h"
 
-void address_wipe(address_t *addr)
-{
-    p_delete(&addr->personal);
-    p_delete(&addr->mailbox);
-    address_delete(&addr->next);
-}
-
-
 void rfc822_qualify(address_t *addr, const char *host)
 {
-    char *p;
+    if (!host)
+        return;
 
     for (; addr; addr = addr->next) {
         if (!addr->group && addr->mailbox && !strchr(addr->mailbox, '@')) {
-            p = p_new(char, m_strlen(addr->mailbox) + m_strlen(host) + 2);
-            sprintf(p, "%s@%s", addr->mailbox, host);        /* __SPRINTF_CHECKED__ */
+            char *p = p_new(char, m_strlen(addr->mailbox) + m_strlen(host) + 2);
+            sprintf(p, "%s@%s", addr->mailbox, host);
             p_delete(&addr->mailbox);
             addr->mailbox = p;
         }
     }
 }
 
-address_t *address_dup(address_t *addr)
+address_t *address_dup(const address_t *addr)
 {
     address_t *res = address_new();
 
@@ -69,7 +55,7 @@ address_t *address_dup(address_t *addr)
     return res;
 }
 
-address_t *address_list_dup(address_t *addr)
+address_t *address_list_dup(const address_t *addr)
 {
     address_t *res = NULL, **resp = &res;
 
@@ -81,6 +67,26 @@ address_t *address_list_dup(address_t *addr)
     return res;
 }
 
+/* given a list of addresses, return a list of unique addresses */
+void address_list_uniq(address_t *a)
+{
+    for (; a; a = a->next) {
+        address_t **b = &a->next;
+
+        if (!a->mailbox)
+            continue;
+
+        while (*b) {
+            if ((*b)->mailbox && !ascii_strcasecmp((*b)->mailbox, a->mailbox))
+            {
+                address_t *pop = address_list_pop(b);
+                address_delete(&pop);
+            } else {
+                b = &(*b)->next;
+            }
+        }
+    }
+}
 
 /****************************************************************************/
 /* Parsing functions                                                        */
@@ -139,7 +145,7 @@ static const char *parse_comment(const char *s, static_buf *buf)
           case ')':
             level--;
             if (!level)
-                return s;
+                return s + 1;
             break;
 
           case '\\':
@@ -250,7 +256,7 @@ parse_address(const char *s, static_buf *comment, address_t *cur)
     return s;
 }
 
-address_t **rfc822_eotoken(address_t **last, static_buf *phrase, static_buf *comment)
+static address_t **rfc822_eotoken(address_t **last, static_buf *phrase, static_buf *comment)
 {
     if (phrase->len) {
         const char *s;
@@ -258,7 +264,7 @@ address_t **rfc822_eotoken(address_t **last, static_buf *phrase, static_buf *com
 
         s = parse_address(phrase->buf, comment, cur);
         if (s && *s && *s != ',' && *s != ';') {
-            address_delete(&cur);
+            address_list_wipe(&cur);
             return last;
         }
 
@@ -289,7 +295,7 @@ address_t *rfc822_parse_adrlist(address_t *top, const char *s)
                 stbuf_append_sp(&phrase);
             s = next_phrase(s, &phrase);
             if (!s) {
-                address_delete(&top);
+                address_list_wipe(&top);
                 return NULL;
             }
             continue;
@@ -298,7 +304,7 @@ address_t *rfc822_parse_adrlist(address_t *top, const char *s)
             stbuf_append_sp(&comment);
             s = parse_comment(s + 1, &comment);
             if (!s) {
-                address_delete(&top);
+                address_list_wipe(&top);
                 return NULL;
             }
             continue;
@@ -313,8 +319,8 @@ address_t *rfc822_parse_adrlist(address_t *top, const char *s)
 
             s = parse_address(skipspaces(s + 1), &comment, cur);
             if (!s || *s != '>' || !cur->mailbox) {
-                address_delete(&top);
-                address_delete(&cur);
+                address_list_wipe(&top);
+                address_list_wipe(&cur);
                 return NULL;
             }
 
@@ -383,90 +389,75 @@ rfc822_strcpy(char *buf, ssize_t buflen, const char *p, const char *specials)
     }
 }
 
-ssize_t rfc822_write_address_single(char *buf, ssize_t buflen,
-                                    address_t *addr, int display)
+ssize_t
+rfc822_addrcpy(char *buf, ssize_t buflen, address_t *addr, int display)
 {
     ssize_t pos = 0;
 
     if (!addr)
         return 0;
 
-    buflen--;                     /* save room for the terminal nul */
-
     if (addr->personal) {
         pos = rfc822_strcpy(buf, buflen, addr->personal, RFC822Specials);
-        if (pos + 2 >= buflen)
-            goto done;
-
-        buf[pos++] = ' ';
-        buf[pos++] = '<';
+        pos += m_strcpy(buf + pos, buflen - pos, " <");
     }
 
     if (addr->mailbox) {
-        if (!display) {
-            pos += m_strcpy(buf + pos, buflen - pos, addr->mailbox);
-        } else {
-            pos += m_strcpy(buf + pos, buflen - pos, mutt_addr_for_display(addr));
-        }
+        pos += m_strcpy(buf + pos, buflen - pos,
+                        display ? mutt_addr_for_display(addr) : addr->mailbox);
 
         if (addr->personal) {
-            if (pos + 1 >= buflen)
-                goto done;
-            buf[pos++] = '>';
+            pos += m_strputc(buf + pos, buflen - pos, '>');
         }
 
         if (addr->group) {
-            if (pos + 1 >= buflen)
-                goto done;
-            buf[pos++] = ':';
+            pos += m_strputc(buf + pos, buflen - pos, ':');
         }
     } else {
-        if (pos + 1 >= buflen)
-            goto done;
-        buf[pos++] = ';';
+        pos += m_strputc(buf + pos, buflen - pos, ';');
     }
 
-  done:
-    /* no need to check for length here since we already save space at the
-       beginning of this routine */
-    buf[pos] = 0;
     return pos;
 }
 
 /* note: it is assumed that `buf' is nul terminated! */
 ssize_t
-rfc822_write_address(char *buf, ssize_t buflen, address_t *addr, int display)
+rfc822_addrcat(char *buf, ssize_t buflen, address_t *addr, int display)
 {
-    ssize_t pos;
+    ssize_t pos = m_strnlen(buf, buflen);
 
-    buflen--;                     /* save room for the terminal nul */
-    pos = m_strnlen(buf, buflen);
-
-    if (pos) {
-        if (pos + 2 >= buflen)
-            goto done;
-
-        buf[pos++] = ',';
-        buf[pos++] = ' ';
-    }
+    if (pos)
+        pos += m_strcpy(buf + pos, buflen - pos, ", ");
 
     for (; addr; addr = addr->next) {
-        pos += rfc822_write_address_single(buf + pos, buflen + 1 - pos,
-                                           addr, display);
+        pos += rfc822_addrcpy(buf + pos, buflen - pos, addr, display);
 
         if (!addr->group && addr->next && addr->next->mailbox) {
             /* if there is another address, and its not a group mailbox name or
                group terminator, add a comma to separate the addresses */
-            if (pos + 2 >= buflen)
-                break;
-
-            buf[pos++] = ',';
-            buf[pos++] = ' ';
+            pos += m_strcpy(buf + pos, buflen - pos, ", ");
         }
     }
 
-  done:
-    buf[pos] = '\0';
     return pos;
 }
 
+address_t *mutt_parse_adrlist(address_t *p, const char *s)
+{
+    /* check for a simple whitespace separated list of addresses */
+    char *q = strpbrk(s, "\"<>():;,\\");
+    char tmp[HUGE_STRING];
+
+    if (q)
+        return rfc822_parse_adrlist(p, s);
+
+    m_strcpy(tmp, sizeof(tmp), s);
+    q = tmp;
+    while ((q = strtok(q, " \t"))) {
+        p = rfc822_parse_adrlist(p, q);
+        q = NULL;
+    }
+
+    return p;
+}
+