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.
12 #include <h/signals.h>
17 #include <h/mhparse.h>
21 static char ebcdicsafe[0x100] = {
22 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
24 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
27 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
28 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
29 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
30 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
31 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
32 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
33 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
34 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
35 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
36 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
37 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
56 static char nib2b64[0x40+1] =
57 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
62 int output_message(CT, char *);
63 int output_message_fp(CT, FILE *, char *);
64 int writeBase64aux(FILE *, FILE *);
69 static int output_content(CT, FILE *);
70 static void output_headers(CT, FILE *);
71 static int write8Bit(CT, FILE *);
72 static int writeQuoted(CT, FILE *);
73 static int writeBase64(CT, FILE *);
77 ** Main routine to output a MIME message contained
78 ** in a Content structure, to a file. Any necessary
79 ** transfer encoding is added.
83 output_message_fp(CT ct, FILE *fp, char *file)
85 if (output_content(ct, fp) == NOTOK)
89 advise((file?file:"<FILE*>"), "error writing to");
96 output_message(CT ct, char *file)
101 if ((fp = fopen(file, "w")) == NULL) {
102 advise(file, "unable to open for writing");
105 status = output_message_fp(ct, fp, file);
112 ** Output a Content structure to a file.
116 output_content(CT ct, FILE *out)
119 CI ci = &ct->c_ctinfo;
122 ** Output all header fields for this content
124 output_headers(ct, out);
127 ** Now output the content bodies.
129 switch (ct->c_type) {
138 m = (struct multipart *) ct->c_ctparams;
139 for (part = m->mp_parts; part; part = part->mp_next) {
140 CT p = part->mp_part;
142 fprintf(out, "\n--%s\n", ci->ci_values[0]);
143 if (output_content(p, out) == NOTOK)
146 fprintf(out, "\n--%s--\n", ci->ci_values[0]);
152 result = write8Bit(ct, out);
156 ** Handle discrete types (text/application/audio/image/video)
159 switch (ct->c_encoding) {
162 result = write8Bit(ct, out);
167 result = write8Bit(ct, out);
172 result = writeQuoted(ct, out);
177 result = writeBase64(ct, out);
181 advise(NULL, "can't handle binary transfer encoding in content");
186 advise(NULL, "unknown transfer encoding in content");
198 ** Output all the header fields for a content
202 output_headers(CT ct, FILE *out)
208 fprintf(out, "%s:%s", hp->name, hp->value);
215 ** Output a content without any transfer encoding
219 write8Bit(CT ct, FILE *out)
222 char c, *file, buffer[BUFSIZ];
223 CE ce = ct->c_cefile;
226 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
230 while (fgets(buffer, sizeof(buffer) - 1, ce->ce_fp)) {
231 c = buffer[strlen(buffer) - 1];
237 (*ct->c_ceclosefnx) (ct);
243 ** Output a content using quoted-printable
247 writeQuoted(CT ct, FILE *out)
251 char c, buffer[BUFSIZ];
252 CE ce = ct->c_cefile;
255 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
258 while (fgets(buffer, sizeof(buffer) - 1, ce->ce_fp)) {
261 cp = buffer + strlen(buffer) - 1;
262 if ((c = *cp) == '\n')
265 if (strncmp(cp = buffer, "From ", sizeof("From ") - 1) == 0) {
266 fprintf(out, "=%02X", *cp++ & 0xff);
272 if (n > CPERLIN - 3) {
285 if (*cp < '!' || *cp > '~' || (ebcdicsw && !ebcdicsafe[*cp & 0xff]))
293 fprintf(out, "=%02X", *cp & 0xff);
300 if (cp > buffer && (*--cp == ' ' || *cp == '\t'))
309 (*ct->c_ceclosefnx) (ct);
315 ** Output a content using base64
319 writeBase64(CT ct, FILE *out)
323 CE ce = ct->c_cefile;
326 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
329 result = writeBase64aux(ce->ce_fp, out);
330 (*ct->c_ceclosefnx) (ct);
336 writeBase64aux(FILE *in, FILE *out)
342 while ((cc = fread(inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) {
347 if (cc < sizeof(inbuf)) {
349 if (cc < sizeof(inbuf) - 1)
352 bits = (inbuf[0] & 0xff) << 16;
353 bits |= (inbuf[1] & 0xff) << 8;
354 bits |= inbuf[2] & 0xff;
356 for (bp = outbuf + sizeof(outbuf); bp > outbuf; bits >>= 6)
357 *--bp = nib2b64[bits & 0x3f];
358 if (cc < sizeof(inbuf)) {
360 if (cc < sizeof inbuf - 1)
364 fwrite(outbuf, sizeof(*outbuf), sizeof(outbuf), out);
366 if (cc < sizeof(inbuf)) {