]>
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>
22 int output_message_fp (CT
, FILE *, char *);
27 static int output_content (CT
, FILE *);
28 static void output_headers (CT
, FILE *);
29 static int writeExternalBody (CT
, FILE *);
30 static int write8Bit (CT
, FILE *);
31 static int writeQuoted (CT
, FILE *);
32 static int writeBase64ct (CT
, FILE *);
36 * Main routine to output a MIME message contained
37 * in a Content structure, to a file. Any necessary
38 * transfer encoding is added.
42 output_message_fp (CT ct
, FILE *fp
, char *file
)
44 if (output_content (ct
, fp
) == NOTOK
)
48 advise ((file
?file
:"<FILE*>"), "error writing to");
56 * Output a Content structure to a file.
60 output_content (CT ct
, FILE *out
)
63 CI ci
= &ct
->c_ctinfo
;
64 char *boundary
= "", *cp
;
66 if ((cp
= get_param(ci
->ci_first_pm
, "boundary", '-', 0)))
70 * Output all header fields for this content
72 output_headers (ct
, out
);
75 * If this is the internal content structure for a
76 * "message/external", then we are done with the
77 * headers (since it has no body).
80 if (*boundary
!= '\0')
86 * Now output the content bodies.
97 m
= (struct multipart
*) ct
->c_ctparams
;
99 if (m
->mp_content_before
) {
100 fputs(m
->mp_content_before
, out
);
103 for (part
= m
->mp_parts
; part
; part
= part
->mp_next
) {
104 CT p
= part
->mp_part
;
106 fprintf (out
, "\n--%s\n", boundary
);
107 if (output_content (p
, out
) == NOTOK
) {
108 if (*boundary
!= '\0')
113 fprintf (out
, "\n--%s--\n", boundary
);
115 if (m
->mp_content_after
) {
116 fputs(m
->mp_content_after
, out
);
123 if (ct
->c_subtype
== MESSAGE_EXTERNAL
) {
126 e
= (struct exbody
*) ct
->c_ctparams
;
127 if (output_content (e
->eb_content
, out
) == NOTOK
)
130 /* output phantom body for access-type "mail-server" */
132 writeExternalBody (ct
, out
);
134 result
= write8Bit (ct
, out
);
139 * Handle discrete types (text/application/audio/image/video)
142 switch (ct
->c_encoding
) {
144 /* Special case: if this is a non-MIME message with no
145 body, don't emit the newline that would appear between
146 the headers and body. In that case, the call to
147 write8Bit() shouldn't be needed, but is harmless. */
148 if (ct
->c_ctinfo
.ci_first_pm
!= NULL
|| ct
->c_begin
== 0 ||
149 ct
->c_begin
!= ct
->c_end
) {
152 result
= write8Bit (ct
, out
);
157 result
= write8Bit (ct
, out
);
162 result
= writeQuoted (ct
, out
);
167 result
= writeBase64ct (ct
, out
);
171 if (ct
->c_type
== CT_TEXT
) {
172 /* So that mhfixmsg can decode to binary text. */
174 result
= write8Bit (ct
, out
);
176 inform("can't handle binary transfer encoding in content");
182 inform("unknown transfer encoding in content");
189 if (*boundary
!= '\0')
197 * Output all the header fields for a content
201 output_headers (CT ct
, FILE *out
)
207 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
214 * Write the phantom body for access-type "mail-server".
218 writeExternalBody (CT ct
, FILE *out
)
221 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
224 for (cp
= e
->eb_body
; *cp
; cp
++) {
225 CT ct2
= e
->eb_content
;
226 CI ci2
= &ct2
->c_ctinfo
;
232 dp
= trimcpy (ct2
->c_id
);
240 dp
= get_param(ci2
->ci_first_pm
, "name", '_', 0);
248 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
249 dp
= output_params(strlen(ci2
->ci_type
) +
250 strlen(ci2
->ci_subtype
) + 1,
251 ci2
->ci_first_pm
, NULL
, 0);
288 * Output a content without any transfer encoding
292 write8Bit (CT ct
, FILE *out
)
296 char c
, *file
, buffer
[BUFSIZ
];
297 CE ce
= &ct
->c_cefile
;
300 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
304 while ((inbytes
= fread (buffer
, 1, sizeof buffer
, ce
->ce_fp
)) > 0) {
305 c
= buffer
[inbytes
- 1];
306 if (fwrite (buffer
, 1, inbytes
, out
) < inbytes
) {
307 advise ("write8Bit", "fwrite");
313 (*ct
->c_ceclosefnx
) (ct
);
319 * Output a content using quoted-printable
323 writeQuoted (CT ct
, FILE *out
)
328 CE ce
= &ct
->c_cefile
;
335 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
338 while ((gotlen
= getline(&bufp
, &buflen
, ce
->ce_fp
)) != -1) {
340 cp
= bufp
+ gotlen
- 1;
341 if ((c
= *cp
) == '\n')
345 * if the line starts with "From ", encode the 'F' so it
346 * doesn't falsely match an mbox delimiter.
349 if (gotlen
>= 5 && has_prefix(cp
, "From ")) {
350 fprintf (out
, "=%02X", 'F');
355 for (; cp
< bufp
+ gotlen
; cp
++) {
356 if (n
> CPERLIN
- 3) {
369 if (*cp
< '!' || *cp
> '~')
377 fprintf (out
, "=%02X", *cp
& 0xff);
384 if (cp
> bufp
&& (*--cp
== ' ' || *cp
== '\t'))
395 (*ct
->c_ceclosefnx
) (ct
);
402 * Output a content using base64
406 writeBase64ct (CT ct
, FILE *out
)
410 CE ce
= &ct
->c_cefile
;
413 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
416 result
= writeBase64aux (ce
->ce_fp
, out
,
417 ct
->c_type
== CT_TEXT
&& ct
->c_ctparams
418 ? ((struct text
*) ct
->c_ctparams
)->lf_line_endings
== 0
420 (*ct
->c_ceclosefnx
) (ct
);