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>
20 static char nib2b64[0x40+1] =
21 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
26 int output_message(CT, char *);
27 int output_message_fp(CT, FILE *, char *);
32 static int output_content(CT, FILE *);
33 static void output_headers(CT, FILE *);
34 static int write8Bit(CT, FILE *);
35 static int writeQuoted(CT, FILE *);
36 static int writeBase64(CT, FILE *);
37 static int writeBase64aux(FILE *, FILE *);
41 ** Main routine to output a MIME message contained
42 ** in a Content structure, to a file. Any necessary
43 ** transfer encoding is added.
47 output_message_fp(CT ct, FILE *fp, char *file)
49 if (output_content(ct, fp) == NOTOK)
53 advise((file?file:"<FILE*>"), "error writing to");
60 output_message(CT ct, char *file)
65 if ((fp = fopen(file, "w")) == NULL) {
66 advise(file, "unable to open for writing");
69 status = output_message_fp(ct, fp, file);
76 ** Output a Content structure to a file.
80 output_content(CT ct, FILE *out)
83 CI ci = &ct->c_ctinfo;
86 ** Output all header fields for this content
88 output_headers(ct, out);
91 ** Now output the content bodies.
99 m = (struct multipart *) ct->c_ctparams;
100 for (part = m->mp_parts; part; part = part->mp_next) {
101 CT p = part->mp_part;
103 fprintf(out, "\n--%s\n", ci->ci_values[0]);
104 if (output_content(p, out) == NOTOK)
107 fprintf(out, "\n--%s--\n", ci->ci_values[0]);
113 result = write8Bit(ct, out);
117 ** Handle discrete types (text/application/audio/image/video)
120 switch (ct->c_encoding) {
123 result = write8Bit(ct, out);
128 result = write8Bit(ct, out);
133 result = writeQuoted(ct, out);
138 result = writeBase64(ct, out);
142 advise(NULL, "can't handle binary transfer encoding in content");
147 advise(NULL, "unknown transfer encoding in content");
159 ** Output all the header fields for a content
163 output_headers(CT ct, FILE *out)
169 fprintf(out, "%s:%s", hp->name, hp->value);
176 ** Output a content without any transfer encoding
180 write8Bit(CT ct, FILE *out)
183 char c, *file, buffer[BUFSIZ];
184 CE ce = ct->c_cefile;
187 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
191 while (fgets(buffer, sizeof(buffer) - 1, ce->ce_fp)) {
192 c = buffer[strlen(buffer) - 1];
198 (*ct->c_ceclosefnx) (ct);
204 ** Output a content using quoted-printable
208 writeQuoted(CT ct, FILE *out)
212 char c, buffer[BUFSIZ];
213 CE ce = ct->c_cefile;
216 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
219 while (fgets(buffer, sizeof(buffer) - 1, ce->ce_fp)) {
222 cp = buffer + strlen(buffer) - 1;
223 if ((c = *cp) == '\n')
226 if (strncmp(cp = buffer, "From ", sizeof("From ") - 1) == 0) {
227 fprintf(out, "=%02X", *cp++ & 0xff);
233 if (n > CPERLIN - 3) {
246 if (*cp < '!' || *cp > '~')
254 fprintf(out, "=%02X", *cp & 0xff);
261 if (cp > buffer && (*--cp == ' ' || *cp == '\t'))
270 (*ct->c_ceclosefnx) (ct);
276 ** Output a content using base64
280 writeBase64(CT ct, FILE *out)
284 CE ce = ct->c_cefile;
287 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
290 result = writeBase64aux(ce->ce_fp, out);
291 (*ct->c_ceclosefnx) (ct);
297 writeBase64aux(FILE *in, FILE *out)
303 while ((cc = fread(inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) {
308 if (cc < sizeof(inbuf)) {
310 if (cc < sizeof(inbuf) - 1)
313 bits = (inbuf[0] & 0xff) << 16;
314 bits |= (inbuf[1] & 0xff) << 8;
315 bits |= inbuf[2] & 0xff;
317 for (bp = outbuf + sizeof(outbuf); bp > outbuf; bits >>= 6)
318 *--bp = nib2b64[bits & 0x3f];
319 if (cc < sizeof(inbuf)) {
321 if (cc < sizeof inbuf - 1)
325 fwrite(outbuf, sizeof(*outbuf), sizeof(outbuf), out);
327 if (cc < sizeof(inbuf)) {