]>
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 (CT
, char *);
25 int output_message_fp (CT
, FILE *, char *);
30 static int output_content (CT
, FILE *);
31 static void output_headers (CT
, FILE *);
32 static int writeExternalBody (CT
, FILE *);
33 static int write8Bit (CT
, FILE *);
34 static int writeQuoted (CT
, FILE *);
35 static int writeBase64ct (CT
, FILE *);
39 * Main routine to output a MIME message contained
40 * in a Content structure, to a file. Any necessary
41 * transfer encoding is added.
45 output_message_fp (CT ct
, FILE *fp
, char *file
)
47 if (output_content (ct
, fp
) == NOTOK
)
51 advise ((file
?file
:"<FILE*>"), "error writing to");
58 output_message (CT ct
, char *file
)
63 if (! strcmp (file
, "-")) {
65 } else if ((fp
= fopen (file
, "w")) == NULL
) {
66 advise (file
, "unable to open for writing");
69 status
= output_message_fp(ct
, fp
, file
);
70 if (strcmp (file
, "-")) fclose(fp
);
76 * Output a Content structure to a file.
80 output_content (CT ct
, FILE *out
)
83 CI ci
= &ct
->c_ctinfo
;
84 char *boundary
= "", *cp
;
86 if ((cp
= get_param(ci
->ci_first_pm
, "boundary", '-', 0)))
90 * Output all header fields for this content
92 output_headers (ct
, out
);
95 * If this is the internal content structure for a
96 * "message/external", then we are done with the
97 * headers (since it has no body).
100 if (*boundary
!= '\0')
106 * Now output the content bodies.
108 switch (ct
->c_type
) {
117 m
= (struct multipart
*) ct
->c_ctparams
;
119 if (m
->mp_content_before
) {
120 fprintf (out
, "%s", m
->mp_content_before
);
123 for (part
= m
->mp_parts
; part
; part
= part
->mp_next
) {
124 CT p
= part
->mp_part
;
126 fprintf (out
, "\n--%s\n", boundary
);
127 if (output_content (p
, out
) == NOTOK
) {
128 if (*boundary
!= '\0')
133 fprintf (out
, "\n--%s--\n", boundary
);
135 if (m
->mp_content_after
) {
136 fprintf (out
, "%s", m
->mp_content_after
);
143 if (ct
->c_subtype
== MESSAGE_EXTERNAL
) {
146 e
= (struct exbody
*) ct
->c_ctparams
;
147 if (output_content (e
->eb_content
, out
) == NOTOK
)
150 /* output phantom body for access-type "mail-server" */
152 writeExternalBody (ct
, out
);
154 result
= write8Bit (ct
, out
);
159 * Handle discrete types (text/application/audio/image/video)
162 switch (ct
->c_encoding
) {
164 /* Special case: if this is a non-MIME message with no
165 body, don't emit the newline that would appear between
166 the headers and body. In that case, the call to
167 write8Bit() shouldn't be needed, but is harmless. */
168 if (ct
->c_ctinfo
.ci_first_pm
!= NULL
|| ct
->c_begin
== 0 ||
169 ct
->c_begin
!= ct
->c_end
) {
172 result
= write8Bit (ct
, out
);
177 result
= write8Bit (ct
, out
);
182 result
= writeQuoted (ct
, out
);
187 result
= writeBase64ct (ct
, out
);
191 if (ct
->c_type
== CT_TEXT
) {
192 /* So that mhfixmsg can decode to binary text. */
194 result
= write8Bit (ct
, out
);
196 advise (NULL
, "can't handle binary transfer encoding in content");
202 advise (NULL
, "unknown transfer encoding in content");
209 if (*boundary
!= '\0')
217 * Output all the header fields for a content
221 output_headers (CT ct
, FILE *out
)
227 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
234 * Write the phantom body for access-type "mail-server".
238 writeExternalBody (CT ct
, FILE *out
)
241 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
244 for (cp
= e
->eb_body
; *cp
; cp
++) {
245 CT ct2
= e
->eb_content
;
246 CI ci2
= &ct2
->c_ctinfo
;
252 dp
= trimcpy (ct2
->c_id
);
260 dp
= get_param(ci2
->ci_first_pm
, "name", '_', 0);
268 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
269 dp
= output_params(strlen(ci2
->ci_type
) +
270 strlen(ci2
->ci_subtype
) + 1,
271 ci2
->ci_first_pm
, NULL
, 0);
308 * Output a content without any transfer encoding
312 write8Bit (CT ct
, FILE *out
)
316 char c
, *file
, buffer
[BUFSIZ
];
317 CE ce
= &ct
->c_cefile
;
320 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
324 while ((inbytes
= fread (buffer
, 1, sizeof buffer
, ce
->ce_fp
)) > 0) {
325 c
= buffer
[inbytes
- 1];
326 if (fwrite (buffer
, 1, inbytes
, out
) < inbytes
) {
327 advise ("write8Bit", "fwrite");
333 (*ct
->c_ceclosefnx
) (ct
);
339 * Output a content using quoted-printable
343 writeQuoted (CT ct
, FILE *out
)
348 CE ce
= &ct
->c_cefile
;
355 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
358 while ((gotlen
= getline(&bufp
, &buflen
, ce
->ce_fp
)) != -1) {
360 cp
= bufp
+ gotlen
- 1;
361 if ((c
= *cp
) == '\n')
365 * if the line starts with "From ", encode the 'F' so it
366 * doesn't falsely match an mbox delimiter.
369 if (gotlen
>= 5 && HasPrefix(cp
, "From ")) {
370 fprintf (out
, "=%02X", 'F');
375 for (; cp
< bufp
+ gotlen
; cp
++) {
376 if (n
> CPERLIN
- 3) {
389 if (*cp
< '!' || *cp
> '~')
397 fprintf (out
, "=%02X", *cp
& 0xff);
404 if (cp
> bufp
&& (*--cp
== ' ' || *cp
== '\t'))
415 (*ct
->c_ceclosefnx
) (ct
);
422 * Output a content using base64
426 writeBase64ct (CT ct
, FILE *out
)
430 CE ce
= &ct
->c_cefile
;
433 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
436 result
= writeBase64aux (ce
->ce_fp
, out
,
437 ct
->c_type
== CT_TEXT
&& ct
->c_ctparams
438 ? ((struct text
*) ct
->c_ctparams
)->lf_line_endings
== 0
440 (*ct
->c_ceclosefnx
) (ct
);