]>
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 advise (NULL
, "can't handle binary transfer encoding in content");
195 advise (NULL
, "unknown transfer encoding in content");
202 if (boundary
&& *boundary
!= '\0')
210 * Output all the header fields for a content
214 output_headers (CT ct
, FILE *out
)
220 fprintf (out
, "%s:%s", hp
->name
, hp
->value
);
227 * Write the phantom body for access-type "mail-server".
231 writeExternalBody (CT ct
, FILE *out
)
234 struct exbody
*e
= (struct exbody
*) ct
->c_ctparams
;
237 for (cp
= e
->eb_body
; *cp
; cp
++) {
238 CT ct2
= e
->eb_content
;
239 CI ci2
= &ct2
->c_ctinfo
;
245 dp
= trimcpy (ct2
->c_id
);
253 dp
= get_param(ci2
->ci_first_pm
, "name", '_', 0);
261 fprintf (out
, "%s/%s", ci2
->ci_type
, ci2
->ci_subtype
);
262 dp
= output_params(strlen(ci2
->ci_type
) +
263 strlen(ci2
->ci_subtype
) + 1,
264 ci2
->ci_first_pm
, NULL
, 0);
301 * Output a content without any transfer encoding
305 write8Bit (CT ct
, FILE *out
)
309 char c
, *file
, buffer
[BUFSIZ
];
310 CE ce
= &ct
->c_cefile
;
313 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
317 while ((inbytes
= fread (buffer
, 1, sizeof buffer
, ce
->ce_fp
)) > 0) {
318 c
= buffer
[inbytes
- 1];
319 if (fwrite (buffer
, 1, inbytes
, out
) < inbytes
) {
320 advise ("write8Bit", "fwrite");
326 (*ct
->c_ceclosefnx
) (ct
);
332 * Output a content using quoted-printable
336 writeQuoted (CT ct
, FILE *out
)
341 CE ce
= &ct
->c_cefile
;
348 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
351 while ((gotlen
= getline(&bufp
, &buflen
, ce
->ce_fp
)) != -1) {
353 cp
= bufp
+ gotlen
- 1;
354 if ((c
= *cp
) == '\n')
358 * if the line starts with "From ", encode the 'F' so it
359 * doesn't falsely match an mbox delimiter.
362 if (gotlen
>= 5 && strncmp (cp
, "From ", 5) == 0) {
363 fprintf (out
, "=%02X", 'F');
368 for (; cp
< bufp
+ gotlen
; cp
++) {
369 if (n
> CPERLIN
- 3) {
382 if (*cp
< '!' || *cp
> '~')
390 fprintf (out
, "=%02X", *cp
& 0xff);
397 if (cp
> bufp
&& (*--cp
== ' ' || *cp
== '\t'))
408 (*ct
->c_ceclosefnx
) (ct
);
415 * Output a content using base64
419 writeBase64ct (CT ct
, FILE *out
)
423 CE ce
= &ct
->c_cefile
;
426 if ((fd
= (*ct
->c_ceopenfnx
) (ct
, &file
)) == NOTOK
)
429 result
= writeBase64aux (ce
->ce_fp
, out
,
430 ct
->c_type
== CT_TEXT
&& ct
->c_ctparams
431 ? ((struct text
*) ct
->c_ctparams
)->lf_line_endings
== 0
433 (*ct
->c_ceclosefnx
) (ct
);