workaround a stupid issue in how decoding is performed in mutt *sigh*
[apps/madmutt.git] / copy.c
diff --git a/copy.c b/copy.c
index 65ed14c..a52a4eb 100644 (file)
--- a/copy.c
+++ b/copy.c
 #include <lib-lib/lib-lib.h>
 
 #include <lib-mime/mime.h>
+#include <lib-ui/lib-ui.h>
+#include <lib-mx/mx.h>
 
 #include "mutt.h"
 #include "handler.h"
-#include "mx.h"
 #include "copy.h"
-#include <lib-crypt/crypt.h>
+#include "crypt.h"
 #include "mutt_idna.h"
 
 static int address_header_decode (char **str);
@@ -32,12 +33,13 @@ mutt_copy_hdr (FILE* in, FILE* out, off_t off_start, off_t off_end,
   int this_is_from;
   int ignore = 0;
   char buf[STRING];             /* should be long enough to get most fields in one pass */
-  char *nl;
+  char *eol;
   string_list_t *t;
   char **headers;
   int hdr_count;
   int x;
   char *this_one = NULL;
+  ssize_t this_one_len = 0, headers_len = 0;
   int error;
   int curline = 0;
 
@@ -54,13 +56,13 @@ mutt_copy_hdr (FILE* in, FILE* out, off_t off_start, off_t off_end,
      * we can do a more efficient line to line copying
      */
     while (ftello (in) < off_end) {
-      nl = strchr (buf, '\n');
+      eol = strchr (buf, '\n');
 
       if ((fgets (buf, sizeof (buf), in)) == NULL)
         break;
 
       /* Is it the begining of a header? */
-      if (nl && buf[0] != ' ' && buf[0] != '\t') {
+      if (eol && buf[0] != ' ' && buf[0] != '\t') {
         ignore = 1;
         if (!from && m_strncmp("From ", buf, 5) == 0) {
           if ((flags & CH_FROM) == 0)
@@ -74,20 +76,32 @@ mutt_copy_hdr (FILE* in, FILE* out, off_t off_start, off_t off_end,
         else if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n'))
           break;                /* end of header */
 
-        if ((flags & (CH_UPDATE | CH_XMIT | CH_NOSTATUS)) &&
-            (ascii_strncasecmp ("Status:", buf, 7) == 0 ||
-             ascii_strncasecmp ("X-Status:", buf, 9) == 0))
-          continue;
-        if ((flags & (CH_UPDATE_LEN | CH_XMIT | CH_NOLEN)) &&
-            (ascii_strncasecmp ("Content-Length:", buf, 15) == 0 ||
-             ascii_strncasecmp ("Lines:", buf, 6) == 0))
-          continue;
-        if ((flags & CH_UPDATE_REFS) &&
-            ascii_strncasecmp ("References:", buf, 11) == 0)
-          continue;
-        if ((flags & CH_UPDATE_IRT) &&
-            ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0)
-          continue;
+        switch (mime_which_token(buf, (strchr(buf, ':') ?: buf) - buf)) {
+          case MIME_STATUS:
+          case MIME_X_STATUS:
+            if (flags & (CH_UPDATE | CH_XMIT | CH_NOSTATUS))
+              continue;
+            break;
+
+          case MIME_CONTENT_LENGTH:
+          case MIME_LINES:
+            if (flags & (CH_UPDATE_LEN | CH_XMIT | CH_NOLEN))
+              continue;
+            break;
+
+          case MIME_REFERENCES:
+            if (flags & CH_UPDATE_REFS)
+              continue;
+            break;
+
+          case MIME_IN_REPLY_TO:
+            if (flags & CH_UPDATE_IRT)
+              continue;
+            break;
+
+          default:
+            break;
+        }
         ignore = 0;
       }
 
@@ -115,14 +129,14 @@ mutt_copy_hdr (FILE* in, FILE* out, off_t off_start, off_t off_end,
 
   /* Read all the headers into the array */
   while (ftello (in) < off_end) {
-    nl = strchr (buf, '\n');
+    eol = strchr (buf, '\n');
 
     /* Read a line */
     if ((fgets (buf, sizeof (buf), in)) == NULL)
       break;
 
     /* Is it the begining of a header? */
-    if (nl && buf[0] != ' ' && buf[0] != '\t') {
+    if (eol && buf[0] != ' ' && buf[0] != '\t') {
 
       /* set curline to 1 for To:/Cc:/Bcc: and 0 otherwise */
       curline = (flags & CH_WEED) && (m_strncmp("To:", buf, 3) == 0 ||
@@ -139,8 +153,9 @@ mutt_copy_hdr (FILE* in, FILE* out, off_t off_start, off_t off_end,
         if (!headers[x])
           headers[x] = this_one;
         else {
-          p_realloc(&headers[x], m_strlen(headers[x]) + m_strlen(this_one) + 1);
-          strcat(headers[x], this_one);        /* __STRCAT_CHECKED__ */
+          headers_len =  m_strlen(headers[x]) + m_strlen(this_one) + 1;
+          p_realloc(&headers[x], headers_len);
+          m_strcat(headers[x], headers_len, this_one);
           p_delete(&this_one);
         }
 
@@ -159,34 +174,49 @@ mutt_copy_hdr (FILE* in, FILE* out, off_t off_start, off_t off_end,
 
       /* note: CH_FROM takes precedence over header weeding. */
       if (!((flags & CH_FROM) && (flags & CH_FORCE_FROM) && this_is_from) &&
-          (flags & CH_WEED) &&
-          mutt_matches_ignore (buf, Ignore) &&
-          !mutt_matches_ignore (buf, UnIgnore))
-        continue;
-      if ((flags & CH_WEED_DELIVERED) &&
-          ascii_strncasecmp ("Delivered-To:", buf, 13) == 0)
-        continue;
-      if ((flags & (CH_UPDATE | CH_XMIT | CH_NOSTATUS)) &&
-          (ascii_strncasecmp ("Status:", buf, 7) == 0 ||
-           ascii_strncasecmp ("X-Status:", buf, 9) == 0))
-        continue;
-      if ((flags & (CH_UPDATE_LEN | CH_XMIT | CH_NOLEN)) &&
-          (ascii_strncasecmp ("Content-Length:", buf, 15) == 0 ||
-           ascii_strncasecmp ("Lines:", buf, 6) == 0))
-        continue;
-      if ((flags & CH_MIME) &&
-          ((ascii_strncasecmp ("content-", buf, 8) == 0 &&
-            (ascii_strncasecmp ("transfer-encoding:", buf + 8, 18) == 0 ||
-             ascii_strncasecmp ("type:", buf + 8, 5) == 0)) ||
-           ascii_strncasecmp ("mime-version:", buf, 13) == 0))
-        continue;
-      if ((flags & CH_UPDATE_REFS) &&
-          ascii_strncasecmp ("References:", buf, 11) == 0)
-        continue;
-      if ((flags & CH_UPDATE_IRT) &&
-          ascii_strncasecmp ("In-Reply-To:", buf, 12) == 0)
+          (flags & CH_WEED) && string_list_contains(Ignore, buf, "*")
+          && !string_list_contains(UnIgnore, buf, "*"))
         continue;
 
+      switch (mime_which_token(buf, (strchr(buf, ':') ?: buf) - buf)) {
+        case MIME_DELIVERED_TO:
+          if (flags & CH_WEED_DELIVERED)
+            continue;
+          break;
+
+        case MIME_STATUS:
+        case MIME_X_STATUS:
+          if (flags & (CH_UPDATE | CH_XMIT | CH_NOSTATUS))
+            continue;
+          break;
+
+        case MIME_CONTENT_LENGTH:
+        case MIME_LINES:
+          if (flags & (CH_UPDATE_LEN | CH_XMIT | CH_NOLEN))
+            continue;
+          break;
+
+        case MIME_CONTENT_TRANSFER_ENCODING:
+        case MIME_CONTENT_TYPE:
+        case MIME_MIME_VERSION:
+          if (flags & CH_MIME)
+            continue;
+          break;
+
+        case MIME_REFERENCES:
+          if (flags & CH_UPDATE_REFS)
+            continue;
+          break;
+
+        case MIME_IN_REPLY_TO:
+          if (flags & CH_UPDATE_IRT)
+            continue;
+          break;
+
+        default:
+          break;
+      }
+
       /* Find x -- the array entry where this header is to be saved */
       if (flags & CH_REORDER) {
         for (t = HeaderOrderList, x = 0; (t); t = t->next, x++) {
@@ -206,13 +236,15 @@ mutt_copy_hdr (FILE* in, FILE* out, off_t off_start, off_t off_end,
        * abbreviations (curline is 0), $max_display_recips is 0 and
        * while the number hasn't reached $max_display_recips yet */
       else if (curline == 0 || MaxDispRecips == 0 || ++curline <= MaxDispRecips) {
-        p_realloc(&this_one, m_strlen(this_one) + m_strlen(buf) + 1);
-        strcat (this_one, buf); /* __STRCAT_CHECKED__ */
+        this_one_len = m_strlen(this_one) + m_strlen(buf) + 1;
+        p_realloc(&this_one, this_one_len);
+        m_strcat(this_one, this_one_len, buf);
       /* only for the first line which doesn't exeeds
        * $max_display_recips: abbreviate it */
       } else if (curline == MaxDispRecips+1) {
-        p_realloc(&this_one, m_strlen(this_one) + 5);
-        strcat (this_one, " ...");
+        this_one_len = m_strlen(this_one) + 5;
+        p_realloc(&this_one, this_one_len);
+        m_strcat(this_one, this_one_len, " ...");
       }
     }
   }                             /* while (ftello (in) < off_end) */
@@ -227,8 +259,9 @@ mutt_copy_hdr (FILE* in, FILE* out, off_t off_start, off_t off_end,
     if (!headers[x])
       headers[x] = this_one;
     else {
-      p_realloc(&headers[x], m_strlen(headers[x]) + m_strlen(this_one) + 1);
-      strcat (headers[x], this_one);    /* __STRCAT_CHECKED__ */
+      headers_len = m_strlen(headers[x]) + m_strlen(this_one) + 1;
+      p_realloc(&headers[x], headers_len);
+      m_strcat(headers[x], headers_len, this_one);
       p_delete(&this_one);
     }
 
@@ -238,11 +271,6 @@ mutt_copy_hdr (FILE* in, FILE* out, off_t off_start, off_t off_end,
   /* Now output the headers in order */
   for (x = 0; x < hdr_count; x++) {
     if (headers[x]) {
-#if 0
-      if (flags & CH_DECODE)
-        rfc2047_decode (&headers[x]);
-#endif
-
       /* We couldn't do the prefixing when reading because RFC 2047
        * decoding may have concatenated lines.
        */
@@ -317,7 +345,7 @@ int
 mutt_copy_header (FILE * in, HEADER * h, FILE * out, int flags,
                   const char *prefix)
 {
-  char buffer[SHORT_STRING];
+  char buffer[STRING];
 
   if (h->env)
     flags |= (h->env->irt_changed ? CH_UPDATE_IRT : 0) |
@@ -328,12 +356,12 @@ mutt_copy_header (FILE * in, HEADER * h, FILE * out, int flags,
     return (-1);
 
   if (flags & CH_TXTPLAIN) {
-    char chsbuf[SHORT_STRING];
+    char chsbuf[STRING];
 
     fputs ("MIME-Version: 1.0\n", out);
     fputs ("Content-Transfer-Encoding: 8bit\n", out);
     fputs ("Content-Type: text/plain; charset=", out);
-    charset_canonicalize(chsbuf, sizeof (chsbuf), Charset);
+    charset_canonicalize(chsbuf, sizeof (chsbuf), mod_cset.charset);
     rfc822_strcpy(buffer, sizeof(buffer), chsbuf, MimeSpecials);
     fputs (buffer, out);
     fputc ('\n', out);
@@ -423,7 +451,7 @@ mutt_copy_header (FILE * in, HEADER * h, FILE * out, int flags,
   }
 
   if (flags & CH_UPDATE_LEN && (flags & CH_NOLEN) == 0) {
-    fprintf (out, "Content-Length: %lld\n", h->content->length);
+    fprintf (out, "Content-Length: %zu\n", h->content->length);
     if (h->lines != 0 || h->content->length == 0)
       fprintf (out, "Lines: %d\n", h->lines);
   }
@@ -493,7 +521,7 @@ int
 _mutt_copy_message (FILE * fpout, FILE * fpin, HEADER * hdr, BODY * body,
                     int flags, int chflags)
 {
-  char prefix[SHORT_STRING];
+  char prefix[STRING];
   STATE s;
   off_t new_offset = -1;
   int rc = 0;
@@ -513,7 +541,7 @@ _mutt_copy_message (FILE * fpout, FILE * fpin, HEADER * hdr, BODY * body,
     else if (hdr->attach_del && (chflags & CH_UPDATE_LEN)) {
       int new_lines;
       off_t new_length = body->length;
-      char date[SHORT_STRING];
+      char date[STRING];
 
       mutt_make_date (date, sizeof (date));
       date[5] = date[m_strlen(date) - 1] = '\"';
@@ -527,7 +555,7 @@ _mutt_copy_message (FILE * fpout, FILE * fpin, HEADER * hdr, BODY * body,
       if (mutt_copy_header (fpin, hdr, fpout,
                             chflags | CH_NOLEN | CH_NONEWLINE, NULL))
         return -1;
-      fprintf (fpout, "Content-Length: %lld\n", new_length);
+      fprintf (fpout, "Content-Length: %zu\n", new_length);
       if (new_lines <= 0)
         new_lines = 0;
       else
@@ -615,12 +643,12 @@ _mutt_copy_message (FILE * fpout, FILE * fpin, HEADER * hdr, BODY * body,
 
     fseeko (fp, cur->offset, 0);
     if (mutt_copy_bytes (fp, fpout, cur->length) == -1) {
-      fclose (fp);
+      m_fclose(&fp);
       body_list_wipe(&cur);
       return (-1);
     }
     body_list_wipe(&cur);
-    fclose (fp);
+    m_fclose(&fp);
   }
   else {
     fseeko (fpin, body->offset, 0);
@@ -657,12 +685,12 @@ mutt_copy_message (FILE * fpout, CONTEXT * src, HEADER * hdr, int flags,
   MESSAGE *msg;
   int r;
 
-  if ((msg = mx_open_message (src, hdr->msgno)) == NULL)
+  if (!(msg = mx_open_message (src, hdr->msgno)))
     return -1;
-  if ((r =
-       _mutt_copy_message (fpout, msg->fp, hdr, hdr->content, flags,
-                           chflags)) == 0 && (ferror (fpout)
-                                              || feof (fpout))) {
+
+  r = _mutt_copy_message(fpout, msg->fp, hdr, hdr->content, flags,
+                         chflags);
+  if (!r && (ferror(fpout) || feof (fpout))) {
     r = -1;
   }
   mx_close_message (&msg);
@@ -692,7 +720,7 @@ _mutt_append_message (CONTEXT * dest, FILE * fpin, CONTEXT * src __attribute__ (
     return (-1);
   if ((msg = mx_open_new_message (dest, hdr, is_from (buf, NULL, 0, NULL) ? 0 : M_ADD_FROM)) == NULL)
     return (-1);
-  if (dest->magic == M_MBOX || dest->magic == M_MMDF)
+  if (dest->magic == M_MBOX)
     chflags |= CH_FROM | CH_FORCE_FROM;
   chflags |= (dest->magic == M_MAILDIR ? CH_NOSTATUS : CH_UPDATE);
   r = _mutt_copy_message (msg->fp, fpin, hdr, body, flags, chflags);
@@ -740,7 +768,7 @@ static int copy_delete_attach (BODY * b, FILE * fpin, FILE * fpout,
       if (part->deleted) {
         fprintf (fpout,
                  "Content-Type: message/external-body; access-type=x-mutt-deleted;\n"
-                 "\texpiration=%s; length=%lld\n"
+                 "\texpiration=%s; length=%zu\n"
                  "\n", date + 5, part->length);
         if (ferror (fpout))
           return -1;
@@ -793,17 +821,17 @@ static void format_address_header (char **h, address_t * a)
 
     a->next = NULL;
     *buf = *cbuf = *c2buf = '\0';
-    rfc822_write_address (buf, sizeof (buf), a, 0);
+    rfc822_addrcat(buf, sizeof (buf), a, 0);
     a->next = tmp;
 
     l = m_strlen(buf);
     if (count && linelen + l > 74) {
-      strcpy (cbuf, "\n\t");    /* __STRCPY_CHECKED__ */
+      m_strcpy(cbuf, sizeof(cbuf), "\n\t");
       linelen = l + 8;
     }
     else {
       if (a->mailbox) {
-        strcpy (cbuf, " ");     /* __STRCPY_CHECKED__ */
+        m_strcpy(cbuf, sizeof(cbuf), " ");
         linelen++;
       }
       linelen += l;
@@ -811,99 +839,56 @@ static void format_address_header (char **h, address_t * a)
     if (!a->group && a->next && a->next->mailbox) {
       linelen++;
       buflen++;
-      strcpy (c2buf, ",");      /* __STRCPY_CHECKED__ */
+      m_strcpy(c2buf, sizeof(c2buf), ",");
     }
 
     buflen += l + m_strlen(cbuf) + m_strlen(c2buf);
     p_realloc(h, buflen);
-    strcat (*h, cbuf);          /* __STRCAT_CHECKED__ */
-    strcat (*h, buf);           /* __STRCAT_CHECKED__ */
-    strcat (*h, c2buf);         /* __STRCAT_CHECKED__ */
+    m_strcat(*h, buflen, cbuf);
+    m_strcat(*h, buflen, buf);
+    m_strcat(*h, buflen, c2buf);
   }
 
   /* Space for this was allocated in the beginning of this function. */
-  strcat (*h, "\n");            /* __STRCAT_CHECKED__ */
+  m_strcat(*h, buflen, "\n");
 }
 
-static int address_header_decode (char **h)
+static int address_header_decode(char **h)
 {
-  char *s = *h;
-  int l;
+    address_t *a;
+    char *p, *s = *h;
 
-  address_t *a = NULL;
+    p = strchr(s, ':');
+    if (!p)
+        return 0;
 
-  switch (tolower ((unsigned char) *s)) {
-  case 'r':
-    {
-      if (ascii_strncasecmp (s, "return-path:", 12) == 0) {
-        l = 12;
+    switch (mime_which_token(s, p - s)) {
+      case MIME_RETURN_PATH:
+      case MIME_REPLY_TO:
+      case MIME_FROM:
+      case MIME_CC:
+      case MIME_BCC:
+      case MIME_SENDER:
+      case MIME_TO:
+      case MIME_MAIL_FOLLOWUP_TO:
+        p++;
         break;
-      }
-      else if (ascii_strncasecmp (s, "reply-to:", 9) == 0) {
-        l = 9;
-        break;
-      }
-      return 0;
-    }
-  case 'f':
-    {
-      if (ascii_strncasecmp (s, "from:", 5))
-        return 0;
-      l = 5;
-      break;
-    }
-  case 'c':
-    {
-      if (ascii_strncasecmp (s, "cc:", 3))
-        return 0;
-      l = 3;
-      break;
 
-    }
-  case 'b':
-    {
-      if (ascii_strncasecmp (s, "bcc:", 4))
-        return 0;
-      l = 4;
-      break;
-    }
-  case 's':
-    {
-      if (ascii_strncasecmp (s, "sender:", 7))
-        return 0;
-      l = 7;
-      break;
-    }
-  case 't':
-    {
-      if (ascii_strncasecmp (s, "to:", 3))
-        return 0;
-      l = 3;
-      break;
-    }
-  case 'm':
-    {
-      if (ascii_strncasecmp (s, "mail-followup-to:", 17))
+      default:
         return 0;
-      l = 17;
-      break;
     }
-  default:
-    return 0;
-  }
 
-  if ((a = rfc822_parse_adrlist (a, s + l)) == NULL)
-    return 0;
-
-  mutt_addrlist_to_local (a);
-  rfc2047_decode_adrlist (a);
-
-  *h = p_dupstr(s, l + 1);
+    a = rfc822_parse_adrlist(NULL, p);
+    if (!a)
+        return 0;
 
-  format_address_header (h, a);
+    mutt_addrlist_to_local(a);
+    rfc2047_decode_adrlist(a);
 
-  address_list_wipe(&a);
+    *h = p_dupstr(s, p - s);
+    format_address_header(h, a);
+    address_list_wipe(&a);
 
-  p_delete(&s);
-  return 1;
+    p_delete(&s);
+    return 1;
 }