/*
- * mhoutsbr.c -- routines to output MIME messages
- * -- given a Content structure
- *
- * 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.
- */
+** mhoutsbr.c -- routines to output MIME messages
+** -- given a Content structure
+**
+** 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 <h/mh.h>
#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 output_message_fp (CT, FILE *, char *);
-int writeBase64aux (FILE *, FILE *);
+** prototypes
+*/
+int output_message(CT, char *);
+int output_message_fp(CT, FILE *, char *);
/*
- * static prototypes
- */
-static int output_content (CT, FILE *);
-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 prototypes
+*/
+static int output_content(CT, FILE *);
+static void output_headers(CT, FILE *);
+static int write8Bit(CT, FILE *);
+static int writeQuoted(CT, FILE *);
+static int writeBase64(CT, FILE *);
+static int writeBase64aux(FILE *, FILE *);
/*
- * Main routine to output a MIME message contained
- * in a Content structure, to a file. Any necessary
- * transfer encoding is added.
- */
+** Main routine to output a MIME message contained
+** in a Content structure, to a file. Any necessary
+** transfer encoding is added.
+*/
int
-output_message_fp (CT ct, FILE *fp, char *file)
+output_message_fp(CT ct, FILE *fp, char *file)
{
- if (output_content (ct, fp) == NOTOK)
+ if (output_content(ct, fp) == NOTOK)
return NOTOK;
- if (fflush (fp)) {
- advise ((file?file:"<FILE*>"), "error writing to");
+ if (fflush(fp)) {
+ advise((file?file:"<FILE*>"), "error writing to");
return NOTOK;
}
return OK;
}
int
-output_message (CT ct, char *file)
+output_message(CT ct, char *file)
{
FILE *fp;
int status;
- if ((fp = fopen (file, "w")) == NULL) {
- advise (file, "unable to open for writing");
+ if ((fp = fopen(file, "w")) == NULL) {
+ advise(file, "unable to open for writing");
return NOTOK;
}
status = output_message_fp(ct, fp, file);
/*
- * Output a Content structure to a file.
- */
+** Output a Content structure to a file.
+*/
static int
-output_content (CT ct, FILE *out)
+output_content(CT ct, FILE *out)
{
int result = 0;
CI ci = &ct->c_ctinfo;
/*
- * Output all header fields for this content
- */
- output_headers (ct, out);
+ ** Output all header fields for this content
+ */
+ output_headers(ct, out);
/*
- * If this is the internal content structure for a
- * "message/external", then we are done with the
- * headers (since it has no body).
- */
- if (ct->c_ctexbody)
- return OK;
-
- /*
- * Now output the content bodies.
- */
+ ** Now output the content bodies.
+ */
switch (ct->c_type) {
case CT_MULTIPART:
{
struct multipart *m;
struct part *part;
- if (ct->c_rfc934)
- putc ('\n', out);
-
m = (struct multipart *) ct->c_ctparams;
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)
+ fprintf(out, "\n--%s\n", ci->ci_values[0]);
+ if (output_content(p, out) == NOTOK)
return NOTOK;
}
- fprintf (out, "\n--%s--\n", ci->ci_values[0]);
+ fprintf(out, "\n--%s--\n", ci->ci_values[0]);
}
break;
case CT_MESSAGE:
- putc ('\n', out);
- if (ct->c_subtype == MESSAGE_EXTERNAL) {
- struct exbody *e;
-
- e = (struct exbody *) ct->c_ctparams;
- if (output_content (e->eb_content, out) == NOTOK)
- return NOTOK;
-
- /* output phantom body for access-type "mail-server" */
- if (e->eb_body)
- writeExternalBody (ct, out);
- } else {
- result = write8Bit (ct, out);
- }
+ putc('\n', out);
+ result = write8Bit(ct, out);
break;
/*
- * Handle discrete types (text/application/audio/image/video)
- */
+ ** Handle discrete types (text/application/audio/image/video)
+ */
default:
switch (ct->c_encoding) {
case CE_7BIT:
- putc ('\n', out);
- result = write8Bit (ct, out);
+ putc('\n', out);
+ result = write8Bit(ct, out);
break;
case CE_8BIT:
- putc ('\n', out);
- result = write8Bit (ct, out);
+ putc('\n', out);
+ result = write8Bit(ct, out);
break;
case CE_QUOTED:
- putc ('\n', out);
- result = writeQuoted (ct, out);
+ putc('\n', out);
+ result = writeQuoted(ct, out);
break;
case CE_BASE64:
- putc ('\n', out);
- result = writeBase64 (ct, out);
+ putc('\n', out);
+ result = writeBase64(ct, out);
break;
case CE_BINARY:
- advise (NULL, "can't handle binary transfer encoding in content");
+ advise(NULL, "can't handle binary transfer encoding in content");
result = NOTOK;
break;
default:
- advise (NULL, "unknown transfer encoding in content");
+ advise(NULL, "unknown transfer encoding in content");
result = NOTOK;
break;
}
/*
- * Output all the header fields for a content
- */
+** Output all the header fields for a content
+*/
static void
-output_headers (CT ct, FILE *out)
+output_headers(CT ct, FILE *out)
{
HF hp;
+ charstring_t body = charstring_create(0);
hp = ct->c_first_hf;
while (hp) {
- fprintf (out, "%s:%s", hp->name, hp->value);
+ fold(body, strlen(hp->name), hp->value);
+ fprintf(out, "%s:%s", hp->name, charstring_buffer(body));
hp = hp->next;
}
+ charstring_free(body);
}
/*
- * Write the phantom body for access-type "mail-server".
- */
+** Output a content without any transfer encoding
+*/
static int
-writeExternalBody (CT ct, FILE *out)
-{
- char **ap, **ep, *cp;
- struct exbody *e = (struct exbody *) ct->c_ctparams;
-
- putc ('\n', out);
- for (cp = e->eb_body; *cp; cp++) {
- CT ct2 = e->eb_content;
- CI ci2 = &ct2->c_ctinfo;
-
- if (*cp == '\\') {
- switch (*++cp) {
- case 'I':
- if (ct2->c_id) {
- char *dp = trimcpy (ct2->c_id);
-
- fputs (dp, out);
- free (dp);
- }
- 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;
- }
- 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);
- continue;
-
- case 'n':
- putc ('\n', out);
- continue;
-
- case 't':
- putc ('\t', out);
- continue;
-
- case '\0':
- cp--;
- break;
-
- case '\\':
- case '"':
- break;
-
- default:
- putc ('\\', out);
- break;
- }
- }
- putc (*cp, out);
- }
- putc ('\n', out);
-
- return OK;
-}
-
-
-/*
- * Output a content without any transfer encoding
- */
-
-static int
-write8Bit (CT ct, FILE *out)
+write8Bit(CT ct, FILE *out)
{
int fd;
char c, *file, buffer[BUFSIZ];
return NOTOK;
c = '\n';
- while (fgets (buffer, sizeof(buffer) - 1, ce->ce_fp)) {
- c = buffer[strlen (buffer) - 1];
- fputs (buffer, out);
+ while (fgets(buffer, sizeof(buffer) - 1, ce->ce_fp)) {
+ c = buffer[strlen(buffer) - 1];
+ fputs(buffer, out);
}
if (c != '\n')
- putc ('\n', out);
+ putc('\n', out);
(*ct->c_ceclosefnx) (ct);
return OK;
/*
- * Output a content using quoted-printable
- */
+** Output a content using quoted-printable
+*/
static int
-writeQuoted (CT ct, FILE *out)
+writeQuoted(CT ct, FILE *out)
{
int fd;
char *cp, *file;
if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
return NOTOK;
- while (fgets (buffer, sizeof(buffer) - 1, ce->ce_fp)) {
+ while (fgets(buffer, sizeof(buffer) - 1, ce->ce_fp)) {
int n;
- cp = buffer + strlen (buffer) - 1;
+ cp = buffer + strlen(buffer) - 1;
if ((c = *cp) == '\n')
*cp = '\0';
- if (strncmp (cp = buffer, "From ", sizeof("From ") - 1) == 0) {
- fprintf (out, "=%02X", *cp++ & 0xff);
+ if (strncmp(cp = buffer, "From ", sizeof("From ") - 1) == 0) {
+ fprintf(out, "=%02X", *cp++ & 0xff);
n = 3;
} else {
n = 0;
}
for (; *cp; cp++) {
- if (n > CPERLIN - 3) {
- fputs ("=\n", out);
+ if (n + 1 >= CPERLIN) {
+ fputs("=\n", out);
n = 0;
}
switch (*cp) {
- case ' ':
- case '\t':
- putc (*cp, out);
- n++;
- break;
-
- default:
- if (*cp < '!' || *cp > '~'
- || (ebcdicsw && !ebcdicsafe[*cp & 0xff]))
- goto three_print;
- putc (*cp, out);
- n++;
- break;
-
- case '=':
+ case ' ':
+ case '\t':
+ putc(*cp, out);
+ n++;
+ break;
+
+ default:
+ if (*cp < '!' || *cp > '~') {
+ goto three_print;
+ }
+ if (n == 0 && *cp == '.') {
+ /*
+ ** encode dot at start of line,
+ ** because it could be alone ...
+ */
+ goto three_print;
+ }
+ putc(*cp, out);
+ n++;
+ break;
+
+ case '=':
three_print:
- fprintf (out, "=%02X", *cp & 0xff);
- n += 3;
- break;
+ fprintf(out, "=%02X", *cp & 0xff);
+ n += 3;
+ break;
}
}
if (c == '\n') {
if (cp > buffer && (*--cp == ' ' || *cp == '\t'))
- fputs ("=\n", out);
+ fputs("=\n", out);
- putc ('\n', out);
+ putc('\n', out);
} else {
- fputs ("=\n", out);
+ fputs("=\n", out);
}
}
/*
- * Output a content using base64
- */
+** Output a content using base64
+*/
static int
-writeBase64 (CT ct, FILE *out)
+writeBase64(CT ct, FILE *out)
{
int fd, result;
char *file;
if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
return NOTOK;
- result = writeBase64aux (ce->ce_fp, out);
+ result = writeBase64aux(ce->ce_fp, out);
(*ct->c_ceclosefnx) (ct);
return result;
}
-int
-writeBase64aux (FILE *in, FILE *out)
+static int
+writeBase64aux(FILE *in, FILE *out)
{
- int cc, n;
+ unsigned int cc, n;
char inbuf[3];
n = BPERLIN;
- while ((cc = fread (inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) {
+ while ((cc = fread(inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) {
unsigned long bits;
char *bp;
char outbuf[4];
outbuf[2] = '=';
}
- fwrite (outbuf, sizeof(*outbuf), sizeof(outbuf), out);
+ fwrite(outbuf, sizeof(*outbuf), sizeof(outbuf), out);
if (cc < sizeof(inbuf)) {
- putc ('\n', out);
+ putc('\n', out);
return OK;
}
if (--n <= 0) {
n = BPERLIN;
- putc ('\n', out);
+ putc('\n', out);
}
}
if (n != BPERLIN)
- putc ('\n', out);
+ putc('\n', out);
return OK;
}