* mhoutsbr.c -- routines to output MIME messages
* -- given a Content structure
*
- * $Id$
- *
* This code is Copyright (c) 2002, by the authors of nmh. See the
* COPYRIGHT file in the root directory of the nmh distribution for
* complete copyright information.
#include <fcntl.h>
#include <h/signals.h>
#include <h/md5.h>
-#include <errno.h>
-#include <signal.h>
#include <h/mts.h>
#include <h/tws.h>
#include <h/mime.h>
#include <h/mhparse.h>
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-
-
-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
*/
int output_message (CT, char *);
-int writeBase64aux (FILE *, FILE *);
+int output_message_fp (CT, FILE *, char *);
/*
* static prototypes
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 *);
/*
*/
int
-output_message (CT ct, char *file)
+output_message_fp (CT ct, FILE *fp, char *file)
{
- FILE *fp;
-
- if ((fp = fopen (file, "w")) == NULL) {
- advise (file, "unable to open for writing");
- return NOTOK;
- }
-
if (output_content (ct, fp) == NOTOK)
return NOTOK;
if (fflush (fp)) {
- advise (file, "error writing to");
+ advise ((file?file:"<FILE*>"), "error writing to");
return NOTOK;
}
- fclose (fp);
-
return OK;
}
+int
+output_message (CT ct, char *file)
+{
+ FILE *fp;
+ int status;
+
+ 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);
+ if (strcmp (file, "-")) fclose(fp);
+ return status;
+}
+
/*
* Output a Content structure to a file.
{
int result = 0;
CI ci = &ct->c_ctinfo;
+ char *boundary = ci->ci_values[0], **ap, **vp;
+
+ for (ap = ci->ci_attrs, vp = ci->ci_values; *ap; ++ap, ++vp) {
+ if (! strcasecmp ("boundary", *ap)) {
+ boundary = *vp;
+ break;
+ }
+ }
/*
* Output all header fields for this content
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]);
+ fprintf (out, "\n--%s\n", boundary);
if (output_content (p, out) == NOTOK)
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;
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_attrs[0] != NULL ||
+ ct->c_begin != ct->c_end) {
+ putc ('\n', out);
+ }
result = write8Bit (ct, out);
break;
case CE_BASE64:
putc ('\n', out);
- result = writeBase64 (ct, out);
+ result = writeBase64ct (ct, out);
break;
case CE_BINARY:
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];
+ fwrite (buffer, 1, inbytes, out);
}
if (c != '\n')
putc ('\n', out);
{
int fd;
char *cp, *file;
- char c, buffer[BUFSIZ];
- CE ce = ct->c_cefile;
+ char c = '\0', buffer[BUFSIZ];
+ CE ce = &ct->c_cefile;
+ int n = 0;
file = NULL;
if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
return NOTOK;
while (fgets (buffer, sizeof(buffer) - 1, ce->ce_fp)) {
- int n;
cp = buffer + strlen (buffer) - 1;
if ((c = *cp) == '\n')
if (strncmp (cp = buffer, "From ", sizeof("From ") - 1) == 0) {
fprintf (out, "=%02X", *cp++ & 0xff);
- n = 3;
- } else {
- n = 0;
+ n += 3;
}
+
for (; *cp; cp++) {
if (n > CPERLIN - 3) {
fputs ("=\n", out);
break;
default:
- if (*cp < '!' || *cp > '~'
- || (ebcdicsw && !ebcdicsafe[*cp & 0xff]))
+ if (*cp < '!' || *cp > '~')
goto three_print;
putc (*cp, out);
n++;
fputs ("=\n", out);
putc ('\n', out);
- } else {
- fputs ("=\n", out);
+ n = 0;
}
}
+ if (c != '\n')
+ putc ('\n', out);
+
(*ct->c_ceclosefnx) (ct);
return OK;
}
*/
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_ceclosefnx) (ct);
return result;
}
-
-
-int
-writeBase64aux (FILE *in, FILE *out)
-{
- 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;
-}