FreeCalypso > hg > falcon-mail-tools
comparison f-demime/header_end.c @ 0:7e0d08176f32
f-demime starting code
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 06 May 2023 06:14:03 +0000 |
parents | |
children | 1857d0d5a7bd |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7e0d08176f32 |
---|---|
1 /* | |
2 * This module implements final processing of message and body part headers, | |
3 * deciding what to do at the end of each header. | |
4 */ | |
5 | |
6 #include <ctype.h> | |
7 #include <stdio.h> | |
8 #include <stdlib.h> | |
9 #include <string.h> | |
10 #include <strings.h> | |
11 #include "defs.h" | |
12 | |
13 extern enum msg_state msg_state; | |
14 extern enum msg_hdr_state hdr_state; | |
15 extern unsigned mp_nest_level; | |
16 extern char mp_boundaries[MAX_MP_NESTING][MAX_MP_BOUNDARY+1]; | |
17 extern int mp_is_digest[MAX_MP_NESTING]; | |
18 extern char cont_type_buf[HDR_BUF_SIZE], cont_te_buf[HDR_BUF_SIZE]; | |
19 extern int got_cont_type, got_cont_te; | |
20 | |
21 static int | |
22 is_valid_tchar(ch) | |
23 { | |
24 if (ch < '!' || ch > '~') | |
25 return(0); | |
26 switch (ch) { | |
27 case '(': | |
28 case ')': | |
29 case '<': | |
30 case '>': | |
31 case '@': | |
32 case ',': | |
33 case ';': | |
34 case ':': | |
35 case '\\': | |
36 case '"': | |
37 case '/': | |
38 case '[': | |
39 case ']': | |
40 case '?': | |
41 case '=': | |
42 return(0); | |
43 default: | |
44 return(1); | |
45 } | |
46 } | |
47 | |
48 static int | |
49 gettoken(cpp, tokbuf) | |
50 char **cpp, *tokbuf; | |
51 { | |
52 register char *cp, *dp; | |
53 register int i; | |
54 | |
55 /* skip initial white space and comments */ | |
56 for (cp = *cpp; ; ) { | |
57 if (isspace(*cp)) { | |
58 cp++; | |
59 continue; | |
60 } | |
61 if (*cp != '(') | |
62 break; | |
63 for (i = 0; ; ) { | |
64 if (!*cp) | |
65 break; | |
66 if (*cp == '\\') | |
67 cp++; | |
68 else if (*cp == '(') | |
69 i++; | |
70 else if (*cp == ')') | |
71 i--; | |
72 if (*cp) | |
73 cp++; | |
74 if (!i) | |
75 break; | |
76 } | |
77 } | |
78 if (!*cp) { | |
79 *cpp = cp; | |
80 return(0); | |
81 } | |
82 if (*cp == '/' || *cp == ';' || *cp == '=') { | |
83 i = *cp++; | |
84 *cpp = cp; | |
85 return(i); | |
86 } | |
87 if (*cp == '"') { | |
88 cp++; | |
89 for (dp = tokbuf; *cp; ) { | |
90 if (*cp == '"') { | |
91 cp++; | |
92 break; | |
93 } | |
94 if (cp[0] == '\\' && cp[1]) | |
95 cp++; | |
96 *dp++ = *cp++; | |
97 } | |
98 *dp = '\0'; | |
99 *cpp = cp; | |
100 return(2); | |
101 } | |
102 if (!is_valid_tchar(*cp)) { | |
103 *cpp = cp; | |
104 return(-1); | |
105 } | |
106 for (dp = tokbuf; is_valid_tchar(*cp); ) | |
107 *dp++ = *cp++; | |
108 *dp = '\0'; | |
109 *cpp = cp; | |
110 return(1); | |
111 } | |
112 | |
113 static int | |
114 parse_content_type(type, subtype, charset, boundary) | |
115 char *type, *subtype, *charset, *boundary; | |
116 { | |
117 char *ctstr = cont_type_buf; | |
118 char tokbuf[HDR_BUF_SIZE], attr[HDR_BUF_SIZE]; | |
119 int rc; | |
120 | |
121 if (gettoken(&ctstr, type) != 1) | |
122 return(-1); | |
123 if (gettoken(&ctstr, tokbuf) != '/') | |
124 return(-1); | |
125 if (gettoken(&ctstr, subtype) != 1) | |
126 return(-1); | |
127 charset[0] = '\0'; | |
128 boundary[0] = '\0'; | |
129 for (;;) { | |
130 rc = gettoken(&ctstr, tokbuf); | |
131 if (!rc) | |
132 return(0); | |
133 if (rc != ';') | |
134 return(-1); | |
135 if (gettoken(&ctstr, attr) != 1) | |
136 return(-1); | |
137 if (gettoken(&ctstr, tokbuf) != '=') | |
138 return(-1); | |
139 rc = gettoken(&ctstr, tokbuf); | |
140 if (rc != 1 && rc != 2) | |
141 return(-1); | |
142 if (!strcasecmp(attr, "charset")) | |
143 strcpy(charset, tokbuf); | |
144 else if (!strcasecmp(attr, "boundary")) | |
145 strcpy(boundary, tokbuf); | |
146 } | |
147 } | |
148 | |
149 static int | |
150 parse_content_te(ctetoken) | |
151 char *ctetoken; | |
152 { | |
153 char *ctestr = cont_te_buf; | |
154 char tokbuf[HDR_BUF_SIZE]; | |
155 | |
156 if (gettoken(&ctestr, ctetoken) != 1) | |
157 return(-1); | |
158 if (gettoken(&ctestr, tokbuf) == 0) | |
159 return(0); | |
160 else | |
161 return(-1); | |
162 } | |
163 | |
164 static void | |
165 handle_multipart(cont_subtype, boundary_attr) | |
166 char *cont_subtype, *boundary_attr; | |
167 { | |
168 if (!boundary_attr[0]) { | |
169 puts("X-Fdemime-Error: multipart without boundary attr"); | |
170 putchar('\n'); | |
171 msg_state = MSG_STATE_BODY_PASS; | |
172 return; | |
173 } | |
174 if (index(boundary_attr, '\n')) { | |
175 puts("X-Fdemime-Error: multipart boundary attr contains newline"); | |
176 putchar('\n'); | |
177 msg_state = MSG_STATE_BODY_PASS; | |
178 return; | |
179 } | |
180 if (strlen(boundary_attr) > MAX_MP_BOUNDARY) { | |
181 puts("X-Fdemime-Error: multipart boundary attr is too long"); | |
182 putchar('\n'); | |
183 msg_state = MSG_STATE_BODY_PASS; | |
184 return; | |
185 } | |
186 if (mp_nest_level >= MAX_MP_NESTING) { | |
187 puts("X-Fdemime-Error: multipart nesting is too deep"); | |
188 putchar('\n'); | |
189 msg_state = MSG_STATE_BODY_PASS; | |
190 return; | |
191 } | |
192 putchar('\n'); | |
193 strcpy(mp_boundaries[mp_nest_level], boundary_attr); | |
194 mp_is_digest[mp_nest_level] = !strcasecmp(cont_subtype, "digest"); | |
195 mp_nest_level++; | |
196 msg_state = MSG_STATE_BODY_PASS; | |
197 } | |
198 | |
199 void | |
200 process_header_end() | |
201 { | |
202 char cont_type[HDR_BUF_SIZE], cont_subtype[HDR_BUF_SIZE]; | |
203 char charset_attr[HDR_BUF_SIZE], boundary_attr[HDR_BUF_SIZE]; | |
204 char content_te[HDR_BUF_SIZE]; | |
205 int in_digest, rc; | |
206 | |
207 if (hdr_state == HDR_STATE_ERROR) { | |
208 if (got_cont_type) | |
209 fputs(cont_type_buf, stdout); | |
210 if (got_cont_te) | |
211 fputs(cont_te_buf, stdout); | |
212 putchar('\n'); | |
213 msg_state = MSG_STATE_BODY_PASS; | |
214 return; | |
215 } | |
216 if (mp_nest_level) | |
217 in_digest = mp_is_digest[mp_nest_level-1]; | |
218 else | |
219 in_digest = 0; | |
220 if (got_cont_type) { | |
221 fputs(cont_type_buf, stdout); | |
222 rc = parse_content_type(cont_type, cont_subtype, charset_attr, | |
223 boundary_attr); | |
224 if (rc < 0) { | |
225 puts("X-Fdemime-Error: unable to parse Content-Type"); | |
226 if (got_cont_te) | |
227 fputs(cont_te_buf, stdout); | |
228 putchar('\n'); | |
229 msg_state = MSG_STATE_BODY_PASS; | |
230 return; | |
231 } | |
232 } else { | |
233 if (in_digest) { | |
234 strcpy(cont_type, "message"); | |
235 strcpy(cont_subtype, "rfc822"); | |
236 } else { | |
237 strcpy(cont_type, "text"); | |
238 strcpy(cont_subtype, "plain"); | |
239 } | |
240 charset_attr[0] = '\0'; | |
241 boundary_attr[0] = '\0'; | |
242 } | |
243 if (!strcasecmp(cont_type, "multipart")) { | |
244 if (got_cont_te) | |
245 fputs(cont_te_buf, stdout); | |
246 handle_multipart(cont_subtype, boundary_attr); | |
247 return; | |
248 } | |
249 if (!strcasecmp(cont_type, "message")) { | |
250 if (got_cont_te) | |
251 fputs(cont_te_buf, stdout); | |
252 putchar('\n'); | |
253 msg_state = MSG_STATE_BODY_PASS; | |
254 return; | |
255 } | |
256 if (got_cont_te) { | |
257 rc = parse_content_te(content_te); | |
258 if (rc < 0) { | |
259 fputs(cont_te_buf, stdout); | |
260 puts( | |
261 "X-Fdemime-Error: unable to parse Content-Transfer-Encoding"); | |
262 putchar('\n'); | |
263 msg_state = MSG_STATE_BODY_PASS; | |
264 return; | |
265 } | |
266 } else | |
267 content_te[0] = '\0'; | |
268 if (!strcasecmp(content_te, "base64")) { | |
269 if (!strcasecmp(cont_type, "text")) { | |
270 if (!strcasecmp(cont_subtype, "plain")) | |
271 init_base64_text_plain(charset_attr); | |
272 else | |
273 init_base64_text_other(); | |
274 } else | |
275 init_base64_nontext(); | |
276 return; | |
277 } | |
278 if (!strcasecmp(content_te, "quoted-printable") && | |
279 !strcasecmp(cont_type, "text") && | |
280 !strcasecmp(cont_subtype, "plain")) { | |
281 init_qp_text_plain(charset_attr); | |
282 return; | |
283 } | |
284 if (got_cont_te) | |
285 fputs(cont_te_buf, stdout); | |
286 putchar('\n'); | |
287 msg_state = MSG_STATE_BODY_PASS; | |
288 } |