]>
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.
10 #include "sbr/trimcpy.h"
11 #include "sbr/error.h"
18 #include "h/mhparse.h"
20 #include "sbr/base64.h"
26 static int output_content (CT
, FILE *);
27 static void output_headers (CT
, FILE *);
28 static int writeExternalBody (CT
, FILE *);
29 static int write8Bit (CT
, FILE *);
30 static int writeQuoted (CT
, FILE *);
31 static int writeBase64ct (CT
, FILE *);
35 * Main routine to output a MIME message contained
36 * in a Content structure, to a file. Any necessary
37 * transfer encoding is added.
41 output_message_fp (CT ct
, FILE *fp
, char *file
)
43 if (output_content (ct
, fp
) == NOTOK
)
47 advise ((file
?file
:"<FILE*>"), "error writing to");
55 * Output a Content structure to a file.
59 output_content (CT ct
, FILE *out
)
62 CI ci
= &ct
->c_ctinfo
;
63 char *boundary
= "", *cp
;
65 if ((cp
= get_param(ci
->ci_first_pm
, "boundary", '-', 0)))
69 * Output all header fields for this content
71 output_headers (ct
, out
);
74 * If this is the internal content structure for a
75 * "message/external", then we are done with the
76 * headers (since it has no body).
79 if (*boundary
!= '\0')
85 * Now output the content bodies.
96 m
= (struct multipart
*) ct
->c_ctparams
;
98 if (m
->mp_content_before
) {
99 fputs(m
->mp_content_before
, out
);
102 for (part
= m
->mp_parts
; part
; part
= part
->mp_next
) {
103 CT p
= part
->mp_part
;
105 fprintf (out
, "\n--%s\n", boundary
);
106 if (output_content (p
, out
) == NOTOK
) {
107 if (*boundary
!= '\0')
112 fprintf (out
, "\n--%s--\n", boundary
);
114 if (m
->mp_content_after
) {
115 fputs(m
->mp_content_after
, out
);
122 if (ct
->c_subtype
== MESSAGE_EXTERNAL
) {
125 e
= (struct exbody
*) ct
->c_ctparams
;
126 if (output_content (e
->eb_content
, out
) == NOTOK
)
129 /* output phantom body for access-type "mail-server" */
131 writeExternalBody (ct
, out
);
133 result
= write8Bit (ct
, out
);
138 * Handle discrete types (text/application/audio/image/video)
141 switch (ct
->c_encoding
) {
143 /* Special case: if this is a non-MIME message with no
144 body, don't emit the newline that would appear between
145 the headers and body. In that case, the call to
146 write8Bit() shouldn't be needed, but is harmless. */
147 if (ct
->c_ctinfo
.ci_first_pm
!= NULL
|| ct
->c_begin
== 0 ||
148 ct
->c_begin
!= ct
->c_end
) {
151 result
= write8Bit (ct
, out
);
156 result
= write8Bit (ct
, out
);
161 result
= writeQuoted (ct
, out
);
166 result
= writeBase64ct (ct
, out
);
170 if (ct
->c_type
== CT_TEXT
) {
171 /* So that mhfixmsg can decode to binary text. */
173 result
= write8Bit (ct
, out
);
175 inform("can't handle binary transfer encoding in content");
181 inform("unknown transfer encoding in content");
188 if (*boundary
!= '\0')
196 * Output all the header fields for a content
200 output_headers (CT ct
, FILE *out
)
206 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
213 * Write the phantom body for access-type "mail-server".
217 writeExternalBody (CT ct
, FILE *out
)
220 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
223 for (cp
= e
->eb_body
; *cp
; cp
++) {
224 CT ct2
= e
->eb_content
;
225 CI ci2
= &ct2
->c_ctinfo
;
231 dp
= trimcpy (ct2
->c_id
);
239 dp
= get_param(ci2
->ci_first_pm
, "name", '_', 0);
247 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
248 dp
= output_params(strlen(ci2
->ci_type
) +
249 strlen(ci2
->ci_subtype
) + 1,
250 ci2
->ci_first_pm
, NULL
, 0);
287 * Output a content without any transfer encoding
291 write8Bit (CT ct
, FILE *out
)
295 char c
, *file
, buffer
[BUFSIZ
];
296 CE ce
= &ct
->c_cefile
;
299 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
303 while ((inbytes
= fread (buffer
, 1, sizeof buffer
, ce
->ce_fp
)) > 0) {
304 c
= buffer
[inbytes
- 1];
305 if (fwrite (buffer
, 1, inbytes
, out
) < inbytes
) {
306 advise ("write8Bit", "fwrite");
312 (*ct
->c_ceclosefnx
) (ct
);
318 * Output a content using quoted-printable
322 writeQuoted (CT ct
, FILE *out
)
327 CE ce
= &ct
->c_cefile
;
334 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
337 while ((gotlen
= getline(&bufp
, &buflen
, ce
->ce_fp
)) != -1) {
339 cp
= bufp
+ gotlen
- 1;
340 if ((c
= *cp
) == '\n')
344 * if the line starts with "From ", encode the 'F' so it
345 * doesn't falsely match an mbox delimiter.
348 if (gotlen
>= 5 && has_prefix(cp
, "From ")) {
349 fprintf (out
, "=%02X", 'F');
354 for (; cp
< bufp
+ gotlen
; cp
++) {
355 if (n
> CPERLIN
- 3) {
368 if (*cp
< '!' || *cp
> '~')
376 fprintf (out
, "=%02X", *cp
& 0xff);
383 if (cp
> bufp
&& (*--cp
== ' ' || *cp
== '\t'))
394 (*ct
->c_ceclosefnx
) (ct
);
401 * Output a content using base64
405 writeBase64ct (CT ct
, FILE *out
)
409 CE ce
= &ct
->c_cefile
;
412 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
415 result
= writeBase64aux (ce
->ce_fp
, out
,
416 ct
->c_type
== CT_TEXT
&& ct
->c_ctparams
417 ? ((struct text
*) ct
->c_ctparams
)->lf_line_endings
== 0
419 (*ct
->c_ceclosefnx
) (ct
);