]>
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>
23 static int output_content (CT
, FILE *);
24 static void output_headers (CT
, FILE *);
25 static int writeExternalBody (CT
, FILE *);
26 static int write8Bit (CT
, FILE *);
27 static int writeQuoted (CT
, FILE *);
28 static int writeBase64ct (CT
, FILE *);
32 * Main routine to output a MIME message contained
33 * in a Content structure, to a file. Any necessary
34 * transfer encoding is added.
38 output_message_fp (CT ct
, FILE *fp
, char *file
)
40 if (output_content (ct
, fp
) == NOTOK
)
44 advise ((file
?file
:"<FILE*>"), "error writing to");
52 * Output a Content structure to a file.
56 output_content (CT ct
, FILE *out
)
59 CI ci
= &ct
->c_ctinfo
;
60 char *boundary
= "", *cp
;
62 if ((cp
= get_param(ci
->ci_first_pm
, "boundary", '-', 0)))
66 * Output all header fields for this content
68 output_headers (ct
, out
);
71 * If this is the internal content structure for a
72 * "message/external", then we are done with the
73 * headers (since it has no body).
76 if (*boundary
!= '\0')
82 * Now output the content bodies.
93 m
= (struct multipart
*) ct
->c_ctparams
;
95 if (m
->mp_content_before
) {
96 fputs(m
->mp_content_before
, out
);
99 for (part
= m
->mp_parts
; part
; part
= part
->mp_next
) {
100 CT p
= part
->mp_part
;
102 fprintf (out
, "\n--%s\n", boundary
);
103 if (output_content (p
, out
) == NOTOK
) {
104 if (*boundary
!= '\0')
109 fprintf (out
, "\n--%s--\n", boundary
);
111 if (m
->mp_content_after
) {
112 fputs(m
->mp_content_after
, out
);
119 if (ct
->c_subtype
== MESSAGE_EXTERNAL
) {
122 e
= (struct exbody
*) ct
->c_ctparams
;
123 if (output_content (e
->eb_content
, out
) == NOTOK
)
126 /* output phantom body for access-type "mail-server" */
128 writeExternalBody (ct
, out
);
130 result
= write8Bit (ct
, out
);
135 * Handle discrete types (text/application/audio/image/video)
138 switch (ct
->c_encoding
) {
140 /* Special case: if this is a non-MIME message with no
141 body, don't emit the newline that would appear between
142 the headers and body. In that case, the call to
143 write8Bit() shouldn't be needed, but is harmless. */
144 if (ct
->c_ctinfo
.ci_first_pm
!= NULL
|| ct
->c_begin
== 0 ||
145 ct
->c_begin
!= ct
->c_end
) {
148 result
= write8Bit (ct
, out
);
153 result
= write8Bit (ct
, out
);
158 result
= writeQuoted (ct
, out
);
163 result
= writeBase64ct (ct
, out
);
167 if (ct
->c_type
== CT_TEXT
) {
168 /* So that mhfixmsg can decode to binary text. */
170 result
= write8Bit (ct
, out
);
172 inform("can't handle binary transfer encoding in content");
178 inform("unknown transfer encoding in content");
185 if (*boundary
!= '\0')
193 * Output all the header fields for a content
197 output_headers (CT ct
, FILE *out
)
203 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
210 * Write the phantom body for access-type "mail-server".
214 writeExternalBody (CT ct
, FILE *out
)
217 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
220 for (cp
= e
->eb_body
; *cp
; cp
++) {
221 CT ct2
= e
->eb_content
;
222 CI ci2
= &ct2
->c_ctinfo
;
228 dp
= trimcpy (ct2
->c_id
);
236 dp
= get_param(ci2
->ci_first_pm
, "name", '_', 0);
244 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
245 dp
= output_params(strlen(ci2
->ci_type
) +
246 strlen(ci2
->ci_subtype
) + 1,
247 ci2
->ci_first_pm
, NULL
, 0);
284 * Output a content without any transfer encoding
288 write8Bit (CT ct
, FILE *out
)
292 char c
, *file
, buffer
[BUFSIZ
];
293 CE ce
= &ct
->c_cefile
;
296 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
300 while ((inbytes
= fread (buffer
, 1, sizeof buffer
, ce
->ce_fp
)) > 0) {
301 c
= buffer
[inbytes
- 1];
302 if (fwrite (buffer
, 1, inbytes
, out
) < inbytes
) {
303 advise ("write8Bit", "fwrite");
309 (*ct
->c_ceclosefnx
) (ct
);
315 * Output a content using quoted-printable
319 writeQuoted (CT ct
, FILE *out
)
324 CE ce
= &ct
->c_cefile
;
331 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
334 while ((gotlen
= getline(&bufp
, &buflen
, ce
->ce_fp
)) != -1) {
336 cp
= bufp
+ gotlen
- 1;
337 if ((c
= *cp
) == '\n')
341 * if the line starts with "From ", encode the 'F' so it
342 * doesn't falsely match an mbox delimiter.
345 if (gotlen
>= 5 && has_prefix(cp
, "From ")) {
346 fprintf (out
, "=%02X", 'F');
351 for (; cp
< bufp
+ gotlen
; cp
++) {
352 if (n
> CPERLIN
- 3) {
365 if (*cp
< '!' || *cp
> '~')
373 fprintf (out
, "=%02X", *cp
& 0xff);
380 if (cp
> bufp
&& (*--cp
== ' ' || *cp
== '\t'))
391 (*ct
->c_ceclosefnx
) (ct
);
398 * Output a content using base64
402 writeBase64ct (CT ct
, FILE *out
)
406 CE ce
= &ct
->c_cefile
;
409 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
412 result
= writeBase64aux (ce
->ce_fp
, out
,
413 ct
->c_type
== CT_TEXT
&& ct
->c_ctparams
414 ? ((struct text
*) ct
->c_ctparams
)->lf_line_endings
== 0
416 (*ct
->c_ceclosefnx
) (ct
);