]> diplodocus.org Git - nmh/commitdiff
Fix base64 to handle text parts properly; currently this breaks mhfixmsg,
authorKen Hornstein <kenh@pobox.com>
Fri, 31 Jan 2014 20:53:04 +0000 (15:53 -0500)
committerKen Hornstein <kenh@pobox.com>
Fri, 31 Jan 2014 20:53:04 +0000 (15:53 -0500)
and I'm not sure why yet.

h/prototypes.h
sbr/base64.c
uip/mhoutsbr.c
uip/mhparse.c
uip/viamail.c

index 563a0d5df2c12839fcc406f6ef85958ddd43737a..e8be9fe63467247f2c68c023927046f6ca260032 100644 (file)
@@ -362,7 +362,20 @@ int SOprintf (char *, ...);
 int what_now (char *, int, int, char *, char *,
        int, struct msgs *, char *, int, char *, int);
 int WhatNow(int, char **);
-int writeBase64aux(FILE *, FILE *);
+
+/*
+ * Copy data from one file to another, converting to base64-encoding.
+ *
+ * Arguments include:
+ *
+ * in          - Input filehandle (unencoded data)
+ * out         - Output filename (base64-encoded data)
+ * crlf                - If set, output encoded CRLF for every LF on input.
+ *
+ * Returns OK on success, NOTOK otherwise.
+ */
+int writeBase64aux(FILE *in, FILE *out, int crlf);
+
 int writeBase64 (unsigned char *, size_t, unsigned char *);
 int writeBase64raw (unsigned char *, size_t, unsigned char *);
 
index 5ff9f53c4f91bdea08fdd868d74e8d588d9c0f6b..6682c3f34f984f974a223c90936320321f6fa101 100644 (file)
@@ -13,10 +13,10 @@ static char nib2b64[0x40+1] =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 int
-writeBase64aux (FILE *in, FILE *out)
+writeBase64aux (FILE *in, FILE *out, int crlf)
 {
     unsigned int cc, n;
-    char inbuf[3];
+    unsigned char inbuf[3];
 
     n = BPERLIN;
     while ((cc = fread (inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) {
@@ -29,6 +29,36 @@ writeBase64aux (FILE *in, FILE *out)
            if (cc < sizeof(inbuf) - 1)
                inbuf[1] = 0;
        }
+
+       /*
+        * Convert a LF to a CRLF if desired.  That means we need to push
+        * data back into the input stream.
+        */
+
+       if (crlf) {
+           unsigned int i;
+
+           for (i = 0; i < cc; i++) {
+               if (inbuf[i] == '\n') {
+                   inbuf[i] = '\r';
+                   /*
+                    * If it's the last character in the buffer, we can just
+                    * substitute a \r and push a \n back.  Otherwise shuffle
+                    * everything down and push the last character back.
+                    */
+                   if (i == cc - 1) {
+                       ungetc('\n', in);
+                   } else {
+                       /* This only works as long as sizeof(inbuf) == 3 */
+                       ungetc(inbuf[cc - 1], in);
+                       if (cc == 3 && i == 0)
+                           inbuf[2] = inbuf[1];
+                       inbuf[++i] = '\n';
+                   }
+               }
+           }
+       }
+
        bits = (inbuf[0] & 0xff) << 16;
        bits |= (inbuf[1] & 0xff) << 8;
        bits |= inbuf[2] & 0xff;
index df23047e6282bc613ca286235c5a7cfc75a01617..9584d78955fc8bc6785096358ea5c5f1efda73f1 100644 (file)
@@ -404,7 +404,7 @@ writeBase64ct (CT ct, FILE *out)
     if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
        return NOTOK;
 
-    result = writeBase64aux (ce->ce_fp, out);
+    result = writeBase64aux (ce->ce_fp, out, (ct->c_type == CT_TEXT));
     (*ct->c_ceclosefnx) (ct);
     return result;
 }
index 371d0c926567e084418a74dcea4dfd1a40886778..d12fbb30f5e394413ef052c55d4f677edfcaa87c 100644 (file)
@@ -1677,7 +1677,7 @@ static int
 openBase64 (CT ct, char **file)
 {
     int        bitno, cc, digested;
-    int fd, len, skip, own_ct_fp = 0;
+    int fd, len, skip, own_ct_fp = 0, text = ct->c_type == CT_TEXT;
     uint32_t bits;
     unsigned char value, b;
     char *cp, *ep, buffer[BUFSIZ];
@@ -1789,17 +1789,20 @@ openBase64 (CT ct, char **file)
 test_end:
                    if ((bitno -= 6) < 0) {
                        b = (bits >> 16) & 0xff;
-                       putc ((char) b, ce->ce_fp);
+                       if (!text || b != '\r')
+                           putc ((char) b, ce->ce_fp);
                        if (digested)
                            MD5Update (&mdContext, &b, 1);
                        if (skip < 2) {
                            b = (bits >> 8) & 0xff;
-                           putc ((char) b, ce->ce_fp);
+                           if (! text || b != '\r')
+                               putc ((char) b, ce->ce_fp);
                            if (digested)
                                MD5Update (&mdContext, &b, 1);
                            if (skip < 1) {
                                b = bits & 0xff;
-                               putc ((char) b, ce->ce_fp);
+                               if (! text || b != '\r')
+                                   putc ((char) b, ce->ce_fp);
                                if (digested)
                                    MD5Update (&mdContext, &b, 1);
                            }
index 97dee86bf3cfb8ab19d448e0e80e95c1050cd3c4..0ff765c4273d84b334c245f1c55a0058a7647aec 100644 (file)
@@ -190,7 +190,7 @@ via_mail (char *mailsw, char *subjsw, char *parmsw, char *descsw,
     if (fflush (fp))
        adios (tmpfil, "error writing to");
 
-    writeBase64aux (stdin, fp);
+    writeBase64aux (stdin, fp, 0);
     if (fflush (fp))
        adios (tmpfil, "error writing to");