3 * mhoutsbr.c -- routines to output MIME messages
4 * -- given a Content structure
6 * This code is Copyright (c) 2002, by the authors of nmh. See the
7 * COPYRIGHT file in the root directory of the nmh distribution for
8 * complete copyright information.
13 #include <h/signals.h>
20 #include <h/mhparse.h>
25 static char ebcdicsafe[0x100] = {
26 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
28 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30 0x01, 0x00, 0x00, 0x00, 0x00, 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, 0x01, 0x01, 0x01, 0x01, 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, 0x01,
38 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
39 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
40 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
41 0x01, 0x01, 0x01, 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,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
63 int output_message (CT, char *);
64 int output_message_fp (CT, FILE *, char *);
69 static int output_content (CT, FILE *);
70 static void output_headers (CT, FILE *);
71 static int writeExternalBody (CT, FILE *);
72 static int write8Bit (CT, FILE *);
73 static int writeQuoted (CT, FILE *);
74 static int writeBase64ct (CT, FILE *);
78 * Main routine to output a MIME message contained
79 * in a Content structure, to a file. Any necessary
80 * transfer encoding is added.
84 output_message_fp (CT ct, FILE *fp, char *file)
86 if (output_content (ct, fp) == NOTOK)
90 advise ((file?file:"<FILE*>"), "error writing to");
97 output_message (CT ct, char *file)
102 if ((fp = fopen (file, "w")) == NULL) {
103 advise (file, "unable to open for writing");
106 status = output_message_fp(ct, fp, file);
113 * Output a Content structure to a file.
117 output_content (CT ct, FILE *out)
120 CI ci = &ct->c_ctinfo;
123 * Output all header fields for this content
125 output_headers (ct, out);
128 * If this is the internal content structure for a
129 * "message/external", then we are done with the
130 * headers (since it has no body).
136 * Now output the content bodies.
138 switch (ct->c_type) {
147 m = (struct multipart *) ct->c_ctparams;
148 for (part = m->mp_parts; part; part = part->mp_next) {
149 CT p = part->mp_part;
151 fprintf (out, "\n--%s\n", ci->ci_values[0]);
152 if (output_content (p, out) == NOTOK)
155 fprintf (out, "\n--%s--\n", ci->ci_values[0]);
161 if (ct->c_subtype == MESSAGE_EXTERNAL) {
164 e = (struct exbody *) ct->c_ctparams;
165 if (output_content (e->eb_content, out) == NOTOK)
168 /* output phantom body for access-type "mail-server" */
170 writeExternalBody (ct, out);
172 result = write8Bit (ct, out);
177 * Handle discrete types (text/application/audio/image/video)
180 switch (ct->c_encoding) {
183 result = write8Bit (ct, out);
188 result = write8Bit (ct, out);
193 result = writeQuoted (ct, out);
198 result = writeBase64ct (ct, out);
202 advise (NULL, "can't handle binary transfer encoding in content");
207 advise (NULL, "unknown transfer encoding in content");
219 * Output all the header fields for a content
223 output_headers (CT ct, FILE *out)
229 fprintf (out, "%s:%s", hp->name, hp->value);
236 * Write the phantom body for access-type "mail-server".
240 writeExternalBody (CT ct, FILE *out)
242 char **ap, **ep, *cp;
243 struct exbody *e = (struct exbody *) ct->c_ctparams;
246 for (cp = e->eb_body; *cp; cp++) {
247 CT ct2 = e->eb_content;
248 CI ci2 = &ct2->c_ctinfo;
254 char *dp = trimcpy (ct2->c_id);
262 for (ap = ci2->ci_attrs, ep = ci2->ci_values; *ap; ap++, ep++)
263 if (!mh_strcasecmp (*ap, "name")) {
264 fprintf (out, "%s", *ep);
270 fprintf (out, "%s/%s", ci2->ci_type, ci2->ci_subtype);
271 for (ap = ci2->ci_attrs, ep = ci2->ci_values; *ap; ap++, ep++)
272 fprintf (out, "; %s=\"%s\"", *ap, *ep);
305 * Output a content without any transfer encoding
309 write8Bit (CT ct, FILE *out)
312 char c, *file, buffer[BUFSIZ];
313 CE ce = ct->c_cefile;
316 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
320 while (fgets (buffer, sizeof(buffer) - 1, ce->ce_fp)) {
321 c = buffer[strlen (buffer) - 1];
327 (*ct->c_ceclosefnx) (ct);
333 * Output a content using quoted-printable
337 writeQuoted (CT ct, FILE *out)
341 char c, buffer[BUFSIZ];
342 CE ce = ct->c_cefile;
345 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
348 while (fgets (buffer, sizeof(buffer) - 1, ce->ce_fp)) {
351 cp = buffer + strlen (buffer) - 1;
352 if ((c = *cp) == '\n')
355 if (strncmp (cp = buffer, "From ", sizeof("From ") - 1) == 0) {
356 fprintf (out, "=%02X", *cp++ & 0xff);
362 if (n > CPERLIN - 3) {
375 if (*cp < '!' || *cp > '~'
376 || (ebcdicsw && !ebcdicsafe[*cp & 0xff]))
384 fprintf (out, "=%02X", *cp & 0xff);
391 if (cp > buffer && (*--cp == ' ' || *cp == '\t'))
400 (*ct->c_ceclosefnx) (ct);
406 * Output a content using base64
410 writeBase64ct (CT ct, FILE *out)
414 CE ce = ct->c_cefile;
417 if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK)
420 result = writeBase64aux (ce->ce_fp, out);
421 (*ct->c_ceclosefnx) (ct);