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 *);
28 int writeBase64aux(FILE *, FILE *);
33 static int output_content(CT, FILE *);
34 static void output_headers(CT, FILE *);
35 static int write8Bit(CT, FILE *);
36 static int writeQuoted(CT, FILE *);
37 static int writeBase64(CT, 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.
102 m = (struct multipart *) ct->c_ctparams;
103 for (part = m->mp_parts; part; part = part->mp_next) {
104 CT p = part->mp_part;
106 fprintf(out, "\n--%s\n", ci->ci_values[0]);
107 if (output_content(p, out) == NOTOK)
110 fprintf(out, "\n--%s--\n", ci->ci_values[0]);
116 result = write8Bit(ct, out);
120 ** Handle discrete types (text/application/audio/image/video)
123 switch (ct->c_encoding) {
126 result = write8Bit(ct, out);
131 result = write8Bit(ct, out);
136 result = writeQuoted(ct, out);
141 result = writeBase64(ct, out);
145 advise(NULL, "can't handle binary transfer encoding in content");
150 advise(NULL, "unknown transfer encoding in content");
162 ** Output all the header fields for a content
166 output_headers(CT ct, FILE *out)
172 fprintf(out, "%s:%s", hp->name, hp->value);
179 ** Output a content without any transfer encoding
183 write8Bit(CT ct, FILE *out)
186 char c, *file, buffer[BUFSIZ];
187 CE ce = ct->c_cefile;
190 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
194 while (fgets(buffer, sizeof(buffer) - 1, ce->ce_fp)) {
195 c = buffer[strlen(buffer) - 1];
201 (*ct->c_ceclosefnx) (ct);
207 ** Output a content using quoted-printable
211 writeQuoted(CT ct, FILE *out)
215 char c, buffer[BUFSIZ];
216 CE ce = ct->c_cefile;
219 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
222 while (fgets(buffer, sizeof(buffer) - 1, ce->ce_fp)) {
225 cp = buffer + strlen(buffer) - 1;
226 if ((c = *cp) == '\n')
229 if (strncmp(cp = buffer, "From ", sizeof("From ") - 1) == 0) {
230 fprintf(out, "=%02X", *cp++ & 0xff);
236 if (n > CPERLIN - 3) {
249 if (*cp < '!' || *cp > '~')
257 fprintf(out, "=%02X", *cp & 0xff);
264 if (cp > buffer && (*--cp == ' ' || *cp == '\t'))
273 (*ct->c_ceclosefnx) (ct);
279 ** Output a content using base64
283 writeBase64(CT ct, FILE *out)
287 CE ce = ct->c_cefile;
290 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
293 result = writeBase64aux(ce->ce_fp, out);
294 (*ct->c_ceclosefnx) (ct);
300 writeBase64aux(FILE *in, FILE *out)
306 while ((cc = fread(inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) {
311 if (cc < sizeof(inbuf)) {
313 if (cc < sizeof(inbuf) - 1)
316 bits = (inbuf[0] & 0xff) << 16;
317 bits |= (inbuf[1] & 0xff) << 8;
318 bits |= inbuf[2] & 0xff;
320 for (bp = outbuf + sizeof(outbuf); bp > outbuf; bits >>= 6)
321 *--bp = nib2b64[bits & 0x3f];
322 if (cc < sizeof(inbuf)) {
324 if (cc < sizeof inbuf - 1)
328 fwrite(outbuf, sizeof(*outbuf), sizeof(outbuf), out);
330 if (cc < sizeof(inbuf)) {