]>
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/error.h"
17 #include "h/mhparse.h"
19 #include "sbr/base64.h"
25 static int output_content (CT
, FILE *);
26 static void output_headers (CT
, FILE *);
27 static int writeExternalBody (CT
, FILE *);
28 static int write8Bit (CT
, FILE *);
29 static int writeQuoted (CT
, FILE *);
30 static int writeBase64ct (CT
, FILE *);
34 * Main routine to output a MIME message contained
35 * in a Content structure, to a file. Any necessary
36 * transfer encoding is added.
40 output_message_fp (CT ct
, FILE *fp
, char *file
)
42 if (output_content (ct
, fp
) == NOTOK
)
46 advise ((file
?file
:"<FILE*>"), "error writing to");
54 * Output a Content structure to a file.
58 output_content (CT ct
, FILE *out
)
61 CI ci
= &ct
->c_ctinfo
;
62 char *boundary
= "", *cp
;
64 if ((cp
= get_param(ci
->ci_first_pm
, "boundary", '-', 0)))
68 * Output all header fields for this content
70 output_headers (ct
, out
);
73 * If this is the internal content structure for a
74 * "message/external", then we are done with the
75 * headers (since it has no body).
78 if (*boundary
!= '\0')
84 * Now output the content bodies.
95 m
= (struct multipart
*) ct
->c_ctparams
;
97 if (m
->mp_content_before
) {
98 fputs(m
->mp_content_before
, out
);
101 for (part
= m
->mp_parts
; part
; part
= part
->mp_next
) {
102 CT p
= part
->mp_part
;
104 fprintf (out
, "\n--%s\n", boundary
);
105 if (output_content (p
, out
) == NOTOK
) {
106 if (*boundary
!= '\0')
111 fprintf (out
, "\n--%s--\n", boundary
);
113 if (m
->mp_content_after
) {
114 fputs(m
->mp_content_after
, out
);
121 if (ct
->c_subtype
== MESSAGE_EXTERNAL
) {
124 e
= (struct exbody
*) ct
->c_ctparams
;
125 if (output_content (e
->eb_content
, out
) == NOTOK
)
128 /* output phantom body for access-type "mail-server" */
130 writeExternalBody (ct
, out
);
132 result
= write8Bit (ct
, out
);
137 * Handle discrete types (text/application/audio/image/video)
140 switch (ct
->c_encoding
) {
142 /* Special case: if this is a non-MIME message with no
143 body, don't emit the newline that would appear between
144 the headers and body. In that case, the call to
145 write8Bit() shouldn't be needed, but is harmless. */
146 if (ct
->c_ctinfo
.ci_first_pm
!= NULL
|| ct
->c_begin
== 0 ||
147 ct
->c_begin
!= ct
->c_end
) {
150 result
= write8Bit (ct
, out
);
155 result
= write8Bit (ct
, out
);
160 result
= writeQuoted (ct
, out
);
165 result
= writeBase64ct (ct
, out
);
169 if (ct
->c_type
== CT_TEXT
) {
170 /* So that mhfixmsg can decode to binary text. */
172 result
= write8Bit (ct
, out
);
174 inform("can't handle binary transfer encoding in content");
180 inform("unknown transfer encoding in content");
187 if (*boundary
!= '\0')
195 * Output all the header fields for a content
199 output_headers (CT ct
, FILE *out
)
205 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
212 * Write the phantom body for access-type "mail-server".
216 writeExternalBody (CT ct
, FILE *out
)
219 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
222 for (cp
= e
->eb_body
; *cp
; cp
++) {
223 CT ct2
= e
->eb_content
;
224 CI ci2
= &ct2
->c_ctinfo
;
230 dp
= trimcpy (ct2
->c_id
);
238 dp
= get_param(ci2
->ci_first_pm
, "name", '_', 0);
246 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
247 dp
= output_params(strlen(ci2
->ci_type
) +
248 strlen(ci2
->ci_subtype
) + 1,
249 ci2
->ci_first_pm
, NULL
, 0);
286 * Output a content without any transfer encoding
290 write8Bit (CT ct
, FILE *out
)
294 char c
, *file
, buffer
[BUFSIZ
];
295 CE ce
= &ct
->c_cefile
;
298 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
302 while ((inbytes
= fread (buffer
, 1, sizeof buffer
, ce
->ce_fp
)) > 0) {
303 c
= buffer
[inbytes
- 1];
304 if (fwrite (buffer
, 1, inbytes
, out
) < inbytes
) {
305 advise ("write8Bit", "fwrite");
311 (*ct
->c_ceclosefnx
) (ct
);
317 * Output a content using quoted-printable
321 writeQuoted (CT ct
, FILE *out
)
326 CE ce
= &ct
->c_cefile
;
333 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
336 while ((gotlen
= getline(&bufp
, &buflen
, ce
->ce_fp
)) != -1) {
338 cp
= bufp
+ gotlen
- 1;
339 if ((c
= *cp
) == '\n')
343 * if the line starts with "From ", encode the 'F' so it
344 * doesn't falsely match an mbox delimiter.
347 if (gotlen
>= 5 && has_prefix(cp
, "From ")) {
348 fprintf (out
, "=%02X", 'F');
353 for (; cp
< bufp
+ gotlen
; cp
++) {
354 if (n
> CPERLIN
- 3) {
367 if (*cp
< '!' || *cp
> '~')
375 fprintf (out
, "=%02X", *cp
& 0xff);
382 if (cp
> bufp
&& (*--cp
== ' ' || *cp
== '\t'))
393 (*ct
->c_ceclosefnx
) (ct
);
400 * Output a content using base64
404 writeBase64ct (CT ct
, FILE *out
)
408 CE ce
= &ct
->c_cefile
;
411 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
414 result
= writeBase64aux (ce
->ce_fp
, out
,
415 ct
->c_type
== CT_TEXT
&& ct
->c_ctparams
416 ? ((struct text
*) ct
->c_ctparams
)->lf_line_endings
== 0
418 (*ct
->c_ceclosefnx
) (ct
);