]>
diplodocus.org Git - nmh/blob - uip/mhoutsbr.c
1 /* mhoutsbr.c -- routines to output MIME messages
2 * -- given a Content structure
4 * This code is Copyright (c) 2002, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
16 #include <h/mhparse.h>
18 #include "sbr/base64.h"
24 static int output_content (CT
, FILE *);
25 static void output_headers (CT
, FILE *);
26 static int writeExternalBody (CT
, FILE *);
27 static int write8Bit (CT
, FILE *);
28 static int writeQuoted (CT
, FILE *);
29 static int writeBase64ct (CT
, FILE *);
33 * Main routine to output a MIME message contained
34 * in a Content structure, to a file. Any necessary
35 * transfer encoding is added.
39 output_message_fp (CT ct
, FILE *fp
, char *file
)
41 if (output_content (ct
, fp
) == NOTOK
)
45 advise ((file
?file
:"<FILE*>"), "error writing to");
53 * Output a Content structure to a file.
57 output_content (CT ct
, FILE *out
)
60 CI ci
= &ct
->c_ctinfo
;
61 char *boundary
= "", *cp
;
63 if ((cp
= get_param(ci
->ci_first_pm
, "boundary", '-', 0)))
67 * Output all header fields for this content
69 output_headers (ct
, out
);
72 * If this is the internal content structure for a
73 * "message/external", then we are done with the
74 * headers (since it has no body).
77 if (*boundary
!= '\0')
83 * Now output the content bodies.
94 m
= (struct multipart
*) ct
->c_ctparams
;
96 if (m
->mp_content_before
) {
97 fputs(m
->mp_content_before
, out
);
100 for (part
= m
->mp_parts
; part
; part
= part
->mp_next
) {
101 CT p
= part
->mp_part
;
103 fprintf (out
, "\n--%s\n", boundary
);
104 if (output_content (p
, out
) == NOTOK
) {
105 if (*boundary
!= '\0')
110 fprintf (out
, "\n--%s--\n", boundary
);
112 if (m
->mp_content_after
) {
113 fputs(m
->mp_content_after
, out
);
120 if (ct
->c_subtype
== MESSAGE_EXTERNAL
) {
123 e
= (struct exbody
*) ct
->c_ctparams
;
124 if (output_content (e
->eb_content
, out
) == NOTOK
)
127 /* output phantom body for access-type "mail-server" */
129 writeExternalBody (ct
, out
);
131 result
= write8Bit (ct
, out
);
136 * Handle discrete types (text/application/audio/image/video)
139 switch (ct
->c_encoding
) {
141 /* Special case: if this is a non-MIME message with no
142 body, don't emit the newline that would appear between
143 the headers and body. In that case, the call to
144 write8Bit() shouldn't be needed, but is harmless. */
145 if (ct
->c_ctinfo
.ci_first_pm
!= NULL
|| ct
->c_begin
== 0 ||
146 ct
->c_begin
!= ct
->c_end
) {
149 result
= write8Bit (ct
, out
);
154 result
= write8Bit (ct
, out
);
159 result
= writeQuoted (ct
, out
);
164 result
= writeBase64ct (ct
, out
);
168 if (ct
->c_type
== CT_TEXT
) {
169 /* So that mhfixmsg can decode to binary text. */
171 result
= write8Bit (ct
, out
);
173 inform("can't handle binary transfer encoding in content");
179 inform("unknown transfer encoding in content");
186 if (*boundary
!= '\0')
194 * Output all the header fields for a content
198 output_headers (CT ct
, FILE *out
)
204 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
211 * Write the phantom body for access-type "mail-server".
215 writeExternalBody (CT ct
, FILE *out
)
218 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
221 for (cp
= e
->eb_body
; *cp
; cp
++) {
222 CT ct2
= e
->eb_content
;
223 CI ci2
= &ct2
->c_ctinfo
;
229 dp
= trimcpy (ct2
->c_id
);
237 dp
= get_param(ci2
->ci_first_pm
, "name", '_', 0);
245 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
246 dp
= output_params(strlen(ci2
->ci_type
) +
247 strlen(ci2
->ci_subtype
) + 1,
248 ci2
->ci_first_pm
, NULL
, 0);
285 * Output a content without any transfer encoding
289 write8Bit (CT ct
, FILE *out
)
293 char c
, *file
, buffer
[BUFSIZ
];
294 CE ce
= &ct
->c_cefile
;
297 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
301 while ((inbytes
= fread (buffer
, 1, sizeof buffer
, ce
->ce_fp
)) > 0) {
302 c
= buffer
[inbytes
- 1];
303 if (fwrite (buffer
, 1, inbytes
, out
) < inbytes
) {
304 advise ("write8Bit", "fwrite");
310 (*ct
->c_ceclosefnx
) (ct
);
316 * Output a content using quoted-printable
320 writeQuoted (CT ct
, FILE *out
)
325 CE ce
= &ct
->c_cefile
;
332 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
335 while ((gotlen
= getline(&bufp
, &buflen
, ce
->ce_fp
)) != -1) {
337 cp
= bufp
+ gotlen
- 1;
338 if ((c
= *cp
) == '\n')
342 * if the line starts with "From ", encode the 'F' so it
343 * doesn't falsely match an mbox delimiter.
346 if (gotlen
>= 5 && has_prefix(cp
, "From ")) {
347 fprintf (out
, "=%02X", 'F');
352 for (; cp
< bufp
+ gotlen
; cp
++) {
353 if (n
> CPERLIN
- 3) {
366 if (*cp
< '!' || *cp
> '~')
374 fprintf (out
, "=%02X", *cp
& 0xff);
381 if (cp
> bufp
&& (*--cp
== ' ' || *cp
== '\t'))
392 (*ct
->c_ceclosefnx
) (ct
);
399 * Output a content using base64
403 writeBase64ct (CT ct
, FILE *out
)
407 CE ce
= &ct
->c_cefile
;
410 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
413 result
= writeBase64aux (ce
->ce_fp
, out
,
414 ct
->c_type
== CT_TEXT
&& ct
->c_ctparams
415 ? ((struct text
*) ct
->c_ctparams
)->lf_line_endings
== 0
417 (*ct
->c_ceclosefnx
) (ct
);