push some date functions in the lib-lib.
[apps/madmutt.git] / lib-mime / rfc822.c
index d672891..9009d40 100644 (file)
@@ -37,8 +37,6 @@
 
 #include "mutt_idna.h"
 
-const char RFC822Specials[] = "@.,:;<>[]\\\"()";
-
 void address_wipe(address_t *addr)
 {
     p_delete(&addr->personal);
@@ -180,7 +178,7 @@ static const char *parse_quote(const char *s, static_buf *buf)
     return NULL;
 }
 
-#define is_special(x)         strchr(RFC822Specials,x)
+const char RFC822Specials[] = "@.,:;<>[]\\\"()";
 
 static const char *next_phrase(const char *s, static_buf *buf)
 {
@@ -189,13 +187,13 @@ static const char *next_phrase(const char *s, static_buf *buf)
         return parse_quote(s + 1, buf);
     }
 
-    if (is_special(*s)) {
+    if (strchr(RFC822Specials, *s)) {
         stbuf_append(buf, *s);
         return s + 1;
     }
 
     while (*s) {
-        if (ISSPACE(*s) || is_special(*s))
+        if (ISSPACE(*s) || strchr(RFC822Specials, *s))
             break;
         stbuf_append(buf, *s++);
     }
@@ -210,7 +208,7 @@ parse_mailboxdomain(const char *s, const char *nonspecial, static_buf *mbox,
     while (*s) {
         s = skipspaces(s);
 
-        if (!strchr(nonspecial, *s) && is_special(*s))
+        if (!strchr(nonspecial, *s) && strchr(RFC822Specials, *s))
             return s;
 
         if (*s == '(') {
@@ -359,185 +357,116 @@ address_t *rfc822_parse_adrlist(address_t *top, const char *s)
 /* Output functions                                                         */
 /****************************************************************************/
 
-void
-rfc822_cat(char *buf, size_t buflen, const char *value, const char *specials)
+ssize_t
+rfc822_strcpy(char *buf, ssize_t buflen, const char *p, const char *specials)
 {
-    if (strpbrk(value, specials)) {
-        char tmp[256], *pc = tmp;
-        size_t tmplen = sizeof (tmp) - 3;
-
-        *pc++ = '"';
-        for (; *value && tmplen > 1; value++) {
-            if (*value == '\\' || *value == '"') {
-                *pc++ = '\\';
-                tmplen--;
+    if (strpbrk(p, specials)) {
+        ssize_t pos = 0;
+
+        buf[pos++] = '"';
+
+        while (*p && pos < buflen - 2) {
+            if (*p == '\\' || *p == '"') {
+                if (pos >= buflen - 4)
+                    break;
+                buf[pos++] = '\\';
             }
-            *pc++ = *value;
-            tmplen--;
+
+            buf[pos++] = *p++;
         }
-        *pc++ = '"';
-        *pc = 0;
-        m_strcpy(buf, buflen, tmp);
+
+        buf[pos++] = '"';
+        buf[pos]   = '\0';
+        return pos;
     } else {
-        m_strcpy(buf, buflen, value);
+        return m_strcpy(buf, buflen, p);
     }
 }
 
-void rfc822_write_address_single(char *buf, size_t buflen, address_t * addr,
-                                 int display)
+ssize_t rfc822_write_address_single(char *buf, ssize_t buflen,
+                                    address_t *addr, int display)
 {
-    size_t len;
-    char *pbuf = buf;
-    char *pc;
+    ssize_t pos = 0;
 
     if (!addr)
-        return;
+        return 0;
 
     buflen--;                     /* save room for the terminal nul */
 
     if (addr->personal) {
-        if (strpbrk (addr->personal, RFC822Specials)) {
-            if (!buflen)
-                goto done;
-            *pbuf++ = '"';
-            buflen--;
-            for (pc = addr->personal; *pc && buflen > 0; pc++) {
-                if (*pc == '"' || *pc == '\\') {
-                    if (!buflen)
-                        goto done;
-                    *pbuf++ = '\\';
-                    buflen--;
-                }
-                if (!buflen)
-                    goto done;
-                *pbuf++ = *pc;
-                buflen--;
-            }
-            if (!buflen)
-                goto done;
-            *pbuf++ = '"';
-            buflen--;
-        }
-        else {
-            if (!buflen)
-                goto done;
-            m_strcpy(pbuf, buflen, addr->personal);
-            len = m_strlen(pbuf);
-            pbuf += len;
-            buflen -= len;
-        }
-
-        if (!buflen)
+        pos = rfc822_strcpy(buf, buflen, addr->personal, RFC822Specials);
+        if (pos + 2 >= buflen)
             goto done;
-        *pbuf++ = ' ';
-        buflen--;
-    }
 
-    if (addr->personal || (addr->mailbox && *addr->mailbox == '@')) {
-        if (!buflen)
-            goto done;
-        *pbuf++ = '<';
-        buflen--;
+        buf[pos++] = ' ';
+        buf[pos++] = '<';
     }
 
     if (addr->mailbox) {
-        if (!buflen)
-            goto done;
-        if (ascii_strcmp (addr->mailbox, "@") && !display) {
-            m_strcpy(pbuf, buflen, addr->mailbox);
-            len = m_strlen(pbuf);
-        }
-        else if (ascii_strcmp (addr->mailbox, "@") && display) {
-            m_strcpy(pbuf, buflen, mutt_addr_for_display(addr));
-            len = m_strlen(pbuf);
-        }
-        else {
-            *pbuf = '\0';
-            len = 0;
+        if (!display) {
+            pos += m_strcpy(buf + pos, buflen - pos, addr->mailbox);
+        } else {
+            pos += m_strcpy(buf + pos, buflen - pos, mutt_addr_for_display(addr));
         }
-        pbuf += len;
-        buflen -= len;
 
-        if (addr->personal || (addr->mailbox && *addr->mailbox == '@')) {
-            if (!buflen)
+        if (addr->personal) {
+            if (pos + 1 >= buflen)
                 goto done;
-            *pbuf++ = '>';
-            buflen--;
+            buf[pos++] = '>';
         }
 
         if (addr->group) {
-            if (!buflen)
+            if (pos + 1 >= buflen)
                 goto done;
-            *pbuf++ = ':';
-            buflen--;
-            if (!buflen)
-                goto done;
-            *pbuf++ = ' ';
-            buflen--;
+            buf[pos++] = ':';
         }
-    }
-    else {
-        if (!buflen)
+    } else {
+        if (pos + 1 >= buflen)
             goto done;
-        *pbuf++ = ';';
-        buflen--;
+        buf[pos++] = ';';
     }
-done:
+
+  done:
     /* no need to check for length here since we already save space at the
        beginning of this routine */
-    *pbuf = 0;
+    buf[pos] = 0;
+    return pos;
 }
 
 /* note: it is assumed that `buf' is nul terminated! */
-void rfc822_write_address (char *buf, size_t buflen, address_t * addr,
-                           int display)
+ssize_t
+rfc822_write_address(char *buf, ssize_t buflen, address_t *addr, int display)
 {
-    char *pbuf = buf;
-    size_t len = m_strlen(buf);
+    ssize_t pos;
 
     buflen--;                     /* save room for the terminal nul */
+    pos = m_strnlen(buf, buflen);
 
-    if (len > 0) {
-        if (len > buflen)
-            return;                   /* safety check for bogus arguments */
-
-        pbuf += len;
-        buflen -= len;
-        if (!buflen)
-            goto done;
-        *pbuf++ = ',';
-        buflen--;
-        if (!buflen)
+    if (pos) {
+        if (pos + 2 >= buflen)
             goto done;
-        *pbuf++ = ' ';
-        buflen--;
+
+        buf[pos++] = ',';
+        buf[pos++] = ' ';
     }
 
-    for (; addr && buflen > 0; addr = addr->next) {
-        /* use buflen+1 here because we already saved space for the trailing
-           nul char, and the subroutine can make use of it */
-        rfc822_write_address_single (pbuf, buflen + 1, addr, display);
-
-        /* this should be safe since we always have at least 1 char passed into
-           the above call, which means `pbuf' should always be nul terminated */
-        len = m_strlen(pbuf);
-        pbuf += len;
-        buflen -= len;
-
-        /* if there is another address, and its not a group mailbox name or
-           group terminator, add a comma to separate the addresses */
-        if (addr->next && addr->next->mailbox && !addr->group) {
-            if (!buflen)
-                goto done;
-            *pbuf++ = ',';
-            buflen--;
-            if (!buflen)
-                goto done;
-            *pbuf++ = ' ';
-            buflen--;
+    for (; addr; addr = addr->next) {
+        pos += rfc822_write_address_single(buf + pos, buflen + 1 - 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++] = ' ';
         }
     }
-done:
-    *pbuf = 0;
+
+  done:
+    buf[pos] = '\0';
+    return pos;
 }