]> granicus.if.org Git - mutt/commitdiff
Convert rfc2047_decode() to use buffers.
authorKevin McCarthy <kevin@8t8.us>
Sun, 25 Nov 2018 05:03:26 +0000 (21:03 -0800)
committerKevin McCarthy <kevin@8t8.us>
Mon, 3 Dec 2018 22:34:11 +0000 (14:34 -0800)
Rework the loop so it's centered on the find_encoded_word() call.

It appears only the last text chunk was run through character
conversion with AssumedCharset.  I've changed it to run for each text
chunk.

rfc2047.c

index 8506425450c1ad197b2f87cbd98f67942b0f5630..5c3574aaf50a0b3d90eb9e0a1c96f301fac07ac1 100644 (file)
--- a/rfc2047.c
+++ b/rfc2047.c
@@ -623,7 +623,7 @@ void rfc2047_encode_adrlist (ADDRESS *addr, const char *tag)
   }
 }
 
-static int rfc2047_decode_word (char *d, const char *s, size_t len)
+static int rfc2047_decode_word (BUFFER *d, const char *s)
 {
   const char *pp, *pp1;
   char *pd, *d0;
@@ -714,7 +714,7 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len)
   if (charset)
     mutt_convert_string (&d0, charset, Charset, MUTT_ICONV_HOOK_FROM);
   mutt_filter_unprintable (&d0);
-  strfcpy (d, d0, len);
+  mutt_buffer_addstr (d, d0);
   rv = 0;
 error_out_0:
   FREE (&charset);
@@ -798,110 +798,99 @@ static size_t lwsrlen (const char *s, size_t n)
   return len;
 }
 
+static void convert_and_add_text (BUFFER *d, const char *text, size_t len)
+{
+  char *t;
+
+  if (AssumedCharset && *AssumedCharset)
+  {
+    t = safe_malloc (len + 1);
+    strfcpy (t, text, len + 1);
+    convert_nonmime_string (&t);
+    mutt_buffer_addstr (d, t);
+    FREE (&t);
+  }
+  else
+    mutt_buffer_addstr_n (d, text, len);
+}
+
 /* try to decode anything that looks like a valid RFC2047 encoded
  * header field, ignoring RFC822 parsing rules
  */
 void rfc2047_decode (char **pd)
 {
-  const char *p, *q;
+  const char *s = *pd;
+  const char *word_begin, *word_end;
   size_t m, n;
   int found_encoded = 0;
-  char *d0, *d;
-  const char *s = *pd;
-  size_t dlen;
+  BUFFER *d;
 
   if (!s || !*s)
     return;
 
-  dlen = 4 * strlen (s); /* should be enough */
-  d = d0 = safe_malloc (dlen + 1);
+  dprint (1, (debugfile, "rfcdecode on *%s*\n", s));
+
+  d = mutt_buffer_pool_get ();
 
-  while (*s && dlen > 0)
+  while ((word_begin = find_encoded_word (s, &word_end)) != NULL)
   {
-    if (!(p = find_encoded_word (s, &q)))
+    /* If there is text before the encoded word */
+    if (word_begin != s)
     {
-      /* no encoded words */
-      if (option (OPTIGNORELWS))
-      {
-        n = mutt_strlen (s);
-        if (found_encoded && (m = lwslen (s, n)) != 0)
-        {
-          if (m != n)
-            *d = ' ', d++, dlen--;
-          s += m;
-        }
-      }
-      if (AssumedCharset && *AssumedCharset)
-      {
-       char *t;
-       size_t tlen;
-
-       n = mutt_strlen (s);
-       t = safe_malloc (n + 1);
-       strfcpy (t, s, n + 1);
-       convert_nonmime_string (&t);
-       tlen = mutt_strlen (t);
-       strncpy (d, t, tlen);
-       d += tlen;
-       FREE (&t);
-       break;
-      }
-      strncpy (d, s, dlen);
-      d += dlen;
-      break;
-    }
+      n = (size_t) (word_begin - s);
 
-    if (p != s)
-    {
-      n = (size_t) (p - s);
-      /* ignore spaces between encoded word
-       * and linear-white-space between encoded word and *text */
       if (option (OPTIGNORELWS))
       {
         if (found_encoded && (m = lwslen (s, n)) != 0)
         {
           if (m != n)
-            *d = ' ', d++, dlen--;
+            mutt_buffer_addch (d, ' ');
           n -= m, s += m;
         }
 
         if ((m = n - lwsrlen (s, n)) != 0)
         {
-          if (m > dlen)
-            m = dlen;
-          memcpy (d, s, m);
-          d += m;
-          dlen -= m;
+          convert_and_add_text (d, s, m);
           if (m != n)
-            *d = ' ', d++, dlen--;
+            mutt_buffer_addch (d, ' ');
         }
       }
+      /* If we haven't encountered an encoded word yet copy it all
+       * over.
+       *
+       * If we just finished an encoded word and the text is all
+       * spaces, we skip the spaces.
+       */
       else if (!found_encoded || strspn (s, " \t\r\n") != n)
-      {
-       if (n > dlen)
-         n = dlen;
-       memcpy (d, s, n);
-       d += n;
-       dlen -= n;
-      }
+        convert_and_add_text (d, s, n);
     }
 
-    if (rfc2047_decode_word (d, p, dlen) == -1)
+    if (rfc2047_decode_word (d, word_begin) == -1)
     {
       /* could not decode word, fall back to displaying the raw string */
-      strfcpy(d, p, dlen);
+      mutt_buffer_addstr (d, word_begin);
     }
     found_encoded = 1;
-    s = q;
-    n = mutt_strlen (d);
-    dlen -= n;
-    d += n;
+    s = word_end;
   }
-  *d = 0;
 
-  FREE (pd);           /* __FREE_CHECKED__ */
-  *pd = d0;
-  mutt_str_adjust (pd);
+  if (*s)
+  {
+    if (found_encoded && option (OPTIGNORELWS))
+    {
+      n = mutt_strlen (s);
+      if ((m = lwslen (s, n)) != 0)
+      {
+        if (m != n)
+          mutt_buffer_addch (d, ' ');
+        s += m;
+      }
+    }
+    convert_and_add_text (d, s, mutt_strlen (s));
+  }
+
+  mutt_str_replace (pd, mutt_b2s (d));
+  mutt_buffer_pool_release (&d);
 }
 
 void rfc2047_decode_adrlist (ADDRESS *a)