1 /*
2 ** Copyright 1998 - 2001 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5
6 #if HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9 #include "imaptoken.h"
10 #include "imapwrite.h"
11 #include "rfc822/rfc822.h"
12 #include "rfc2045/rfc2045.h"
13 #include <stdio.h>
14 #include <ctype.h>
15 #include <stdlib.h>
16 #include <string.h>
17
18
19 extern void msgenvelope(void (*)(const char *, size_t),
20 FILE *, struct rfc2045 *);
21
22 extern void msgappends(void (*)(const char *, size_t), const char *, size_t);
23
do_param_list(void (* writefunc)(const char *,size_t),struct rfc2045attr * a)24 static void do_param_list(void (*writefunc)(const char *, size_t),
25 struct rfc2045attr *a)
26 {
27 int flag;
28 char *p;
29
30 flag=0;
31 p="(";
32 for (; a; a=a->next)
33 {
34 (*writefunc)(p, strlen(p));
35 (*writefunc)("\"", 1);
36 if (a->name)
37 msgappends(writefunc, a->name, strlen(a->name));
38 (*writefunc)("\" \"", 3);
39 if (a->value)
40 {
41 #if IMAP_CLIENT_BUGS
42
43 /* NETSCAPE */
44
45 char *u, *v, *w;
46
47 u=strdup(a->value);
48 if (!u) write_error_exit(0);
49 strcpy(u, a->value);
50 for (v=w=u; *v; v++)
51 if (*v != '\\') *w++ = *v;
52 *w=0;
53 msgappends(writefunc, u, strlen(u));
54 free(u);
55
56 #else
57 msgappends(writefunc, a->value, strlen(a->value));
58 #endif
59 }
60 (*writefunc)("\"", 1);
61 flag=1;
62 p=" ";
63 }
64 if (flag)
65 (*writefunc)(")", 1);
66 else
67 (*writefunc)("NIL", 3);
68 }
69
contentstr(void (* writefunc)(const char *,size_t),const char * s)70 static void contentstr( void (*writefunc)(const char *, size_t), const char *s)
71 {
72 if (!s || !*s)
73 {
74 (*writefunc)("NIL", 3);
75 return;
76 }
77
78 (*writefunc)("\"", 1);
79 msgappends(writefunc, s, strlen(s));
80 (*writefunc)("\"", 1);
81 }
82
83
do_disposition(void (* writefunc)(const char *,size_t),const char * disposition_s,struct rfc2045attr * disposition_a)84 static void do_disposition(
85 void (*writefunc)(const char *, size_t), const char *disposition_s,
86 struct rfc2045attr *disposition_a)
87 {
88 if ( (disposition_s == 0 || *disposition_s == 0) &&
89 disposition_a == 0)
90 {
91 (*writefunc)("NIL", 3);
92 return;
93 }
94 (*writefunc)("(", 1);
95
96 if (disposition_s && *disposition_s)
97 {
98 (*writefunc)("\"", 1);
99 msgappends(writefunc, disposition_s,
100 strlen(disposition_s));
101 (*writefunc)("\"", 1);
102 }
103 else
104 (*writefunc)("\"\"", 2);
105
106 (*writefunc)(" ", 1);
107 do_param_list(writefunc, disposition_a);
108 (*writefunc)(")", 1);
109 }
110
msgbodystructure(void (* writefunc)(const char *,size_t),int dox,FILE * fp,struct rfc2045 * mimep)111 void msgbodystructure( void (*writefunc)(const char *, size_t), int dox,
112 FILE *fp, struct rfc2045 *mimep)
113 {
114 const char *content_type_s;
115 const char *content_transfer_encoding_s;
116 const char *charset_s;
117 off_t start_pos, end_pos, start_body;
118 off_t nlines, nbodylines;
119 const char *disposition_s;
120
121 char *p, *q;
122
123 rfc2045_mimeinfo(mimep, &content_type_s, &content_transfer_encoding_s,
124 &charset_s);
125 rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
126 &nlines, &nbodylines);
127
128 disposition_s=mimep->content_disposition;
129
130 (*writefunc)("(", 1);
131
132 if (mimep->firstpart && mimep->firstpart->isdummy &&
133 mimep->firstpart->next)
134 /* MULTIPART */
135 {
136 struct rfc2045 *childp;
137
138 for (childp=mimep->firstpart; (childp=childp->next) != 0; )
139 msgbodystructure(writefunc, dox, fp, childp);
140
141 (*writefunc)(" \"", 2);
142 p=strchr(content_type_s, '/');
143 if (p)
144 msgappends(writefunc, p+1, strlen(p+1));
145 (*writefunc)("\"", 1);
146
147 if (dox)
148 {
149 (*writefunc)(" ", 1);
150 do_param_list(writefunc, mimep->content_type_attr);
151
152 (*writefunc)(" ", 1);
153 do_disposition(writefunc, disposition_s,
154 mimep->content_disposition_attr);
155
156 (*writefunc)(" ", 1);
157 contentstr(writefunc, rfc2045_content_language(mimep));
158 }
159 }
160 else
161 {
162 char *mybuf;
163 char buf[40];
164 const char *cp;
165
166 mybuf=my_strdup(content_type_s);
167 q=strtok(mybuf, " /");
168 (*writefunc)("\"", 1);
169 if (q)
170 msgappends(writefunc, q, strlen(q));
171 (*writefunc)("\" \"", 3);
172 if (q) q=strtok(0, " /");
173 if (q)
174 msgappends(writefunc, q, strlen(q));
175 free(mybuf);
176 (*writefunc)("\" ", 2);
177
178 do_param_list(writefunc, mimep->content_type_attr);
179
180 (*writefunc)(" ", 1);
181 cp=rfc2045_content_id(mimep);
182 if (!cp || !*cp)
183 contentstr(writefunc, cp);
184 else
185 {
186 (*writefunc)("\"<", 2);
187 msgappends(writefunc, cp, strlen(cp));
188 (*writefunc)(">\"", 2);
189 }
190 (*writefunc)(" ", 1);
191 contentstr(writefunc, rfc2045_content_description(mimep));
192
193 (*writefunc)(" \"", 2);
194 msgappends(writefunc, content_transfer_encoding_s,
195 strlen(content_transfer_encoding_s));
196 (*writefunc)("\" ", 2);
197
198 sprintf(buf, "%lu", (unsigned long)
199 (end_pos-start_body+nbodylines));
200 /* nbodylines added for CRs */
201 (*writefunc)(buf, strlen(buf));
202
203 if (
204 (content_type_s[0] == 't' || content_type_s[0] == 'T') &&
205 (content_type_s[1] == 'e' || content_type_s[1] == 'E') &&
206 (content_type_s[2] == 'x' || content_type_s[2] == 'X') &&
207 (content_type_s[3] == 't' || content_type_s[3] == 'T') &&
208 (content_type_s[4] == '/' ||
209 content_type_s[4] == 0))
210 {
211 (*writefunc)(" ", 1);
212 sprintf(buf, "%lu", (unsigned long)nbodylines);
213 (*writefunc)(buf, strlen(buf));
214 }
215
216 if (mimep->firstpart && !mimep->firstpart->isdummy)
217 /* message/rfc822 */
218 {
219 (*writefunc)(" ", 1);
220 msgenvelope(writefunc, fp, mimep->firstpart);
221 (*writefunc)(" ", 1);
222 msgbodystructure(writefunc, dox, fp, mimep->firstpart);
223 (*writefunc)(" ", 1);
224 sprintf(buf, "%lu", (unsigned long)nbodylines);
225 (*writefunc)(buf, strlen(buf));
226 }
227
228 if (dox)
229 {
230 (*writefunc)(" ", 1);
231 contentstr(writefunc, rfc2045_content_md5(mimep));
232
233 (*writefunc)(" ", 1);
234 do_disposition(writefunc, disposition_s,
235 mimep->content_disposition_attr);
236
237 (*writefunc)(" NIL", 4);
238 /* TODO Content-Language: */
239 }
240 }
241 (*writefunc)(")", 1);
242 }
243