nmh-workers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Nmh-workers] mhshow: invalid QUOTED-PRINTABLE encoding


From: Paul Fox
Subject: Re: [Nmh-workers] mhshow: invalid QUOTED-PRINTABLE encoding
Date: Tue, 28 Mar 2006 11:35:15 -0500

i wrote:
 > i really really wouldn't care if mh applied multiple hex
 > encodings with shrieking warnings to the several characters
 > surrounding the mis-encoded ones, if it would only show me the
 > _rest_ of the message intact.  i guess i'll go look at how hard
 > this might be.

well, i've sort of made it do just that.  it's not perfect, but
at least i get to see my mail now.

with this patch applied, if quoted-printable parse error occurs,
the offending character(s) will be left undecoded, and displayd,
inline, with a sequence that looks like "[QPerr(X)]" X is either
the ascii value of the character or its hex rendition, if the
char is non-printable.  the "mhshow:  invalid QUOTED-PRINTABLE
encoding" error message will still come out, albeit after the
message has been shown.

now, i've seen enough of the mh source to know that i probably
missed several side-effects and edge conditions, and i've been on
this list long enough to know that at least three of you will
point out backward or forward incompatibility problems with this
change.  i'm ready -- i can take it.  i'll try and fix what's
broken, or bow to greater wisdom and do something else entirely.

btw, i was somewhat surprised to find not one, not two, but three
separate qp-decoders in the nmh source.  i modified mhparse.c,
mhbuildsbr.c has its own copy (only slightly modified) and
there's a very different version in fmt_rfc2047.c.

paul
=---------------------
 paul fox, address@hidden (arlington, ma, where it's 50.7 degrees)


--- mhparse.c.orig      Mon Mar 27 21:51:04 2006
+++ mhparse.c   Tue Mar 28 11:24:47 2006
@@ -1775,11 +1775,20 @@
     return init_encoding (ct, openQuoted);
 }
 
+static int
+errputc(char c, FILE *fp)
+{
+    if (c < '!' || c > '~')
+       fprintf(fp, "[QPerr(%02x)]", c);
+    else
+       fprintf(fp, "[QPerr('%c')]", c);
+    return ferror (fp);
+}
 
 static int
 openQuoted (CT ct, char **file)
 {
-    int        cc, digested, len, quoted;
+    int        cc, digested, len, quoted, invalid_hex, range_error;
     char *cp, *ep;
     char buffer[BUFSIZ];
     unsigned char mask;
@@ -1845,13 +1854,14 @@
        MD5Init (&mdContext);
 
     quoted = 0;
+    invalid_hex = 0;
+    range_error = 0;
 #ifdef lint
     mask = 0;
 #endif
 
     fseek (ct->c_fp, ct->c_begin, SEEK_SET);
     while (len > 0) {
-       char *dp;
 
        if (fgets (buffer, sizeof(buffer) - 1, ct->c_fp) == NULL) {
            content_error (NULL, ct, "premature eof");
@@ -1871,9 +1881,12 @@
            if (quoted) {
                if (quoted > 1) {
                    if (!isxdigit (*cp)) {
-invalid_hex:
-                       dp = "expecting hexidecimal-digit";
-                       goto invalid_encoding;
+                       if (errputc(*cp, ce->ce_fp))
+                           goto ferror_out;
+
+                       invalid_hex = 1;
+                       quoted = 0;
+                       continue;
                    }
                    mask <<= 4;
                    mask |= hex2nib[*cp & 0x7f];
@@ -1889,18 +1902,22 @@
                        break;
 
                    default:
-                       if (!isxdigit (*cp))
-                           goto invalid_hex;
-                       mask = hex2nib[*cp & 0x7f];
                        quoted = 2;
+                       if (!isxdigit (*cp)) {
+                           putc('=', ce->ce_fp);
+                           if (errputc(*cp, ce->ce_fp))
+                               goto ferror_out;
+                           invalid_hex = 1;
+                           continue;
+                       }
+                       mask = hex2nib[*cp & 0x7f];
                        continue;
                    }
                }
 
-               if (ferror (ce->ce_fp)) {
-                   content_error (ce->ce_file, ct, "error writing to");
-                   goto clean_up;
-               }
+               if (ferror (ce->ce_fp))
+                   goto ferror_out;
+
                quoted = 0;
                continue;
            }
@@ -1908,15 +1925,11 @@
            switch (*cp) {
            default:
                if (*cp < '!' || *cp > '~') {
-                   int i;
-                   dp = "expecting character in range [!..~]";
+                   if (errputc(*cp, ce->ce_fp))
+                       goto ferror_out;
 
-invalid_encoding:
-                   i = strlen (invo_name) + 2;
-                   content_error (NULL, ct,
-                                  "invalid QUOTED-PRINTABLE encoding -- 
%s,\n%*.*sbut got char 0x%x",
-                                  dp, i, i, "", *cp);
-                   goto clean_up;
+                   range_error = 1;
+                   break;
                }
                /* and fall...*/
            case ' ':
@@ -1929,10 +1942,9 @@
                    else
                        MD5Update (&mdContext, (unsigned char *) cp, 1);
                }
-               if (ferror (ce->ce_fp)) {
-                   content_error (ce->ce_file, ct, "error writing to");
-                   goto clean_up;
-               }
+               if (ferror (ce->ce_fp))
+                   goto ferror_out;
+
                break;
 
            case '=':
@@ -1947,15 +1959,20 @@
     if (quoted) {
        content_error (NULL, ct,
                       "invalid QUOTED-PRINTABLE encoding -- end-of-content 
while still quoting");
-       goto clean_up;
+    }
+    if (invalid_hex) {
+       content_error (NULL, ct,
+                      "invalid QUOTED-PRINTABLE encoding -- invalid hex digit 
in encoding");
+    }
+    if (range_error) {
+       content_error (NULL, ct,
+                      "invalid QUOTED-PRINTABLE encoding -- found char out of 
range [!..~]");
     }
 
     fseek (ct->c_fp, 0L, SEEK_SET);
 
-    if (fflush (ce->ce_fp)) {
-       content_error (ce->ce_file, ct, "error writing to");
-       goto clean_up;
-    }
+    if (fflush (ce->ce_fp))
+       goto ferror_out;
 
     if (digested) {
        unsigned char digest[16];
@@ -1976,6 +1993,9 @@
     *file = ce->ce_file;
     return fileno (ce->ce_fp);
 
+ferror_out:
+    content_error (ce->ce_file, ct, "error writing to");
+
 clean_up:
     free_encoding (ct, 0);
     return NOTOK;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]