]>
diplodocus.org Git - nmh/blob - uip/mhoutsbr.c
3 * mhoutsbr.c -- routines to output MIME messages
4 * -- given a Content structure
8 * This code is Copyright (c) 2002, by the authors of nmh. See the
9 * COPYRIGHT file in the root directory of the nmh distribution for
10 * complete copyright information.
15 #include <h/signals.h>
22 #include <h/mhparse.h>
24 #ifdef HAVE_SYS_WAIT_H
25 # include <sys/wait.h>
31 static char ebcdicsafe
[0x100] = {
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
37 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
38 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
39 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
40 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
41 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
42 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
43 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
44 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
45 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
46 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
47 0x01, 0x01, 0x01, 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,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
66 static char nib2b64
[0x40+1] =
67 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
72 int output_message (CT
, char *);
73 int writeBase64aux (FILE *, FILE *);
78 static int output_content (CT
, FILE *);
79 static void output_headers (CT
, FILE *);
80 static int writeExternalBody (CT
, FILE *);
81 static int write8Bit (CT
, FILE *);
82 static int writeQuoted (CT
, FILE *);
83 static int writeBase64 (CT
, FILE *);
87 * Main routine to output a MIME message contained
88 * in a Content structure, to a file. Any necessary
89 * transfer encoding is added.
93 output_message (CT ct
, char *file
)
97 if ((fp
= fopen (file
, "w")) == NULL
) {
98 advise (file
, "unable to open for writing");
102 if (output_content (ct
, fp
) == NOTOK
)
106 advise (file
, "error writing to");
116 * Output a Content structure to a file.
120 output_content (CT ct
, FILE *out
)
123 CI ci
= &ct
->c_ctinfo
;
126 * Output all header fields for this content
128 output_headers (ct
, out
);
131 * If this is the internal content structure for a
132 * "message/external", then we are done with the
133 * headers (since it has no body).
139 * Now output the content bodies.
141 switch (ct
->c_type
) {
150 m
= (struct multipart
*) ct
->c_ctparams
;
151 for (part
= m
->mp_parts
; part
; part
= part
->mp_next
) {
152 CT p
= part
->mp_part
;
154 fprintf (out
, "\n--%s\n", ci
->ci_values
[0]);
155 if (output_content (p
, out
) == NOTOK
)
158 fprintf (out
, "\n--%s--\n", ci
->ci_values
[0]);
164 if (ct
->c_subtype
== MESSAGE_EXTERNAL
) {
167 e
= (struct exbody
*) ct
->c_ctparams
;
168 if (output_content (e
->eb_content
, out
) == NOTOK
)
171 /* output phantom body for access-type "mail-server" */
173 writeExternalBody (ct
, out
);
175 result
= write8Bit (ct
, out
);
180 * Handle discrete types (text/application/audio/image/video)
183 switch (ct
->c_encoding
) {
186 result
= write8Bit (ct
, out
);
191 result
= write8Bit (ct
, out
);
196 result
= writeQuoted (ct
, out
);
201 result
= writeBase64 (ct
, out
);
205 advise (NULL
, "can't handle binary transfer encoding in content");
210 advise (NULL
, "unknown transfer encoding in content");
222 * Output all the header fields for a content
226 output_headers (CT ct
, FILE *out
)
232 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
239 * Write the phantom body for access-type "mail-server".
243 writeExternalBody (CT ct
, FILE *out
)
245 char **ap
, **ep
, *cp
;
246 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
249 for (cp
= e
->eb_body
; *cp
; cp
++) {
250 CT ct2
= e
->eb_content
;
251 CI ci2
= &ct2
->c_ctinfo
;
257 char *dp
= trimcpy (ct2
->c_id
);
265 for (ap
= ci2
->ci_attrs
, ep
= ci2
->ci_values
; *ap
; ap
++, ep
++)
266 if (!strcasecmp (*ap
, "name")) {
267 fprintf (out
, "%s", *ep
);
273 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
274 for (ap
= ci2
->ci_attrs
, ep
= ci2
->ci_values
; *ap
; ap
++, ep
++)
275 fprintf (out
, "; %s=\"%s\"", *ap
, *ep
);
308 * Output a content without any transfer encoding
312 write8Bit (CT ct
, FILE *out
)
315 char c
, *file
, buffer
[BUFSIZ
];
316 CE ce
= ct
->c_cefile
;
319 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
323 while (fgets (buffer
, sizeof(buffer
) - 1, ce
->ce_fp
)) {
324 c
= buffer
[strlen (buffer
) - 1];
330 (*ct
->c_ceclosefnx
) (ct
);
336 * Output a content using quoted-printable
340 writeQuoted (CT ct
, FILE *out
)
344 char c
, buffer
[BUFSIZ
];
345 CE ce
= ct
->c_cefile
;
348 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
351 while (fgets (buffer
, sizeof(buffer
) - 1, ce
->ce_fp
)) {
354 cp
= buffer
+ strlen (buffer
) - 1;
355 if ((c
= *cp
) == '\n')
358 if (strncmp (cp
= buffer
, "From ", sizeof("From ") - 1) == 0) {
359 fprintf (out
, "=%02X", *cp
++ & 0xff);
365 if (n
> CPERLIN
- 3) {
378 if (*cp
< '!' || *cp
> '~'
379 || (ebcdicsw
&& !ebcdicsafe
[*cp
& 0xff]))
387 fprintf (out
, "=%02X", *cp
& 0xff);
394 if (cp
> buffer
&& (*--cp
== ' ' || *cp
== '\t'))
403 (*ct
->c_ceclosefnx
) (ct
);
409 * Output a content using base64
413 writeBase64 (CT ct
, FILE *out
)
417 CE ce
= ct
->c_cefile
;
420 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
423 result
= writeBase64aux (ce
->ce_fp
, out
);
424 (*ct
->c_ceclosefnx
) (ct
);
430 writeBase64aux (FILE *in
, FILE *out
)
436 while ((cc
= fread (inbuf
, sizeof(*inbuf
), sizeof(inbuf
), in
)) > 0) {
441 if (cc
< sizeof(inbuf
)) {
443 if (cc
< sizeof(inbuf
) - 1)
446 bits
= (inbuf
[0] & 0xff) << 16;
447 bits
|= (inbuf
[1] & 0xff) << 8;
448 bits
|= inbuf
[2] & 0xff;
450 for (bp
= outbuf
+ sizeof(outbuf
); bp
> outbuf
; bits
>>= 6)
451 *--bp
= nib2b64
[bits
& 0x3f];
452 if (cc
< sizeof(inbuf
)) {
454 if (cc
< sizeof inbuf
- 1)
458 fwrite (outbuf
, sizeof(*outbuf
), sizeof(outbuf
), out
);
460 if (cc
< sizeof(inbuf
)) {