]>
diplodocus.org Git - nmh/blob - uip/mhoutsbr.c
01eb91dd309ee9107e579f7e8b0203266d456da4
2 * mhoutsbr.c -- routines to output MIME messages
3 * -- given a Content structure
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
17 #include <h/mhparse.h>
23 int output_message_fp (CT
, FILE *, char *);
28 static int output_content (CT
, FILE *);
29 static void output_headers (CT
, FILE *);
30 static int writeExternalBody (CT
, FILE *);
31 static int write8Bit (CT
, FILE *);
32 static int writeQuoted (CT
, FILE *);
33 static int writeBase64ct (CT
, FILE *);
37 * Main routine to output a MIME message contained
38 * in a Content structure, to a file. Any necessary
39 * transfer encoding is added.
43 output_message_fp (CT ct
, FILE *fp
, char *file
)
45 if (output_content (ct
, fp
) == NOTOK
)
49 advise ((file
?file
:"<FILE*>"), "error writing to");
57 * Output a Content structure to a file.
61 output_content (CT ct
, FILE *out
)
64 CI ci
= &ct
->c_ctinfo
;
65 char *boundary
= "", *cp
;
67 if ((cp
= get_param(ci
->ci_first_pm
, "boundary", '-', 0)))
71 * Output all header fields for this content
73 output_headers (ct
, out
);
76 * If this is the internal content structure for a
77 * "message/external", then we are done with the
78 * headers (since it has no body).
81 if (*boundary
!= '\0')
87 * Now output the content bodies.
98 m
= (struct multipart
*) ct
->c_ctparams
;
100 if (m
->mp_content_before
) {
101 fputs(m
->mp_content_before
, out
);
104 for (part
= m
->mp_parts
; part
; part
= part
->mp_next
) {
105 CT p
= part
->mp_part
;
107 fprintf (out
, "\n--%s\n", boundary
);
108 if (output_content (p
, out
) == NOTOK
) {
109 if (*boundary
!= '\0')
114 fprintf (out
, "\n--%s--\n", boundary
);
116 if (m
->mp_content_after
) {
117 fputs(m
->mp_content_after
, out
);
124 if (ct
->c_subtype
== MESSAGE_EXTERNAL
) {
127 e
= (struct exbody
*) ct
->c_ctparams
;
128 if (output_content (e
->eb_content
, out
) == NOTOK
)
131 /* output phantom body for access-type "mail-server" */
133 writeExternalBody (ct
, out
);
135 result
= write8Bit (ct
, out
);
140 * Handle discrete types (text/application/audio/image/video)
143 switch (ct
->c_encoding
) {
145 /* Special case: if this is a non-MIME message with no
146 body, don't emit the newline that would appear between
147 the headers and body. In that case, the call to
148 write8Bit() shouldn't be needed, but is harmless. */
149 if (ct
->c_ctinfo
.ci_first_pm
!= NULL
|| ct
->c_begin
== 0 ||
150 ct
->c_begin
!= ct
->c_end
) {
153 result
= write8Bit (ct
, out
);
158 result
= write8Bit (ct
, out
);
163 result
= writeQuoted (ct
, out
);
168 result
= writeBase64ct (ct
, out
);
172 if (ct
->c_type
== CT_TEXT
) {
173 /* So that mhfixmsg can decode to binary text. */
175 result
= write8Bit (ct
, out
);
177 inform("can't handle binary transfer encoding in content");
183 inform("unknown transfer encoding in content");
190 if (*boundary
!= '\0')
198 * Output all the header fields for a content
202 output_headers (CT ct
, FILE *out
)
208 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
215 * Write the phantom body for access-type "mail-server".
219 writeExternalBody (CT ct
, FILE *out
)
222 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
225 for (cp
= e
->eb_body
; *cp
; cp
++) {
226 CT ct2
= e
->eb_content
;
227 CI ci2
= &ct2
->c_ctinfo
;
233 dp
= trimcpy (ct2
->c_id
);
241 dp
= get_param(ci2
->ci_first_pm
, "name", '_', 0);
249 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
250 dp
= output_params(strlen(ci2
->ci_type
) +
251 strlen(ci2
->ci_subtype
) + 1,
252 ci2
->ci_first_pm
, NULL
, 0);
289 * Output a content without any transfer encoding
293 write8Bit (CT ct
, FILE *out
)
297 char c
, *file
, buffer
[BUFSIZ
];
298 CE ce
= &ct
->c_cefile
;
301 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
305 while ((inbytes
= fread (buffer
, 1, sizeof buffer
, ce
->ce_fp
)) > 0) {
306 c
= buffer
[inbytes
- 1];
307 if (fwrite (buffer
, 1, inbytes
, out
) < inbytes
) {
308 advise ("write8Bit", "fwrite");
314 (*ct
->c_ceclosefnx
) (ct
);
320 * Output a content using quoted-printable
324 writeQuoted (CT ct
, FILE *out
)
329 CE ce
= &ct
->c_cefile
;
336 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
339 while ((gotlen
= getline(&bufp
, &buflen
, ce
->ce_fp
)) != -1) {
341 cp
= bufp
+ gotlen
- 1;
342 if ((c
= *cp
) == '\n')
346 * if the line starts with "From ", encode the 'F' so it
347 * doesn't falsely match an mbox delimiter.
350 if (gotlen
>= 5 && has_prefix(cp
, "From ")) {
351 fprintf (out
, "=%02X", 'F');
356 for (; cp
< bufp
+ gotlen
; cp
++) {
357 if (n
> CPERLIN
- 3) {
370 if (*cp
< '!' || *cp
> '~')
378 fprintf (out
, "=%02X", *cp
& 0xff);
385 if (cp
> bufp
&& (*--cp
== ' ' || *cp
== '\t'))
396 (*ct
->c_ceclosefnx
) (ct
);
403 * Output a content using base64
407 writeBase64ct (CT ct
, FILE *out
)
411 CE ce
= &ct
->c_cefile
;
414 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
417 result
= writeBase64aux (ce
->ce_fp
, out
,
418 ct
->c_type
== CT_TEXT
&& ct
->c_ctparams
419 ? ((struct text
*) ct
->c_ctparams
)->lf_line_endings
== 0
421 (*ct
->c_ceclosefnx
) (ct
);