move rfc822.c as well
[apps/madmutt.git] / rfc2047.c
index b77b60b..a181e9d 100644 (file)
--- a/rfc2047.c
+++ b/rfc2047.c
 # include "config.h"
 #endif
 
+#include <lib-lib/mem.h>
+#include <lib-lib/str.h>
+#include <lib-lib/ascii.h>
+
+#include <lib-mime/mime.h>
+
 #include "mutt.h"
-#include "mime.h"
 #include "charset.h"
 #include "rfc2047.h"
+#include "thread.h"
 
-#include "lib/mem.h"
-#include "lib/str.h"
 
 #include <ctype.h>
 #include <errno.h>
 #endif
 
 #define ENCWORD_LEN_MAX 75
-#define ENCWORD_LEN_MIN 9       /* mutt_strlen ("=?.?.?.?=") */
+#define ENCWORD_LEN_MIN 9       /* m_strlen("=?.?.?.?=") */
 
 #define HSPACE(x) ((x) == '\0' || (x) == ' ' || (x) == '\t')
 
 #define CONTINUATION_BYTE(c) (((c) & 0xc0) == 0x80)
 
-extern char RFC822Specials[];
-
-typedef size_t (*encoder_t) (char *, ICONV_CONST char *, size_t,
+typedef size_t (*encoder_t) (char *, const char *, size_t,
                              const char *);
 
-static size_t convert_string (ICONV_CONST char *f, size_t flen,
+static size_t convert_string (const char *f, size_t flen,
                               const char *from, const char *to,
                               char **t, size_t * tlen)
 {
@@ -60,11 +62,11 @@ static size_t convert_string (ICONV_CONST char *f, size_t flen,
   if (cd == (iconv_t) (-1))
     return (size_t) (-1);
   obl = 4 * flen + 1;
-  ob = buf = safe_malloc (obl);
-  n = iconv (cd, &f, &flen, &ob, &obl);
-  if (n == (size_t) (-1) || iconv (cd, 0, 0, &ob, &obl) == (size_t) (-1)) {
+  ob = buf = p_new(char, obl);
+  n = my_iconv(cd, &f, &flen, &ob, &obl);
+  if (n == (size_t) (-1) || my_iconv(cd, 0, 0, &ob, &obl) == (size_t) (-1)) {
     e = errno;
-    FREE (&buf);
+    p_delete(&buf);
     iconv_close (cd);
     errno = e;
     return (size_t) (-1);
@@ -73,7 +75,7 @@ static size_t convert_string (ICONV_CONST char *f, size_t flen,
 
   *tlen = ob - buf;
 
-  safe_realloc (&buf, ob - buf + 1);
+  p_realloc(&buf, ob - buf + 1);
   *t = buf;
   iconv_close (cd);
 
@@ -94,7 +96,7 @@ char *mutt_choose_charset (const char *fromcode, const char *charsets,
 
     q = strchr (p, ':');
 
-    n = q ? q - p : mutt_strlen (p);
+    n = q ? q - p : m_strlen(p);
 
     if (!n ||
         /* Assume that we never need more than 12 characters of
@@ -102,9 +104,7 @@ char *mutt_choose_charset (const char *fromcode, const char *charsets,
         n > (ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 2 - 12))
       continue;
 
-    t = safe_malloc (n + 1);
-    memcpy (t, p, n);
-    t[n] = '\0';
+    t = p_dupstr(p, n);
 
     n = convert_string (u, ulen, fromcode, t, &s, &slen);
     if (n == (size_t) (-1))
@@ -112,21 +112,21 @@ char *mutt_choose_charset (const char *fromcode, const char *charsets,
 
     if (!tocode || n < bestn) {
       bestn = n;
-      FREE (&tocode);
+      p_delete(&tocode);
       tocode = t;
       if (d) {
-        FREE (&e);
+        p_delete(&e);
         e = s;
       }
       else
-        FREE (&s);
+        p_delete(&s);
       elen = slen;
       if (!bestn)
         break;
     }
     else {
-      FREE (&t);
-      FREE (&s);
+      p_delete(&t);
+      p_delete(&s);
     }
   }
   if (tocode) {
@@ -136,41 +136,41 @@ char *mutt_choose_charset (const char *fromcode, const char *charsets,
       *dlen = elen;
 
     mutt_canonical_charset (canonical_buff, sizeof (canonical_buff), tocode);
-    mutt_str_replace (&tocode, canonical_buff);
+    str_replace (&tocode, canonical_buff);
   }
   return tocode;
 }
 
-static size_t b_encoder (char *s, ICONV_CONST char *d, size_t dlen,
+static size_t b_encoder (char *s, const char *d, size_t dlen,
                          const char *tocode)
 {
   char *s0 = s;
 
   memcpy (s, "=?", 2), s += 2;
-  memcpy (s, tocode, mutt_strlen (tocode)), s += mutt_strlen (tocode);
+  memcpy (s, tocode, m_strlen(tocode)), s += m_strlen(tocode);
   memcpy (s, "?B?", 3), s += 3;
   for (;;) {
     if (!dlen)
       break;
     else if (dlen == 1) {
-      *s++ = B64Chars[(*d >> 2) & 0x3f];
-      *s++ = B64Chars[(*d & 0x03) << 4];
+      *s++ = __m_b64chars[(*d >> 2) & 0x3f];
+      *s++ = __m_b64chars[(*d & 0x03) << 4];
       *s++ = '=';
       *s++ = '=';
       break;
     }
     else if (dlen == 2) {
-      *s++ = B64Chars[(*d >> 2) & 0x3f];
-      *s++ = B64Chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)];
-      *s++ = B64Chars[(d[1] & 0x0f) << 2];
+      *s++ = __m_b64chars[(*d >> 2) & 0x3f];
+      *s++ = __m_b64chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)];
+      *s++ = __m_b64chars[(d[1] & 0x0f) << 2];
       *s++ = '=';
       break;
     }
     else {
-      *s++ = B64Chars[(*d >> 2) & 0x3f];
-      *s++ = B64Chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)];
-      *s++ = B64Chars[((d[1] & 0x0f) << 2) | ((d[2] >> 6) & 0x03)];
-      *s++ = B64Chars[d[2] & 0x3f];
+      *s++ = __m_b64chars[(*d >> 2) & 0x3f];
+      *s++ = __m_b64chars[((*d & 0x03) << 4) | ((d[1] >> 4) & 0x0f)];
+      *s++ = __m_b64chars[((d[1] & 0x0f) << 2) | ((d[2] >> 6) & 0x03)];
+      *s++ = __m_b64chars[d[2] & 0x3f];
       d += 3, dlen -= 3;
     }
   }
@@ -178,14 +178,14 @@ static size_t b_encoder (char *s, ICONV_CONST char *d, size_t dlen,
   return s - s0;
 }
 
-static size_t q_encoder (char *s, ICONV_CONST char *d, size_t dlen,
+static size_t q_encoder (char *s, const char *d, size_t dlen,
                          const char *tocode)
 {
   char hex[] = "0123456789ABCDEF";
   char *s0 = s;
 
   memcpy (s, "=?", 2), s += 2;
-  memcpy (s, tocode, mutt_strlen (tocode)), s += mutt_strlen (tocode);
+  memcpy (s, tocode, m_strlen(tocode)), s += m_strlen(tocode);
   memcpy (s, "?Q?", 3), s += 3;
   while (dlen--) {
     unsigned char c = *d++;
@@ -213,13 +213,13 @@ static size_t q_encoder (char *s, ICONV_CONST char *d, size_t dlen,
  * tocode, unless fromcode is 0, in which case the data is assumed to
  * be already in tocode, which should be 8-bit and stateless.
  */
-static size_t try_block (ICONV_CONST char *d, size_t dlen,
+static size_t try_block (const char *d, size_t dlen,
                          const char *fromcode, const char *tocode,
                          encoder_t * encoder, size_t * wlen)
 {
   char buf1[ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 1];
   iconv_t cd;
-  ICONV_CONST char *ib;
+  const char *ib;
   char *ob, *p;
   size_t ibl, obl;
   int count, len, len_b, len_q;
@@ -227,9 +227,9 @@ static size_t try_block (ICONV_CONST char *d, size_t dlen,
   if (fromcode) {
     cd = mutt_iconv_open (tocode, fromcode, 0);
     assert (cd != (iconv_t) (-1));
-    ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - mutt_strlen (tocode);
-    if (iconv (cd, &ib, &ibl, &ob, &obl) == (size_t) (-1) ||
-        iconv (cd, 0, 0, &ob, &obl) == (size_t) (-1)) {
+    ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - m_strlen(tocode);
+    if (my_iconv(cd, &ib, &ibl, &ob, &obl) == (size_t) (-1) ||
+        my_iconv(cd, 0, 0, &ob, &obl) == (size_t) (-1)) {
       assert (errno == E2BIG);
       iconv_close (cd);
       assert (ib > d);
@@ -238,8 +238,8 @@ static size_t try_block (ICONV_CONST char *d, size_t dlen,
     iconv_close (cd);
   }
   else {
-    if (dlen > sizeof (buf1) - mutt_strlen (tocode))
-      return sizeof (buf1) - mutt_strlen (tocode) + 1;
+    if (dlen > sizeof (buf1) - m_strlen(tocode))
+      return sizeof (buf1) - m_strlen(tocode) + 1;
     memcpy (buf1, d, dlen);
     ob = buf1 + dlen;
   }
@@ -254,7 +254,7 @@ static size_t try_block (ICONV_CONST char *d, size_t dlen,
       ++count;
   }
 
-  len = ENCWORD_LEN_MIN - 2 + mutt_strlen (tocode);
+  len = ENCWORD_LEN_MIN - 2 + m_strlen(tocode);
   len_b = len + (((ob - buf1) + 2) / 3) * 4;
   len_q = len + (ob - buf1) + 2 * count;
 
@@ -286,16 +286,16 @@ static size_t encode_block (char *s, char *d, size_t dlen,
 {
   char buf1[ENCWORD_LEN_MAX - ENCWORD_LEN_MIN + 1];
   iconv_t cd;
-  ICONV_CONST char *ib;
+  const char *ib;
   char *ob;
   size_t ibl, obl, n1, n2;
 
   if (fromcode) {
     cd = mutt_iconv_open (tocode, fromcode, 0);
     assert (cd != (iconv_t) (-1));
-    ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - mutt_strlen (tocode);
-    n1 = iconv (cd, &ib, &ibl, &ob, &obl);
-    n2 = iconv (cd, 0, 0, &ob, &obl);
+    ib = d, ibl = dlen, ob = buf1, obl = sizeof (buf1) - m_strlen(tocode);
+    n1 = my_iconv(cd, &ib, &ibl, &ob, &obl);
+    n2 = my_iconv(cd, 0, 0, &ob, &obl);
     assert (n1 != (size_t) (-1) && n2 != (size_t) (-1));
     iconv_close (cd);
     return (*encoder) (s, buf1, ob - buf1, tocode);
@@ -342,7 +342,7 @@ static size_t choose_block (char *d, size_t dlen, int col,
  * The input data is assumed to be a single line starting at column col;
  * if col is non-zero, the preceding character was a space.
  */
-static int rfc2047_encode (ICONV_CONST char *d, size_t dlen, int col,
+static int rfc2047_encode (const char *d, size_t dlen, int col,
                            const char *fromcode, const char *charsets,
                            char **e, size_t * elen, char *specials)
 {
@@ -355,15 +355,13 @@ static int rfc2047_encode (ICONV_CONST char *d, size_t dlen, int col,
   encoder_t encoder;
   char *tocode1 = 0;
   const char *tocode;
-  char *icode = "UTF-8";
+  const char *icode = "UTF-8";
 
   /* Try to convert to UTF-8. */
   if (convert_string (d, dlen, fromcode, icode, &u, &ulen)) {
     ret = 1;
     icode = 0;
-    u = safe_malloc ((ulen = dlen) + 1);
-    memcpy (u, d, dlen);
-    u[ulen] = 0;
+    u = p_dupstr(d, ulen = dlen);
   }
 
   /* Find earliest and latest things we must encode. */
@@ -446,7 +444,7 @@ static int rfc2047_encode (ICONV_CONST char *d, size_t dlen, int col,
 
   /* Initialise the output buffer with the us-ascii prefix. */
   buflen = 2 * ulen;
-  buf = safe_malloc (buflen);
+  buf = p_new(char, buflen);
   bufpos = t0 - u;
   memcpy (buf, u, t0 - u);
 
@@ -480,15 +478,15 @@ static int rfc2047_encode (ICONV_CONST char *d, size_t dlen, int col,
 
     /* Add to output buffer. */
 #define LINEBREAK "\n\t"
-    if (bufpos + wlen + mutt_strlen (LINEBREAK) > buflen) {
-      buflen = bufpos + wlen + mutt_strlen (LINEBREAK);
-      safe_realloc (&buf, buflen);
+    if (bufpos + wlen + m_strlen(LINEBREAK) > buflen) {
+      buflen = bufpos + wlen + m_strlen(LINEBREAK);
+      p_realloc(&buf, buflen);
     }
     r = encode_block (buf + bufpos, t, n, icode, tocode, encoder);
     assert (r == wlen);
     bufpos += wlen;
-    memcpy (buf + bufpos, LINEBREAK, mutt_strlen (LINEBREAK));
-    bufpos += mutt_strlen (LINEBREAK);
+    memcpy (buf + bufpos, LINEBREAK, m_strlen(LINEBREAK));
+    bufpos += m_strlen(LINEBREAK);
 #undef LINEBREAK
 
     col = 1;
@@ -498,14 +496,14 @@ static int rfc2047_encode (ICONV_CONST char *d, size_t dlen, int col,
 
   /* Add last encoded word and us-ascii suffix to buffer. */
   buflen = bufpos + wlen + (u + ulen - t1);
-  safe_realloc (&buf, buflen + 1);
+  p_realloc(&buf, buflen + 1);
   r = encode_block (buf + bufpos, t, t1 - t, icode, tocode, encoder);
   assert (r == wlen);
   bufpos += wlen;
   memcpy (buf + bufpos, t1, u + ulen - t1);
 
-  FREE (&tocode1);
-  FREE (&u);
+  p_delete(&tocode1);
+  p_delete(&u);
 
   buf[buflen] = '\0';
 
@@ -518,7 +516,7 @@ void _rfc2047_encode_string (char **pd, int encode_specials, int col)
 {
   char *e;
   size_t elen;
-  char *charsets;
+  const char *charsets;
 
   if (!Charset || !*pd)
     return;
@@ -527,26 +525,22 @@ void _rfc2047_encode_string (char **pd, int encode_specials, int col)
   if (!charsets || !*charsets)
     charsets = "UTF-8";
 
-  rfc2047_encode (*pd, mutt_strlen (*pd), col,
+  rfc2047_encode (*pd, m_strlen(*pd), col,
                   Charset, charsets, &e, &elen,
                   encode_specials ? RFC822Specials : NULL);
 
-  FREE (pd);
+  p_delete(pd);
   *pd = e;
 }
 
 void rfc2047_encode_adrlist (ADDRESS * addr, const char *tag)
 {
   ADDRESS *ptr = addr;
-  int col = tag ? mutt_strlen (tag) + 2 : 32;
+  int col = tag ? m_strlen(tag) + 2 : 32;
 
   while (ptr) {
     if (ptr->personal)
       _rfc2047_encode_string (&ptr->personal, 1, col);
-#ifdef EXACT_ADDRESS
-    if (ptr->val)
-      _rfc2047_encode_string (&ptr->val, 1, col);
-#endif
     ptr = ptr->next;
   }
 }
@@ -559,7 +553,7 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len)
   int enc = 0, count = 0;
   char *charset = NULL;
 
-  pd = d0 = safe_malloc (mutt_strlen (s));
+  pd = d0 = p_new(char, m_strlen(s));
 
   for (pp = s; (pp1 = strchr (pp, '?')); pp = pp1 + 1) {
     count++;
@@ -569,9 +563,7 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len)
       t = pp1;
       if ((t1 = memchr (pp, '*', t - pp)))
         t = t1;
-      charset = safe_malloc (t - pp + 1);
-      memcpy (charset, pp, t - pp);
-      charset[t - pp] = '\0';
+      charset = p_dupstr(pp, t - pp);
       break;
     case 3:
       if (toupper ((unsigned char) *pp) == 'Q')
@@ -579,8 +571,8 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len)
       else if (toupper ((unsigned char) *pp) == 'B')
         enc = ENCBASE64;
       else {
-        FREE (&charset);
-        FREE (&d0);
+        p_delete(&charset);
+        p_delete(&d0);
         return (-1);
       }
       break;
@@ -589,9 +581,7 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len)
         for (; pp < pp1; pp++) {
           if (*pp == '_')
             *pd++ = ' ';
-          else if (*pp == '=' &&
-                   (!(pp[1] & ~127) && hexval (pp[1]) != -1) &&
-                   (!(pp[2] & ~127) && hexval (pp[2]) != -1)) {
+          else if (*pp == '=' && hexval(pp[1]) >= 0 && hexval(pp[2]) >= 0) {
             *pd++ = (hexval (pp[1]) << 4) | hexval (pp[2]);
             pp += 2;
           }
@@ -606,7 +596,7 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len)
         for (; pp < pp1; pp++) {
           if (*pp == '=')
             break;
-          if ((*pp & ~127) || (c = base64val (*pp)) == -1)
+          if ((c = base64val(*pp)) < 0)
             continue;
           if (k + 6 >= 8) {
             k -= 2;
@@ -626,9 +616,9 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len)
 
   if (charset)
     mutt_convert_string (&d0, charset, Charset, M_ICONV_HOOK_FROM);
-  strfcpy (d, d0, len);
-  FREE (&charset);
-  FREE (&d0);
+  m_strcpy(d, len, d0);
+  p_delete(&charset);
+  p_delete(&d0);
   return (0);
 }
 
@@ -715,14 +705,14 @@ void rfc2047_decode (char **pd)
   if (!s || !*s)
     return;
 
-  dlen = 4 * mutt_strlen (s);        /* should be enough */
-  d = d0 = safe_malloc (dlen + 1);
+  dlen = 4 * m_strlen(s);        /* should be enough */
+  d = d0 = p_new(char, dlen + 1);
 
   while (*s && dlen > 0) {
     if (!(p = find_encoded_word (s, &q))) {
       /* no encoded words */
       if (!option (OPTSTRICTMIME)) {
-        n = mutt_strlen (s);
+        n = m_strlen(s);
         if (found_encoded && (m = lwslen (s, n)) != 0) {
           if (m != n)
             *d = ' ', d++, dlen--;
@@ -732,10 +722,9 @@ void rfc2047_decode (char **pd)
           char *t;
           size_t tlen;
 
-          t = safe_malloc (n + 1);
-          strfcpy (t, s, n + 1);
+          t = p_dupstr(s, n);
           if (mutt_convert_nonmime_string (&t) == 0) {
-            tlen = mutt_strlen (t);
+            tlen = m_strlen(t);
             strncpy (d, t, tlen);
             d += tlen;
           }
@@ -743,7 +732,7 @@ void rfc2047_decode (char **pd)
             strncpy (d, s, n);
             d += n;
           }
-          FREE (&t);
+          p_delete(&t);
           break;
         }
       }
@@ -785,15 +774,15 @@ void rfc2047_decode (char **pd)
     rfc2047_decode_word (d, p, dlen);
     found_encoded = 1;
     s = q;
-    n = mutt_strlen (d);
+    n = m_strlen(d);
     dlen -= n;
     d += n;
   }
   *d = 0;
 
-  FREE (pd);
+  p_delete(pd);
   *pd = d0;
-  mutt_str_adjust (pd);
+  str_adjust (pd);
 }
 
 void rfc2047_decode_adrlist (ADDRESS * a)
@@ -801,10 +790,27 @@ void rfc2047_decode_adrlist (ADDRESS * a)
   while (a) {
     if (a->personal)
       rfc2047_decode (&a->personal);
-#ifdef EXACT_ADDRESS
-    if (a->val && strstr (a->val, "=?") != NULL)
-      rfc2047_decode (&a->val);
-#endif
     a = a->next;
   }
 }
+
+void rfc2047_decode_envelope (ENVELOPE* e) {
+
+  if (!e)
+    return;
+
+  /* do RFC2047 decoding */
+  rfc2047_decode_adrlist (e->from);
+  rfc2047_decode_adrlist (e->to);
+  rfc2047_decode_adrlist (e->cc);
+  rfc2047_decode_adrlist (e->bcc);
+  rfc2047_decode_adrlist (e->reply_to);
+  rfc2047_decode_adrlist (e->mail_followup_to);
+  rfc2047_decode_adrlist (e->return_path);
+  rfc2047_decode_adrlist (e->sender);
+
+  if (e->subject) {
+    rfc2047_decode (&e->subject);
+    mutt_adjust_subject (e);
+  }
+}