<<< Date Index >>>     <<< Thread Index >>>

Re: RFC 2047 encoder botched?



On 2007-06-08 15:09:51 +0000, Rocco Rutte wrote:

> A dirty fix was to change 'break' in that function to 'continue', but now 
> the subject header for your example gets quite long (2 lines compared to 
> 3)... but I don't know if that's what header wrapping was all about.

So...  This was a combination of several corner cases.

What basically happened was that, if we wrap a header, and respect
an existing line break, we actually eat up all the leading
whitespace of the new line toward the end of the while loop.
Therefore, the for loop never got to see that whitespace, and never
detected the beginning of an encoded-word if that was in the
beginning of a new line.

The easiest way around is to keep a copy of the last character that
we looked at around, and trigger the encoded word check on that.

The attachd changeset should fix the problem.  (At least it does for
my test case.)

-- 
Thomas Roessler   <roessler@xxxxxxxxxxxxxxxxxx>





# HG changeset patch
# User Thomas Roessler <roessler@xxxxxxxxxxxxxxxxxx>
# Date 1181342846 -7200
# Node ID 5fba5131a8ad868bc190007fef9a19b19f6d9421
# Parent  9e90789518ad2a6bef64610ce39801c93afca255
Fix header encoding corner case.

diff -r 9e90789518ad -r 5fba5131a8ad sendlib.c
--- a/sendlib.c Tue Jun 05 13:12:05 2007 -0700
+++ b/sendlib.c Sat Jun 09 00:47:26 2007 +0200
@@ -1566,7 +1566,8 @@ int mutt_write_one_header (FILE *fp, con
   int i, k, n;
   const char *cp;
   char buf [HUGE_STRING];
-  wchar_t w;
+  wchar_t w = (wchar_t) -1;
+  wchar_t last = (wchar_t) '\n';
   int l = 0;
   int first = 1;
   int wrapped = 0;
@@ -1606,9 +1607,11 @@ int mutt_write_one_header (FILE *fp, con
     }
 
     if (first)
+    {
+      last = '\n';
       wrapped = 0;
-    
-    first = 0;
+      first = 0;
+    }
 
     /*
      * i is our running pointer, and always points to the *beginning* of an mb 
character.
@@ -1619,9 +1622,26 @@ int mutt_write_one_header (FILE *fp, con
      */
     
     for (i = 0, k = 0, l = 0, n = 0; i + MB_CUR_MAX < sizeof (buf)
-           && cp[i] != '\0' && ((col < wraplen || in_encoded_word));
-        i += l)
-    {
+           && cp[i] != '\0' && (col < wraplen || in_encoded_word);
+        i += l, last = w)
+    {
+
+      if (i == 0) 
+      {
+       dprint (1, (debugfile, "WRITEONE cp: %s\n", cp));
+       dprint (1, (debugfile, "WRITEONE w:  %x\n", (unsigned int) w));
+       dprint (1, (debugfile, "WRITEONE iswspace (w) = %d\n", iswspace (w)));
+      }
+      
+      /* Brief look at the last character we had... */
+      if (iswspace (last))
+      {
+       /* ... and if the next thing is an encoded word ... */
+       if (strncmp (&cp[i], "=?", 2) == 0)
+         in_encoded_word = 1;
+       else
+         in_encoded_word = 0;
+      }
       
       /* If there is a line break in the header, honor it. */
       if (cp[i] == '\n')
@@ -1636,6 +1656,7 @@ int mutt_write_one_header (FILE *fp, con
          k = i;
          n = k + 1;
          l = 1;
+         w = (wchar_t) '\n';
          break;
        }
       }
@@ -1646,19 +1667,12 @@ int mutt_write_one_header (FILE *fp, con
       {
        dprint (1, (debugfile, "mutt_write_one_header: encoutered bad 
multi-byte character at %d.\n", i));
        l = 1; /* if bad, move on by one character */
+       w = (wchar_t) -1;
       }
       else 
       {
        if (wcwidth (w) >= 0)
          col += wcwidth (w);
-
-       if (iswspace (w))
-       {
-         if (strncmp (&cp[i+l], "=?", 2) == 0)
-           in_encoded_word = 1;
-         else
-           in_encoded_word = 0;
-       }
 
        if (iswspace (w) && 
            (!k || col <= wraplen))
@@ -1698,6 +1712,7 @@ int mutt_write_one_header (FILE *fp, con
 
     while (*cp)
     {
+      last = w;
       if ((l = mbtowc (&w, cp, MB_CUR_MAX)) > 0 && iswspace (w))
        cp += l;
       else