2 ** mhoutsbr.c -- routines to output MIME messages
3 ** -- given a Content structure
5 ** This code is Copyright (c) 2002, by the authors of nmh. See the
6 ** COPYRIGHT file in the root directory of the nmh distribution for
7 ** complete copyright information.
15 #include <h/mhparse.h>
18 static char nib2b64[0x40+1] =
19 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
24 int output_message(CT, char *);
25 int output_message_fp(CT, FILE *, char *);
30 static int output_content(CT, FILE *);
31 static void output_headers(CT, FILE *);
32 static int write8Bit(CT, FILE *);
33 static int writeQuoted(CT, FILE *);
34 static int writeBase64(CT, FILE *);
35 static int writeBase64aux(FILE *, FILE *);
39 ** Main routine to output a MIME message contained
40 ** in a Content structure, to a file. Any necessary
41 ** transfer encoding is added.
45 output_message_fp(CT ct, FILE *fp, char *file)
47 if (output_content(ct, fp) == NOTOK)
51 advise((file?file:"<FILE*>"), "error writing to");
58 output_message(CT ct, char *file)
63 if ((fp = fopen(file, "w")) == NULL) {
64 advise(file, "unable to open for writing");
67 status = output_message_fp(ct, fp, file);
74 ** Output a Content structure to a file.
78 output_content(CT ct, FILE *out)
81 CI ci = &ct->c_ctinfo;
84 ** Output all header fields for this content
86 output_headers(ct, out);
89 ** Now output the content bodies.
97 m = (struct multipart *) ct->c_ctparams;
98 for (part = m->mp_parts; part; part = part->mp_next) {
101 fprintf(out, "\n--%s\n", ci->ci_values[0]);
102 if (output_content(p, out) == NOTOK)
105 fprintf(out, "\n--%s--\n", ci->ci_values[0]);
111 result = write8Bit(ct, out);
115 ** Handle discrete types (text/application/audio/image/video)
118 switch (ct->c_encoding) {
121 result = write8Bit(ct, out);
126 result = write8Bit(ct, out);
131 result = writeQuoted(ct, out);
136 result = writeBase64(ct, out);
140 advise(NULL, "can't handle binary transfer encoding in content");
145 advise(NULL, "unknown transfer encoding in content");
157 ** Output all the header fields for a content
161 output_headers(CT ct, FILE *out)
167 fprintf(out, "%s:%s", hp->name, hp->value);
174 ** Output a content without any transfer encoding
178 write8Bit(CT ct, FILE *out)
181 char c, *file, buffer[BUFSIZ];
182 CE ce = ct->c_cefile;
185 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
189 while (fgets(buffer, sizeof(buffer) - 1, ce->ce_fp)) {
190 c = buffer[strlen(buffer) - 1];
196 (*ct->c_ceclosefnx) (ct);
202 ** Output a content using quoted-printable
206 writeQuoted(CT ct, FILE *out)
210 char c, buffer[BUFSIZ];
211 CE ce = ct->c_cefile;
214 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
217 while (fgets(buffer, sizeof(buffer) - 1, ce->ce_fp)) {
220 cp = buffer + strlen(buffer) - 1;
221 if ((c = *cp) == '\n')
224 if (strncmp(cp = buffer, "From ", sizeof("From ") - 1) == 0) {
225 fprintf(out, "=%02X", *cp++ & 0xff);
231 if (n > CPERLIN - 3) {
244 if (*cp < '!' || *cp > '~') {
247 if (n == 0 && *cp == '.') {
249 ** encode dot at start of line,
250 ** because it could be alone ...
260 fprintf(out, "=%02X", *cp & 0xff);
267 if (cp > buffer && (*--cp == ' ' || *cp == '\t'))
276 (*ct->c_ceclosefnx) (ct);
282 ** Output a content using base64
286 writeBase64(CT ct, FILE *out)
290 CE ce = ct->c_cefile;
293 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
296 result = writeBase64aux(ce->ce_fp, out);
297 (*ct->c_ceclosefnx) (ct);
303 writeBase64aux(FILE *in, FILE *out)
309 while ((cc = fread(inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) {
314 if (cc < sizeof(inbuf)) {
316 if (cc < sizeof(inbuf) - 1)
319 bits = (inbuf[0] & 0xff) << 16;
320 bits |= (inbuf[1] & 0xff) << 8;
321 bits |= inbuf[2] & 0xff;
323 for (bp = outbuf + sizeof(outbuf); bp > outbuf; bits >>= 6)
324 *--bp = nib2b64[bits & 0x3f];
325 if (cc < sizeof(inbuf)) {
327 if (cc < sizeof inbuf - 1)
331 fwrite(outbuf, sizeof(*outbuf), sizeof(outbuf), out);
333 if (cc < sizeof(inbuf)) {