X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/df6971a59e8d01dcfe605bbac949b7d4b3ab0a92..ef1ba39e8dae81091b6c3e73e72825ef6edea3c6:/uip/mhoutsbr.c diff --git a/uip/mhoutsbr.c b/uip/mhoutsbr.c index 8324991d..89b4b932 100644 --- a/uip/mhoutsbr.c +++ b/uip/mhoutsbr.c @@ -10,56 +10,13 @@ #include #include -#include #include -#include -#include #include #include #include #include -extern int ebcdicsw; - -static char ebcdicsafe[0x100] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static char nib2b64[0x40+1] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - /* * prototypes */ @@ -74,7 +31,7 @@ static void output_headers (CT, FILE *); static int writeExternalBody (CT, FILE *); static int write8Bit (CT, FILE *); static int writeQuoted (CT, FILE *); -static int writeBase64 (CT, FILE *); +static int writeBase64ct (CT, FILE *); /* @@ -102,12 +59,14 @@ output_message (CT ct, char *file) FILE *fp; int status; - if ((fp = fopen (file, "w")) == NULL) { + if (! strcmp (file, "-")) { + fp = stdout; + } else if ((fp = fopen (file, "w")) == NULL) { advise (file, "unable to open for writing"); return NOTOK; } status = output_message_fp(ct, fp, file); - fclose(fp); + if (strcmp (file, "-")) fclose(fp); return status; } @@ -121,6 +80,10 @@ output_content (CT ct, FILE *out) { int result = 0; CI ci = &ct->c_ctinfo; + char *boundary = "", *cp; + + if ((cp = get_param(ci->ci_first_pm, "boundary", '-', 0))) + boundary = cp; /* * Output all header fields for this content @@ -132,8 +95,11 @@ output_content (CT ct, FILE *out) * "message/external", then we are done with the * headers (since it has no body). */ - if (ct->c_ctexbody) + if (ct->c_ctexbody) { + if (*boundary != '\0') + free(boundary); return OK; + } /* * Now output the content bodies. @@ -148,14 +114,26 @@ output_content (CT ct, FILE *out) putc ('\n', out); m = (struct multipart *) ct->c_ctparams; + + if (m->mp_content_before) { + fprintf (out, "%s", m->mp_content_before); + } + for (part = m->mp_parts; part; part = part->mp_next) { CT p = part->mp_part; - fprintf (out, "\n--%s\n", ci->ci_values[0]); - if (output_content (p, out) == NOTOK) - return NOTOK; + fprintf (out, "\n--%s\n", boundary); + if (output_content (p, out) == NOTOK) { + if (*boundary != '\0') + free(boundary); + return NOTOK; + } } - fprintf (out, "\n--%s--\n", ci->ci_values[0]); + fprintf (out, "\n--%s--\n", boundary); + + if (m->mp_content_after) { + fprintf (out, "%s", m->mp_content_after); + } } break; @@ -182,7 +160,14 @@ output_content (CT ct, FILE *out) default: switch (ct->c_encoding) { case CE_7BIT: - putc ('\n', out); + /* Special case: if this is a non-MIME message with no + body, don't emit the newline that would appear between + the headers and body. In that case, the call to + write8Bit() shouldn't be needed, but is harmless. */ + if (ct->c_ctinfo.ci_first_pm != NULL || ct->c_begin == 0 || + ct->c_begin != ct->c_end) { + putc ('\n', out); + } result = write8Bit (ct, out); break; @@ -198,12 +183,18 @@ output_content (CT ct, FILE *out) case CE_BASE64: putc ('\n', out); - result = writeBase64 (ct, out); + result = writeBase64ct (ct, out); break; case CE_BINARY: - advise (NULL, "can't handle binary transfer encoding in content"); - result = NOTOK; + if (ct->c_type == CT_TEXT) { + /* So that mhfixmsg can decode to binary text. */ + putc ('\n', out); + result = write8Bit (ct, out); + } else { + advise (NULL, "can't handle binary transfer encoding in content"); + result = NOTOK; + } break; default: @@ -214,6 +205,9 @@ output_content (CT ct, FILE *out) break; } + if (*boundary != '\0') + free(boundary); + return result; } @@ -242,7 +236,7 @@ output_headers (CT ct, FILE *out) static int writeExternalBody (CT ct, FILE *out) { - char **ap, **ep, *cp; + char *cp, *dp; struct exbody *e = (struct exbody *) ct->c_ctparams; putc ('\n', out); @@ -254,7 +248,7 @@ writeExternalBody (CT ct, FILE *out) switch (*++cp) { case 'I': if (ct2->c_id) { - char *dp = trimcpy (ct2->c_id); + dp = trimcpy (ct2->c_id); fputs (dp, out); free (dp); @@ -262,17 +256,22 @@ writeExternalBody (CT ct, FILE *out) continue; case 'N': - for (ap = ci2->ci_attrs, ep = ci2->ci_values; *ap; ap++, ep++) - if (!mh_strcasecmp (*ap, "name")) { - fprintf (out, "%s", *ep); - break; - } + dp = get_param(ci2->ci_first_pm, "name", '_', 0); + if (dp) { + fputs (dp, out); + free (dp); + } continue; case 'T': fprintf (out, "%s/%s", ci2->ci_type, ci2->ci_subtype); - for (ap = ci2->ci_attrs, ep = ci2->ci_values; *ap; ap++, ep++) - fprintf (out, "; %s=\"%s\"", *ap, *ep); + dp = output_params(strlen(ci2->ci_type) + + strlen(ci2->ci_subtype) + 1, + ci2->ci_first_pm, NULL, 0); + if (dp) { + fputs (dp, out); + free (dp); + } continue; case 'n': @@ -312,17 +311,20 @@ static int write8Bit (CT ct, FILE *out) { int fd; + size_t inbytes; char c, *file, buffer[BUFSIZ]; - CE ce = ct->c_cefile; + CE ce = &ct->c_cefile; file = NULL; if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK) return NOTOK; c = '\n'; - while (fgets (buffer, sizeof(buffer) - 1, ce->ce_fp)) { - c = buffer[strlen (buffer) - 1]; - fputs (buffer, out); + while ((inbytes = fread (buffer, 1, sizeof buffer, ce->ce_fp)) > 0) { + c = buffer[inbytes - 1]; + if (fwrite (buffer, 1, inbytes, out) < inbytes) { + advise ("write8Bit", "fwrite"); + } } if (c != '\n') putc ('\n', out); @@ -341,27 +343,35 @@ writeQuoted (CT ct, FILE *out) { int fd; char *cp, *file; - char c, buffer[BUFSIZ]; - CE ce = ct->c_cefile; + char c = '\0'; + CE ce = &ct->c_cefile; + int n = 0; + char *bufp = NULL; + size_t buflen; + ssize_t gotlen; file = NULL; if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK) return NOTOK; - while (fgets (buffer, sizeof(buffer) - 1, ce->ce_fp)) { - int n; + while ((gotlen = getline(&bufp, &buflen, ce->ce_fp)) != -1) { - cp = buffer + strlen (buffer) - 1; + cp = bufp + gotlen - 1; if ((c = *cp) == '\n') - *cp = '\0'; - - if (strncmp (cp = buffer, "From ", sizeof("From ") - 1) == 0) { - fprintf (out, "=%02X", *cp++ & 0xff); - n = 3; - } else { - n = 0; + gotlen--; + + /* + * if the line starts with "From ", encode the 'F' so it + * doesn't falsely match an mbox delimiter. + */ + cp = bufp; + if (gotlen >= 5 && strncmp (cp, "From ", 5) == 0) { + fprintf (out, "=%02X", 'F'); + cp++; + n += 3; } - for (; *cp; cp++) { + + for (; cp < bufp + gotlen; cp++) { if (n > CPERLIN - 3) { fputs ("=\n", out); n = 0; @@ -375,8 +385,7 @@ writeQuoted (CT ct, FILE *out) break; default: - if (*cp < '!' || *cp > '~' - || (ebcdicsw && !ebcdicsafe[*cp & 0xff])) + if (*cp < '!' || *cp > '~') goto three_print; putc (*cp, out); n++; @@ -391,16 +400,19 @@ three_print: } if (c == '\n') { - if (cp > buffer && (*--cp == ' ' || *cp == '\t')) + if (cp > bufp && (*--cp == ' ' || *cp == '\t')) fputs ("=\n", out); putc ('\n', out); - } else { - fputs ("=\n", out); + n = 0; } } + if (c != '\n') + putc ('\n', out); + (*ct->c_ceclosefnx) (ct); + free (bufp); return OK; } @@ -410,65 +422,20 @@ three_print: */ static int -writeBase64 (CT ct, FILE *out) +writeBase64ct (CT ct, FILE *out) { int fd, result; char *file; - CE ce = ct->c_cefile; + CE ce = &ct->c_cefile; file = NULL; 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_ctparams + ? ((struct text *) ct->c_ctparams)->lf_line_endings == 0 + : 0); (*ct->c_ceclosefnx) (ct); return result; } - - -int -writeBase64aux (FILE *in, FILE *out) -{ - unsigned int cc, n; - char inbuf[3]; - - n = BPERLIN; - while ((cc = fread (inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) { - unsigned long bits; - char *bp; - char outbuf[4]; - - if (cc < sizeof(inbuf)) { - inbuf[2] = 0; - if (cc < sizeof(inbuf) - 1) - inbuf[1] = 0; - } - bits = (inbuf[0] & 0xff) << 16; - bits |= (inbuf[1] & 0xff) << 8; - bits |= inbuf[2] & 0xff; - - for (bp = outbuf + sizeof(outbuf); bp > outbuf; bits >>= 6) - *--bp = nib2b64[bits & 0x3f]; - if (cc < sizeof(inbuf)) { - outbuf[3] = '='; - if (cc < sizeof inbuf - 1) - outbuf[2] = '='; - } - - fwrite (outbuf, sizeof(*outbuf), sizeof(outbuf), out); - - if (cc < sizeof(inbuf)) { - putc ('\n', out); - return OK; - } - - if (--n <= 0) { - n = BPERLIN; - putc ('\n', out); - } - } - if (n != BPERLIN) - putc ('\n', out); - - return OK; -}