]>
diplodocus.org Git - nmh/blob - uip/mhoutsbr.c
3 * mhoutsbr.c -- routines to output MIME messages
4 * -- given a Content structure
6 * This code is Copyright (c) 2002, by the authors of nmh. See the
7 * COPYRIGHT file in the root directory of the nmh distribution for
8 * complete copyright information.
18 #include <h/mhparse.h>
24 int output_message_fp (CT
, FILE *, char *);
29 static int output_content (CT
, FILE *);
30 static void output_headers (CT
, FILE *);
31 static int writeExternalBody (CT
, FILE *);
32 static int write8Bit (CT
, FILE *);
33 static int writeQuoted (CT
, FILE *);
34 static int writeBase64ct (CT
, FILE *);
38 * Main routine to output a MIME message contained
39 * in a Content structure, to a file. Any necessary
40 * transfer encoding is added.
44 output_message_fp (CT ct
, FILE *fp
, char *file
)
46 if (output_content (ct
, fp
) == NOTOK
)
50 advise ((file
?file
:"<FILE*>"), "error writing to");
58 * Output a Content structure to a file.
62 output_content (CT ct
, FILE *out
)
65 CI ci
= &ct
->c_ctinfo
;
66 char *boundary
= "", *cp
;
68 if ((cp
= get_param(ci
->ci_first_pm
, "boundary", '-', 0)))
72 * Output all header fields for this content
74 output_headers (ct
, out
);
77 * If this is the internal content structure for a
78 * "message/external", then we are done with the
79 * headers (since it has no body).
82 if (*boundary
!= '\0')
88 * Now output the content bodies.
99 m
= (struct multipart
*) ct
->c_ctparams
;
101 if (m
->mp_content_before
) {
102 fputs(m
->mp_content_before
, out
);
105 for (part
= m
->mp_parts
; part
; part
= part
->mp_next
) {
106 CT p
= part
->mp_part
;
108 fprintf (out
, "\n--%s\n", boundary
);
109 if (output_content (p
, out
) == NOTOK
) {
110 if (*boundary
!= '\0')
115 fprintf (out
, "\n--%s--\n", boundary
);
117 if (m
->mp_content_after
) {
118 fputs(m
->mp_content_after
, out
);
125 if (ct
->c_subtype
== MESSAGE_EXTERNAL
) {
128 e
= (struct exbody
*) ct
->c_ctparams
;
129 if (output_content (e
->eb_content
, out
) == NOTOK
)
132 /* output phantom body for access-type "mail-server" */
134 writeExternalBody (ct
, out
);
136 result
= write8Bit (ct
, out
);
141 * Handle discrete types (text/application/audio/image/video)
144 switch (ct
->c_encoding
) {
146 /* Special case: if this is a non-MIME message with no
147 body, don't emit the newline that would appear between
148 the headers and body. In that case, the call to
149 write8Bit() shouldn't be needed, but is harmless. */
150 if (ct
->c_ctinfo
.ci_first_pm
!= NULL
|| ct
->c_begin
== 0 ||
151 ct
->c_begin
!= ct
->c_end
) {
154 result
= write8Bit (ct
, out
);
159 result
= write8Bit (ct
, out
);
164 result
= writeQuoted (ct
, out
);
169 result
= writeBase64ct (ct
, out
);
173 if (ct
->c_type
== CT_TEXT
) {
174 /* So that mhfixmsg can decode to binary text. */
176 result
= write8Bit (ct
, out
);
178 advise (NULL
, "can't handle binary transfer encoding in content");
184 advise (NULL
, "unknown transfer encoding in content");
191 if (*boundary
!= '\0')
199 * Output all the header fields for a content
203 output_headers (CT ct
, FILE *out
)
209 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
216 * Write the phantom body for access-type "mail-server".
220 writeExternalBody (CT ct
, FILE *out
)
223 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
226 for (cp
= e
->eb_body
; *cp
; cp
++) {
227 CT ct2
= e
->eb_content
;
228 CI ci2
= &ct2
->c_ctinfo
;
234 dp
= trimcpy (ct2
->c_id
);
242 dp
= get_param(ci2
->ci_first_pm
, "name", '_', 0);
250 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
251 dp
= output_params(strlen(ci2
->ci_type
) +
252 strlen(ci2
->ci_subtype
) + 1,
253 ci2
->ci_first_pm
, NULL
, 0);
290 * Output a content without any transfer encoding
294 write8Bit (CT ct
, FILE *out
)
298 char c
, *file
, buffer
[BUFSIZ
];
299 CE ce
= &ct
->c_cefile
;
302 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
306 while ((inbytes
= fread (buffer
, 1, sizeof buffer
, ce
->ce_fp
)) > 0) {
307 c
= buffer
[inbytes
- 1];
308 if (fwrite (buffer
, 1, inbytes
, out
) < inbytes
) {
309 advise ("write8Bit", "fwrite");
315 (*ct
->c_ceclosefnx
) (ct
);
321 * Output a content using quoted-printable
325 writeQuoted (CT ct
, FILE *out
)
330 CE ce
= &ct
->c_cefile
;
337 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
340 while ((gotlen
= getline(&bufp
, &buflen
, ce
->ce_fp
)) != -1) {
342 cp
= bufp
+ gotlen
- 1;
343 if ((c
= *cp
) == '\n')
347 * if the line starts with "From ", encode the 'F' so it
348 * doesn't falsely match an mbox delimiter.
351 if (gotlen
>= 5 && has_prefix(cp
, "From ")) {
352 fprintf (out
, "=%02X", 'F');
357 for (; cp
< bufp
+ gotlen
; cp
++) {
358 if (n
> CPERLIN
- 3) {
371 if (*cp
< '!' || *cp
> '~')
379 fprintf (out
, "=%02X", *cp
& 0xff);
386 if (cp
> bufp
&& (*--cp
== ' ' || *cp
== '\t'))
397 (*ct
->c_ceclosefnx
) (ct
);
404 * Output a content using base64
408 writeBase64ct (CT ct
, FILE *out
)
412 CE ce
= &ct
->c_cefile
;
415 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
418 result
= writeBase64aux (ce
->ce_fp
, out
,
419 ct
->c_type
== CT_TEXT
&& ct
->c_ctparams
420 ? ((struct text
*) ct
->c_ctparams
)->lf_line_endings
== 0
422 (*ct
->c_ceclosefnx
) (ct
);