]>
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.
17 #include <h/mhparse.h>
23 int output_message (CT
, char *);
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");
57 output_message (CT ct
, char *file
)
62 if (! strcmp (file
, "-")) {
64 } else if ((fp
= fopen (file
, "w")) == NULL
) {
65 advise (file
, "unable to open for writing");
68 status
= output_message_fp(ct
, fp
, file
);
69 if (strcmp (file
, "-")) fclose(fp
);
75 * Output a Content structure to a file.
79 output_content (CT ct
, FILE *out
)
82 CI ci
= &ct
->c_ctinfo
;
83 char *boundary
= "", *cp
;
85 if ((cp
= get_param(ci
->ci_first_pm
, "boundary", '-', 0)))
89 * Output all header fields for this content
91 output_headers (ct
, out
);
94 * If this is the internal content structure for a
95 * "message/external", then we are done with the
96 * headers (since it has no body).
99 if (boundary
&& *boundary
!= '\0')
105 * Now output the content bodies.
107 switch (ct
->c_type
) {
116 m
= (struct multipart
*) ct
->c_ctparams
;
118 if (m
->mp_content_before
) {
119 fprintf (out
, "%s", m
->mp_content_before
);
122 for (part
= m
->mp_parts
; part
; part
= part
->mp_next
) {
123 CT p
= part
->mp_part
;
125 fprintf (out
, "\n--%s\n", boundary
);
126 if (output_content (p
, out
) == NOTOK
) {
127 if (boundary
&& *boundary
!= '\0')
132 fprintf (out
, "\n--%s--\n", boundary
);
134 if (m
->mp_content_after
) {
135 fprintf (out
, "%s", m
->mp_content_after
);
142 if (ct
->c_subtype
== MESSAGE_EXTERNAL
) {
145 e
= (struct exbody
*) ct
->c_ctparams
;
146 if (output_content (e
->eb_content
, out
) == NOTOK
)
149 /* output phantom body for access-type "mail-server" */
151 writeExternalBody (ct
, out
);
153 result
= write8Bit (ct
, out
);
158 * Handle discrete types (text/application/audio/image/video)
161 switch (ct
->c_encoding
) {
163 /* Special case: if this is a non-MIME message with no
164 body, don't emit the newline that would appear between
165 the headers and body. In that case, the call to
166 write8Bit() shouldn't be needed, but is harmless. */
167 if (ct
->c_ctinfo
.ci_first_pm
!= NULL
|| ct
->c_begin
== 0 ||
168 ct
->c_begin
!= ct
->c_end
) {
171 result
= write8Bit (ct
, out
);
176 result
= write8Bit (ct
, out
);
181 result
= writeQuoted (ct
, out
);
186 result
= writeBase64ct (ct
, out
);
190 if (ct
->c_type
== CT_TEXT
) {
191 /* So that mhfixmsg can decode to binary text. */
193 result
= write8Bit (ct
, out
);
195 advise (NULL
, "can't handle binary transfer encoding in content");
201 advise (NULL
, "unknown transfer encoding in content");
208 if (boundary
&& *boundary
!= '\0')
216 * Output all the header fields for a content
220 output_headers (CT ct
, FILE *out
)
226 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
233 * Write the phantom body for access-type "mail-server".
237 writeExternalBody (CT ct
, FILE *out
)
240 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
243 for (cp
= e
->eb_body
; *cp
; cp
++) {
244 CT ct2
= e
->eb_content
;
245 CI ci2
= &ct2
->c_ctinfo
;
251 dp
= trimcpy (ct2
->c_id
);
259 dp
= get_param(ci2
->ci_first_pm
, "name", '_', 0);
267 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
268 dp
= output_params(strlen(ci2
->ci_type
) +
269 strlen(ci2
->ci_subtype
) + 1,
270 ci2
->ci_first_pm
, NULL
, 0);
307 * Output a content without any transfer encoding
311 write8Bit (CT ct
, FILE *out
)
315 char c
, *file
, buffer
[BUFSIZ
];
316 CE ce
= &ct
->c_cefile
;
319 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
323 while ((inbytes
= fread (buffer
, 1, sizeof buffer
, ce
->ce_fp
)) > 0) {
324 c
= buffer
[inbytes
- 1];
325 if (fwrite (buffer
, 1, inbytes
, out
) < inbytes
) {
326 advise ("write8Bit", "fwrite");
332 (*ct
->c_ceclosefnx
) (ct
);
338 * Output a content using quoted-printable
342 writeQuoted (CT ct
, FILE *out
)
347 CE ce
= &ct
->c_cefile
;
354 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
357 while ((gotlen
= getline(&bufp
, &buflen
, ce
->ce_fp
)) != -1) {
359 cp
= bufp
+ gotlen
- 1;
360 if ((c
= *cp
) == '\n')
364 * if the line starts with "From ", encode the 'F' so it
365 * doesn't falsely match an mbox delimiter.
368 if (gotlen
>= 5 && strncmp (cp
, "From ", 5) == 0) {
369 fprintf (out
, "=%02X", 'F');
374 for (; cp
< bufp
+ gotlen
; cp
++) {
375 if (n
> CPERLIN
- 3) {
388 if (*cp
< '!' || *cp
> '~')
396 fprintf (out
, "=%02X", *cp
& 0xff);
403 if (cp
> bufp
&& (*--cp
== ' ' || *cp
== '\t'))
414 (*ct
->c_ceclosefnx
) (ct
);
421 * Output a content using base64
425 writeBase64ct (CT ct
, FILE *out
)
429 CE ce
= &ct
->c_cefile
;
432 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
435 result
= writeBase64aux (ce
->ce_fp
, out
,
436 ct
->c_type
== CT_TEXT
&& ct
->c_ctparams
437 ? ((struct text
*) ct
->c_ctparams
)->lf_line_endings
== 0
439 (*ct
->c_ceclosefnx
) (ct
);