-rw-r--r-- | kmicromail/libetpan/mime/.libs/libmailmime.a | bin | 0 -> 192784 bytes | |||
-rw-r--r-- | kmicromail/libetpan/mime/TODO | 10 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime.c | 1408 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime.h | 100 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_content.c | 2164 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_content.h | 89 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_decode.c | 533 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_decode.h | 55 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_disposition.c | 595 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_disposition.h | 62 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_types.c | 750 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_types.h | 440 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_types_helper.c | 1385 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_types_helper.h | 165 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_write.c | 1416 | ||||
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_write.h | 73 |
16 files changed, 9245 insertions, 0 deletions
diff --git a/kmicromail/libetpan/mime/.libs/libmailmime.a b/kmicromail/libetpan/mime/.libs/libmailmime.a new file mode 100644 index 0000000..902b9d9 --- a/dev/null +++ b/kmicromail/libetpan/mime/.libs/libmailmime.a | |||
Binary files differ | |||
diff --git a/kmicromail/libetpan/mime/TODO b/kmicromail/libetpan/mime/TODO new file mode 100644 index 0000000..df02810 --- a/dev/null +++ b/kmicromail/libetpan/mime/TODO | |||
@@ -0,0 +1,10 @@ | |||
1 | - see about the RFC2047, beginning in mailmime_decode.[ch] | ||
2 | - content-langage | ||
3 | - single mime_field | ||
4 | - RFC 2048 | ||
5 | - RFC 2049 | ||
6 | - RFC 2231 | ||
7 | - RFC 2387 | ||
8 | - RFC 2424 | ||
9 | - RFC 2557 | ||
10 | |||
diff --git a/kmicromail/libetpan/mime/mailmime.c b/kmicromail/libetpan/mime/mailmime.c new file mode 100644 index 0000000..e920722 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime.c | |||
@@ -0,0 +1,1408 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #include "mailmime.h" | ||
37 | |||
38 | /* | ||
39 | RFC 2045 | ||
40 | RFC 2046 | ||
41 | RFC 2047 | ||
42 | RFC 2048 | ||
43 | RFC 2049 | ||
44 | RFC 2231 | ||
45 | RFC 2387 | ||
46 | RFC 2424 | ||
47 | RFC 2557 | ||
48 | |||
49 | RFC 2183 Content-Disposition | ||
50 | |||
51 | RFC 1766 Language | ||
52 | */ | ||
53 | |||
54 | #include <ctype.h> | ||
55 | #include <stdlib.h> | ||
56 | #include <string.h> | ||
57 | |||
58 | #include "mailmime_types.h" | ||
59 | #include "mailmime_disposition.h" | ||
60 | #include "mailimf.h" | ||
61 | |||
62 | #ifndef TRUE | ||
63 | #define TRUE 1 | ||
64 | #endif | ||
65 | |||
66 | #ifndef FALSE | ||
67 | #define FALSE 0 | ||
68 | #endif | ||
69 | |||
70 | static int mailmime_attribute_parse(const char * message, size_t length, | ||
71 | size_t * index, | ||
72 | char ** result); | ||
73 | static int | ||
74 | mailmime_composite_type_parse(const char * message, size_t length, | ||
75 | size_t * index, | ||
76 | struct mailmime_composite_type ** result); | ||
77 | |||
78 | static int is_text(char ch); | ||
79 | |||
80 | static int | ||
81 | mailmime_discrete_type_parse(const char * message, size_t length, | ||
82 | size_t * index, | ||
83 | struct mailmime_discrete_type ** result); | ||
84 | |||
85 | static int mailmime_mechanism_parse(const char * message, size_t length, | ||
86 | size_t * index, | ||
87 | struct mailmime_mechanism ** result); | ||
88 | |||
89 | static int mailmime_subtype_parse(const char * message, size_t length, | ||
90 | size_t * index, char ** result); | ||
91 | |||
92 | static int is_token(char ch); | ||
93 | |||
94 | static int mailmime_token_parse(const char * message, size_t length, | ||
95 | size_t * index, | ||
96 | char ** token); | ||
97 | |||
98 | static int is_tspecials(char ch); | ||
99 | |||
100 | static int mailmime_type_parse(const char * message, size_t length, | ||
101 | size_t * index, | ||
102 | struct mailmime_type ** result); | ||
103 | |||
104 | /* | ||
105 | int mailmime_version_parse(const char * message, guint32 length, | ||
106 | guint32 * index, | ||
107 | guint32 * result); | ||
108 | */ | ||
109 | |||
110 | /* | ||
111 | static gboolean mailmime_x_token_parse(gconst char * message, guint32 length, | ||
112 | guint32 * index, | ||
113 | gchar ** result); | ||
114 | */ | ||
115 | |||
116 | /* ********************************************************************** */ | ||
117 | |||
118 | /* | ||
119 | x attribute := token | ||
120 | ; Matching of attributes | ||
121 | ; is ALWAYS case-insensitive. | ||
122 | */ | ||
123 | |||
124 | static int mailmime_attribute_parse(const char * message, size_t length, | ||
125 | size_t * index, | ||
126 | char ** result) | ||
127 | { | ||
128 | return mailmime_token_parse(message, length, index, result); | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | x composite-type := "message" / "multipart" / extension-token | ||
133 | */ | ||
134 | |||
135 | static int | ||
136 | mailmime_composite_type_parse(const char * message, size_t length, | ||
137 | size_t * index, | ||
138 | struct mailmime_composite_type ** result) | ||
139 | { | ||
140 | char * extension_token; | ||
141 | int type; | ||
142 | struct mailmime_composite_type * ct; | ||
143 | size_t cur_token; | ||
144 | int r; | ||
145 | int res; | ||
146 | |||
147 | cur_token = * index; | ||
148 | |||
149 | extension_token = NULL; | ||
150 | |||
151 | type = MAILMIME_COMPOSITE_TYPE_ERROR; /* XXX - removes a gcc warning */ | ||
152 | |||
153 | r = mailimf_token_case_insensitive_parse(message, length, | ||
154 | &cur_token, "message"); | ||
155 | if (r == MAILIMF_NO_ERROR) | ||
156 | type = MAILMIME_COMPOSITE_TYPE_MESSAGE; | ||
157 | |||
158 | if (r == MAILIMF_ERROR_PARSE) { | ||
159 | r = mailimf_token_case_insensitive_parse(message, length, | ||
160 | &cur_token, "multipart"); | ||
161 | if (r == MAILIMF_NO_ERROR) | ||
162 | type = MAILMIME_COMPOSITE_TYPE_MULTIPART; | ||
163 | } | ||
164 | |||
165 | if (r != MAILIMF_NO_ERROR) { | ||
166 | res = r; | ||
167 | goto err; | ||
168 | } | ||
169 | |||
170 | ct = mailmime_composite_type_new(type, extension_token); | ||
171 | if (ct == NULL) { | ||
172 | res = MAILIMF_ERROR_MEMORY; | ||
173 | goto free_extension; | ||
174 | } | ||
175 | |||
176 | * result = ct; | ||
177 | * index = cur_token; | ||
178 | |||
179 | return MAILIMF_NO_ERROR; | ||
180 | |||
181 | free_extension: | ||
182 | if (extension_token != NULL) | ||
183 | mailmime_extension_token_free(extension_token); | ||
184 | err: | ||
185 | return res; | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | x content := "Content-Type" ":" type "/" subtype | ||
190 | *(";" parameter) | ||
191 | ; Matching of media type and subtype | ||
192 | ; is ALWAYS case-insensitive. | ||
193 | */ | ||
194 | |||
195 | int mailmime_content_parse(const char * message, size_t length, | ||
196 | size_t * index, | ||
197 | struct mailmime_content ** result) | ||
198 | { | ||
199 | size_t cur_token; | ||
200 | struct mailmime_type * type; | ||
201 | char * subtype; | ||
202 | clist * parameters_list; | ||
203 | struct mailmime_content * content; | ||
204 | int r; | ||
205 | int res; | ||
206 | |||
207 | cur_token = * index; | ||
208 | |||
209 | mailimf_cfws_parse(message, length, &cur_token); | ||
210 | |||
211 | r = mailmime_type_parse(message, length, &cur_token, &type); | ||
212 | if (r != MAILIMF_NO_ERROR) { | ||
213 | res = r; | ||
214 | goto err; | ||
215 | } | ||
216 | |||
217 | r = mailimf_unstrict_char_parse(message, length, &cur_token, '/'); | ||
218 | switch (r) { | ||
219 | case MAILIMF_NO_ERROR: | ||
220 | r = mailimf_cfws_parse(message, length, &cur_token); | ||
221 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
222 | res = r; | ||
223 | goto free_type; | ||
224 | } | ||
225 | |||
226 | r = mailmime_subtype_parse(message, length, &cur_token, &subtype); | ||
227 | if (r != MAILIMF_NO_ERROR) { | ||
228 | res = r; | ||
229 | goto free_type; | ||
230 | } | ||
231 | break; | ||
232 | |||
233 | case MAILIMF_ERROR_PARSE: | ||
234 | subtype = strdup("unknown"); | ||
235 | break; | ||
236 | |||
237 | default: | ||
238 | res = r; | ||
239 | goto free_type; | ||
240 | } | ||
241 | |||
242 | parameters_list = clist_new(); | ||
243 | if (parameters_list == NULL) { | ||
244 | res = MAILIMF_ERROR_MEMORY; | ||
245 | goto free_type; | ||
246 | } | ||
247 | |||
248 | while (1) { | ||
249 | size_t final_token; | ||
250 | struct mailmime_parameter * parameter; | ||
251 | |||
252 | final_token = cur_token; | ||
253 | r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); | ||
254 | if (r != MAILIMF_NO_ERROR) { | ||
255 | cur_token = final_token; | ||
256 | break; | ||
257 | } | ||
258 | |||
259 | r = mailimf_cfws_parse(message, length, &cur_token); | ||
260 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
261 | res = r; | ||
262 | goto free_type; | ||
263 | } | ||
264 | |||
265 | r = mailmime_parameter_parse(message, length, &cur_token, ¶meter); | ||
266 | if (r == MAILIMF_NO_ERROR) { | ||
267 | /* do nothing */ | ||
268 | } | ||
269 | else if (r == MAILIMF_ERROR_PARSE) { | ||
270 | cur_token = final_token; | ||
271 | break; | ||
272 | } | ||
273 | else { | ||
274 | res = r; | ||
275 | goto err; | ||
276 | } | ||
277 | |||
278 | r = clist_append(parameters_list, parameter); | ||
279 | if (r < 0) { | ||
280 | mailmime_parameter_free(parameter); | ||
281 | res = MAILIMF_ERROR_MEMORY; | ||
282 | goto free_parameters; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | content = mailmime_content_new(type, subtype, parameters_list); | ||
287 | if (content == NULL) { | ||
288 | res = MAILIMF_ERROR_MEMORY; | ||
289 | goto free_parameters; | ||
290 | } | ||
291 | |||
292 | * result = content; | ||
293 | * index = cur_token; | ||
294 | |||
295 | return MAILIMF_NO_ERROR; | ||
296 | |||
297 | free_parameters: | ||
298 | clist_foreach(parameters_list, (clist_func) mailmime_parameter_free, NULL); | ||
299 | clist_free(parameters_list); | ||
300 | |||
301 | mailmime_subtype_free(subtype); | ||
302 | free_type: | ||
303 | mailmime_type_free(type); | ||
304 | err: | ||
305 | return res; | ||
306 | } | ||
307 | |||
308 | /* | ||
309 | x description := "Content-Description" ":" *text | ||
310 | */ | ||
311 | |||
312 | static int is_text(char ch) | ||
313 | { | ||
314 | unsigned char uch = (unsigned char) ch; | ||
315 | |||
316 | if (uch < 1) | ||
317 | return FALSE; | ||
318 | |||
319 | if ((uch == 10) || (uch == 13)) | ||
320 | return FALSE; | ||
321 | |||
322 | return TRUE; | ||
323 | } | ||
324 | |||
325 | int mailmime_description_parse(const char * message, size_t length, | ||
326 | size_t * index, | ||
327 | char ** result) | ||
328 | { | ||
329 | return mailimf_custom_string_parse(message, length, | ||
330 | index, result, | ||
331 | is_text); | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | x discrete-type := "text" / "image" / "audio" / "video" / | ||
336 | "application" / extension-token | ||
337 | */ | ||
338 | |||
339 | /* currently porting */ | ||
340 | |||
341 | static int | ||
342 | mailmime_discrete_type_parse(const char * message, size_t length, | ||
343 | size_t * index, | ||
344 | struct mailmime_discrete_type ** result) | ||
345 | { | ||
346 | char * extension; | ||
347 | int type; | ||
348 | struct mailmime_discrete_type * discrete_type; | ||
349 | size_t cur_token; | ||
350 | int r; | ||
351 | int res; | ||
352 | |||
353 | cur_token = * index; | ||
354 | |||
355 | extension = NULL; | ||
356 | |||
357 | type = MAILMIME_DISCRETE_TYPE_ERROR; /* XXX - removes a gcc warning */ | ||
358 | |||
359 | r = mailimf_token_case_insensitive_parse(message, length, | ||
360 | &cur_token, "text"); | ||
361 | if (r == MAILIMF_NO_ERROR) | ||
362 | type = MAILMIME_DISCRETE_TYPE_TEXT; | ||
363 | |||
364 | if (r == MAILIMF_ERROR_PARSE) { | ||
365 | r = mailimf_token_case_insensitive_parse(message, length, | ||
366 | &cur_token, "image"); | ||
367 | if (r == MAILIMF_NO_ERROR) | ||
368 | type = MAILMIME_DISCRETE_TYPE_IMAGE; | ||
369 | } | ||
370 | |||
371 | if (r == MAILIMF_ERROR_PARSE) { | ||
372 | r = mailimf_token_case_insensitive_parse(message, length, | ||
373 | &cur_token, "audio"); | ||
374 | if (r == MAILIMF_NO_ERROR) | ||
375 | type = MAILMIME_DISCRETE_TYPE_AUDIO; | ||
376 | } | ||
377 | |||
378 | if (r == MAILIMF_ERROR_PARSE) { | ||
379 | r = mailimf_token_case_insensitive_parse(message, length, | ||
380 | &cur_token, "video"); | ||
381 | if (r == MAILIMF_NO_ERROR) | ||
382 | type = MAILMIME_DISCRETE_TYPE_VIDEO; | ||
383 | } | ||
384 | |||
385 | if (r == MAILIMF_ERROR_PARSE) { | ||
386 | r = mailimf_token_case_insensitive_parse(message, length, | ||
387 | &cur_token, "application"); | ||
388 | if (r == MAILIMF_NO_ERROR) | ||
389 | type = MAILMIME_DISCRETE_TYPE_APPLICATION; | ||
390 | } | ||
391 | |||
392 | if (r == MAILIMF_ERROR_PARSE) { | ||
393 | r = mailmime_extension_token_parse(message, length, | ||
394 | &cur_token, &extension); | ||
395 | if (r == MAILIMF_NO_ERROR) | ||
396 | type = MAILMIME_DISCRETE_TYPE_EXTENSION; | ||
397 | } | ||
398 | |||
399 | if (r != MAILIMF_NO_ERROR) { | ||
400 | res = r; | ||
401 | goto err; | ||
402 | } | ||
403 | |||
404 | discrete_type = mailmime_discrete_type_new(type, extension); | ||
405 | if (discrete_type == NULL) { | ||
406 | res = MAILIMF_ERROR_MEMORY; | ||
407 | goto free; | ||
408 | } | ||
409 | |||
410 | * result = discrete_type; | ||
411 | * index = cur_token; | ||
412 | |||
413 | return MAILIMF_NO_ERROR; | ||
414 | |||
415 | free: | ||
416 | mailmime_extension_token_free(extension); | ||
417 | err: | ||
418 | return res; | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | x encoding := "Content-Transfer-Encoding" ":" mechanism | ||
423 | */ | ||
424 | |||
425 | int mailmime_encoding_parse(const char * message, size_t length, | ||
426 | size_t * index, | ||
427 | struct mailmime_mechanism ** result) | ||
428 | { | ||
429 | return mailmime_mechanism_parse(message, length, index, result); | ||
430 | } | ||
431 | |||
432 | /* | ||
433 | x entity-headers := [ content CRLF ] | ||
434 | [ encoding CRLF ] | ||
435 | [ id CRLF ] | ||
436 | [ description CRLF ] | ||
437 | *( MIME-extension-field CRLF ) | ||
438 | */ | ||
439 | |||
440 | enum { | ||
441 | FIELD_STATE_START, | ||
442 | FIELD_STATE_T, | ||
443 | FIELD_STATE_D | ||
444 | }; | ||
445 | |||
446 | static int guess_field_type(char * name) | ||
447 | { | ||
448 | int state; | ||
449 | |||
450 | if (* name == 'M') | ||
451 | return MAILMIME_FIELD_VERSION; | ||
452 | |||
453 | if (strncasecmp(name, "Content-", 8) != 0) | ||
454 | return MAILMIME_FIELD_NONE; | ||
455 | |||
456 | name += 8; | ||
457 | |||
458 | state = FIELD_STATE_START; | ||
459 | |||
460 | while (1) { | ||
461 | |||
462 | switch (state) { | ||
463 | |||
464 | case FIELD_STATE_START: | ||
465 | switch ((char) toupper((unsigned char) * name)) { | ||
466 | case 'T': | ||
467 | state = FIELD_STATE_T; | ||
468 | break; | ||
469 | case 'I': | ||
470 | return MAILMIME_FIELD_ID; | ||
471 | case 'D': | ||
472 | state = FIELD_STATE_D; | ||
473 | break; | ||
474 | case 'L': | ||
475 | return MAILMIME_FIELD_LANGUAGE; | ||
476 | default: | ||
477 | return MAILMIME_FIELD_NONE; | ||
478 | } | ||
479 | break; | ||
480 | |||
481 | case FIELD_STATE_T: | ||
482 | switch ((char) toupper((unsigned char) * name)) { | ||
483 | case 'Y': | ||
484 | return MAILMIME_FIELD_TYPE; | ||
485 | case 'R': | ||
486 | return MAILMIME_FIELD_TRANSFER_ENCODING; | ||
487 | default: | ||
488 | return MAILMIME_FIELD_NONE; | ||
489 | } | ||
490 | break; | ||
491 | |||
492 | case FIELD_STATE_D: | ||
493 | switch ((char) toupper((unsigned char) * name)) { | ||
494 | case 'E': | ||
495 | return MAILMIME_FIELD_DESCRIPTION; | ||
496 | case 'I': | ||
497 | return MAILMIME_FIELD_DISPOSITION; | ||
498 | default: | ||
499 | return MAILMIME_FIELD_NONE; | ||
500 | } | ||
501 | break; | ||
502 | } | ||
503 | name ++; | ||
504 | } | ||
505 | } | ||
506 | |||
507 | int | ||
508 | mailmime_field_parse(struct mailimf_optional_field * field, | ||
509 | struct mailmime_field ** result) | ||
510 | { | ||
511 | char * name; | ||
512 | char * value; | ||
513 | int guessed_type; | ||
514 | size_t cur_token; | ||
515 | struct mailmime_content * content; | ||
516 | struct mailmime_mechanism * encoding; | ||
517 | char * id; | ||
518 | char * description; | ||
519 | uint32_t version; | ||
520 | struct mailmime_field * mime_field; | ||
521 | struct mailmime_language * language; | ||
522 | struct mailmime_disposition * disposition; | ||
523 | int res; | ||
524 | int r; | ||
525 | |||
526 | name = field->fld_name; | ||
527 | value = field->fld_value; | ||
528 | cur_token = 0; | ||
529 | |||
530 | content = NULL; | ||
531 | encoding = NULL; | ||
532 | id = NULL; | ||
533 | description = NULL; | ||
534 | version = 0; | ||
535 | disposition = NULL; | ||
536 | language = NULL; | ||
537 | |||
538 | guessed_type = guess_field_type(name); | ||
539 | |||
540 | switch (guessed_type) { | ||
541 | case MAILMIME_FIELD_TYPE: | ||
542 | if (strcasecmp(name, "Content-Type") != 0) | ||
543 | return MAILIMF_ERROR_PARSE; | ||
544 | r = mailmime_content_parse(value, strlen(value), &cur_token, &content); | ||
545 | if (r != MAILIMF_NO_ERROR) | ||
546 | return r; | ||
547 | break; | ||
548 | |||
549 | case MAILMIME_FIELD_TRANSFER_ENCODING: | ||
550 | if (strcasecmp(name, "Content-Transfer-Encoding") != 0) | ||
551 | return MAILIMF_ERROR_PARSE; | ||
552 | r = mailmime_encoding_parse(value, strlen(value), &cur_token, &encoding); | ||
553 | if (r != MAILIMF_NO_ERROR) | ||
554 | return r; | ||
555 | break; | ||
556 | |||
557 | case MAILMIME_FIELD_ID: | ||
558 | if (strcasecmp(name, "Content-ID") != 0) | ||
559 | return MAILIMF_ERROR_PARSE; | ||
560 | r = mailmime_id_parse(value, strlen(value), &cur_token, &id); | ||
561 | if (r != MAILIMF_NO_ERROR) | ||
562 | return r; | ||
563 | break; | ||
564 | |||
565 | case MAILMIME_FIELD_DESCRIPTION: | ||
566 | if (strcasecmp(name, "Content-Description") != 0) | ||
567 | return MAILIMF_ERROR_PARSE; | ||
568 | r = mailmime_description_parse(value, strlen(value), | ||
569 | &cur_token, &description); | ||
570 | if (r != MAILIMF_NO_ERROR) | ||
571 | return r; | ||
572 | break; | ||
573 | |||
574 | case MAILMIME_FIELD_VERSION: | ||
575 | if (strcasecmp(name, "MIME-Version") != 0) | ||
576 | return MAILIMF_ERROR_PARSE; | ||
577 | r = mailmime_version_parse(value, strlen(value), &cur_token, &version); | ||
578 | if (r != MAILIMF_NO_ERROR) | ||
579 | return r; | ||
580 | break; | ||
581 | |||
582 | case MAILMIME_FIELD_DISPOSITION: | ||
583 | if (strcasecmp(name, "Content-Disposition") != 0) | ||
584 | return MAILIMF_ERROR_PARSE; | ||
585 | r = mailmime_disposition_parse(value, strlen(value), | ||
586 | &cur_token, &disposition); | ||
587 | if (r != MAILIMF_NO_ERROR) | ||
588 | return r; | ||
589 | break; | ||
590 | |||
591 | case MAILMIME_FIELD_LANGUAGE: | ||
592 | if (strcasecmp(name, "Content-Language") != 0) | ||
593 | return MAILIMF_ERROR_PARSE; | ||
594 | r = mailmime_language_parse(value, strlen(value), &cur_token, &language); | ||
595 | if (r != MAILIMF_NO_ERROR) | ||
596 | return r; | ||
597 | break; | ||
598 | |||
599 | default: | ||
600 | return MAILIMF_ERROR_PARSE; | ||
601 | } | ||
602 | |||
603 | mime_field = mailmime_field_new(guessed_type, content, encoding, | ||
604 | id, description, version, disposition, | ||
605 | language); | ||
606 | if (mime_field == NULL) { | ||
607 | res = MAILIMF_ERROR_MEMORY; | ||
608 | goto free; | ||
609 | } | ||
610 | |||
611 | * result = mime_field; | ||
612 | |||
613 | return MAILIMF_NO_ERROR; | ||
614 | |||
615 | free: | ||
616 | if (content != NULL) | ||
617 | mailmime_content_free(content); | ||
618 | if (encoding != NULL) | ||
619 | mailmime_encoding_free(encoding); | ||
620 | if (id != NULL) | ||
621 | mailmime_id_free(id); | ||
622 | if (description != NULL) | ||
623 | mailmime_description_free(description); | ||
624 | return res; | ||
625 | } | ||
626 | |||
627 | /* | ||
628 | x extension-token := ietf-token / x-token | ||
629 | */ | ||
630 | |||
631 | int | ||
632 | mailmime_extension_token_parse(const char * message, size_t length, | ||
633 | size_t * index, char ** result) | ||
634 | { | ||
635 | return mailmime_token_parse(message, length, index, result); | ||
636 | } | ||
637 | |||
638 | /* | ||
639 | hex-octet := "=" 2(DIGIT / "A" / "B" / "C" / "D" / "E" / "F") | ||
640 | ; Octet must be used for characters > 127, =, | ||
641 | ; SPACEs or TABs at the ends of lines, and is | ||
642 | ; recommended for any character not listed in | ||
643 | ; RFC 2049 as "mail-safe". | ||
644 | */ | ||
645 | |||
646 | /* | ||
647 | x iana-token := <A publicly-defined extension token. Tokens | ||
648 | of this form must be registered with IANA | ||
649 | as specified in RFC 2048.> | ||
650 | */ | ||
651 | |||
652 | /* | ||
653 | x ietf-token := <An extension token defined by a | ||
654 | standards-track RFC and registered | ||
655 | with IANA.> | ||
656 | */ | ||
657 | |||
658 | /* | ||
659 | x id := "Content-ID" ":" msg-id | ||
660 | */ | ||
661 | |||
662 | int mailmime_id_parse(const char * message, size_t length, | ||
663 | size_t * index, char ** result) | ||
664 | { | ||
665 | return mailimf_msg_id_parse(message, length, index, result); | ||
666 | } | ||
667 | |||
668 | /* | ||
669 | x mechanism := "7bit" / "8bit" / "binary" / | ||
670 | "quoted-printable" / "base64" / | ||
671 | ietf-token / x-token | ||
672 | */ | ||
673 | |||
674 | static int mailmime_mechanism_parse(const char * message, size_t length, | ||
675 | size_t * index, | ||
676 | struct mailmime_mechanism ** result) | ||
677 | { | ||
678 | char * token; | ||
679 | int type; | ||
680 | struct mailmime_mechanism * mechanism; | ||
681 | size_t cur_token; | ||
682 | int r; | ||
683 | int res; | ||
684 | |||
685 | cur_token = * index; | ||
686 | |||
687 | type = MAILMIME_MECHANISM_ERROR; /* XXX - removes a gcc warning */ | ||
688 | |||
689 | token = NULL; | ||
690 | r = mailimf_token_case_insensitive_parse(message, length, | ||
691 | &cur_token, "7bit"); | ||
692 | if (r == MAILIMF_NO_ERROR) | ||
693 | type = MAILMIME_MECHANISM_7BIT; | ||
694 | |||
695 | if (r == MAILIMF_ERROR_PARSE) { | ||
696 | r = mailimf_token_case_insensitive_parse(message, length, | ||
697 | &cur_token, "8bit"); | ||
698 | if (r == MAILIMF_NO_ERROR) | ||
699 | type = MAILMIME_MECHANISM_8BIT; | ||
700 | } | ||
701 | |||
702 | if (r == MAILIMF_ERROR_PARSE) { | ||
703 | r = mailimf_token_case_insensitive_parse(message, length, | ||
704 | &cur_token, "binary"); | ||
705 | if (r == MAILIMF_NO_ERROR) | ||
706 | type = MAILMIME_MECHANISM_BINARY; | ||
707 | } | ||
708 | |||
709 | if (r == MAILIMF_ERROR_PARSE) { | ||
710 | r = mailimf_token_case_insensitive_parse(message, length, | ||
711 | &cur_token, "quoted-printable"); | ||
712 | if (r == MAILIMF_NO_ERROR) | ||
713 | type = MAILMIME_MECHANISM_QUOTED_PRINTABLE; | ||
714 | } | ||
715 | |||
716 | if (r == MAILIMF_ERROR_PARSE) { | ||
717 | r = mailimf_token_case_insensitive_parse(message, length, | ||
718 | &cur_token, "base64"); | ||
719 | if (r == MAILIMF_NO_ERROR) | ||
720 | type = MAILMIME_MECHANISM_BASE64; | ||
721 | } | ||
722 | |||
723 | if (r == MAILIMF_ERROR_PARSE) { | ||
724 | r = mailmime_token_parse(message, length, &cur_token, &token); | ||
725 | if (r == MAILIMF_NO_ERROR) | ||
726 | type = MAILMIME_MECHANISM_TOKEN; | ||
727 | } | ||
728 | |||
729 | if (r != MAILIMF_NO_ERROR) { | ||
730 | res = r; | ||
731 | goto err; | ||
732 | } | ||
733 | |||
734 | mechanism = mailmime_mechanism_new(type, token); | ||
735 | if (mechanism == NULL) { | ||
736 | res = MAILIMF_ERROR_MEMORY; | ||
737 | goto free; | ||
738 | } | ||
739 | |||
740 | * result = mechanism; | ||
741 | * index = cur_token; | ||
742 | |||
743 | return MAILIMF_NO_ERROR; | ||
744 | |||
745 | free: | ||
746 | if (token != NULL) | ||
747 | mailmime_token_free(token); | ||
748 | err: | ||
749 | return res; | ||
750 | } | ||
751 | |||
752 | /* | ||
753 | x MIME-extension-field := <Any RFC 822 header field which | ||
754 | begins with the string | ||
755 | "Content-"> | ||
756 | */ | ||
757 | |||
758 | /* | ||
759 | in headers | ||
760 | |||
761 | x MIME-message-headers := entity-headers | ||
762 | fields | ||
763 | version CRLF | ||
764 | ; The ordering of the header | ||
765 | ; fields implied by this BNF | ||
766 | ; definition should be ignored. | ||
767 | */ | ||
768 | |||
769 | /* | ||
770 | in message | ||
771 | |||
772 | x MIME-part-headers := entity-headers | ||
773 | [fields] | ||
774 | ; Any field not beginning with | ||
775 | ; "content-" can have no defined | ||
776 | ; meaning and may be ignored. | ||
777 | ; The ordering of the header | ||
778 | ; fields implied by this BNF | ||
779 | ; definition should be ignored. | ||
780 | */ | ||
781 | |||
782 | #if 0 | ||
783 | int | ||
784 | mailmime_unparsed_fields_parse(struct mailimf_unparsed_fields * | ||
785 | fields, | ||
786 | struct mailmime_fields ** | ||
787 | result) | ||
788 | { | ||
789 | clistiter * cur; | ||
790 | struct mailmime_fields * mime_fields; | ||
791 | clist * list; | ||
792 | int r; | ||
793 | int res; | ||
794 | |||
795 | list = clist_new(); | ||
796 | if (list == NULL) { | ||
797 | res = MAILIMF_ERROR_MEMORY; | ||
798 | goto err; | ||
799 | } | ||
800 | |||
801 | if (fields->list == NULL) { | ||
802 | res = MAILIMF_ERROR_PARSE; | ||
803 | goto err; | ||
804 | } | ||
805 | |||
806 | for(cur = clist_begin(fields->list) ; cur != NULL ; | ||
807 | cur = clist_next(cur)) { | ||
808 | struct mailimf_optional_field * field = cur->data; | ||
809 | struct mailmime_field * mime_field; | ||
810 | |||
811 | r = mailmime_field_parse(field, &mime_field); | ||
812 | if (r == MAILIMF_NO_ERROR) { | ||
813 | r = clist_append(list, mime_field); | ||
814 | if (r < 0) { | ||
815 | mailmime_field_free(mime_field); | ||
816 | res = MAILIMF_ERROR_MEMORY; | ||
817 | goto free_list; | ||
818 | } | ||
819 | } | ||
820 | } | ||
821 | |||
822 | if (clist_begin(list) == NULL) { | ||
823 | res = MAILIMF_ERROR_PARSE; | ||
824 | goto free_list; | ||
825 | } | ||
826 | |||
827 | mime_fields = mailmime_fields_new(list); | ||
828 | if (mime_fields == NULL) { | ||
829 | res = MAILIMF_ERROR_MEMORY; | ||
830 | goto free_list; | ||
831 | } | ||
832 | |||
833 | * result = mime_fields; | ||
834 | |||
835 | return MAILIMF_NO_ERROR; | ||
836 | |||
837 | free_list: | ||
838 | clist_foreach(list, (clist_func) mailmime_field_free, NULL); | ||
839 | clist_free(list); | ||
840 | err: | ||
841 | return res; | ||
842 | } | ||
843 | #endif | ||
844 | |||
845 | int | ||
846 | mailmime_fields_parse(struct mailimf_fields * | ||
847 | fields, | ||
848 | struct mailmime_fields ** | ||
849 | result) | ||
850 | { | ||
851 | clistiter * cur; | ||
852 | struct mailmime_fields * mime_fields; | ||
853 | clist * list; | ||
854 | int r; | ||
855 | int res; | ||
856 | |||
857 | list = clist_new(); | ||
858 | if (list == NULL) { | ||
859 | res = MAILIMF_ERROR_MEMORY; | ||
860 | goto err; | ||
861 | } | ||
862 | |||
863 | for(cur = clist_begin(fields->fld_list) ; cur != NULL ; | ||
864 | cur = clist_next(cur)) { | ||
865 | struct mailimf_field * field; | ||
866 | struct mailmime_field * mime_field; | ||
867 | |||
868 | field = clist_content(cur); | ||
869 | |||
870 | if (field->fld_type == MAILIMF_FIELD_OPTIONAL_FIELD) { | ||
871 | r = mailmime_field_parse(field->fld_data.fld_optional_field, | ||
872 | &mime_field); | ||
873 | if (r == MAILIMF_NO_ERROR) { | ||
874 | r = clist_append(list, mime_field); | ||
875 | if (r < 0) { | ||
876 | mailmime_field_free(mime_field); | ||
877 | res = MAILIMF_ERROR_MEMORY; | ||
878 | goto free_list; | ||
879 | } | ||
880 | } | ||
881 | else if (r == MAILIMF_ERROR_PARSE) { | ||
882 | /* do nothing */ | ||
883 | } | ||
884 | else { | ||
885 | res = r; | ||
886 | goto free_list; | ||
887 | } | ||
888 | } | ||
889 | } | ||
890 | |||
891 | if (clist_begin(list) == NULL) { | ||
892 | res = MAILIMF_ERROR_PARSE; | ||
893 | goto free_list; | ||
894 | } | ||
895 | |||
896 | mime_fields = mailmime_fields_new(list); | ||
897 | if (mime_fields == NULL) { | ||
898 | res = MAILIMF_ERROR_MEMORY; | ||
899 | goto free_list; | ||
900 | } | ||
901 | |||
902 | * result = mime_fields; | ||
903 | |||
904 | return MAILIMF_NO_ERROR; | ||
905 | |||
906 | free_list: | ||
907 | clist_foreach(list, (clist_func) mailmime_field_free, NULL); | ||
908 | clist_free(list); | ||
909 | err: | ||
910 | return res; | ||
911 | } | ||
912 | |||
913 | /* | ||
914 | x parameter := attribute "=" value | ||
915 | */ | ||
916 | |||
917 | int mailmime_parameter_parse(const char * message, size_t length, | ||
918 | size_t * index, | ||
919 | struct mailmime_parameter ** result) | ||
920 | { | ||
921 | char * attribute; | ||
922 | char * value; | ||
923 | struct mailmime_parameter * parameter; | ||
924 | size_t cur_token; | ||
925 | int r; | ||
926 | int res; | ||
927 | |||
928 | cur_token = * index; | ||
929 | |||
930 | r = mailmime_attribute_parse(message, length, &cur_token, &attribute); | ||
931 | if (r != MAILIMF_NO_ERROR) { | ||
932 | res = r; | ||
933 | goto err; | ||
934 | } | ||
935 | |||
936 | r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); | ||
937 | if (r != MAILIMF_NO_ERROR) { | ||
938 | res = r; | ||
939 | goto free_attr; | ||
940 | } | ||
941 | |||
942 | r = mailimf_cfws_parse(message, length, &cur_token); | ||
943 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
944 | res = r; | ||
945 | goto free_attr; | ||
946 | } | ||
947 | |||
948 | r = mailmime_value_parse(message, length, &cur_token, &value); | ||
949 | if (r != MAILIMF_NO_ERROR) { | ||
950 | res = r; | ||
951 | goto free_attr; | ||
952 | } | ||
953 | |||
954 | parameter = mailmime_parameter_new(attribute, value); | ||
955 | if (parameter == NULL) { | ||
956 | res = MAILIMF_ERROR_MEMORY; | ||
957 | goto free_value; | ||
958 | } | ||
959 | |||
960 | * result = parameter; | ||
961 | * index = cur_token; | ||
962 | |||
963 | return MAILIMF_NO_ERROR; | ||
964 | |||
965 | free_value: | ||
966 | mailmime_value_free(value); | ||
967 | free_attr: | ||
968 | mailmime_attribute_free(attribute); | ||
969 | err: | ||
970 | return res; | ||
971 | } | ||
972 | |||
973 | /* | ||
974 | ptext := hex-octet / safe-char | ||
975 | */ | ||
976 | |||
977 | /* | ||
978 | qp-line := *(qp-segment transport-padding CRLF) | ||
979 | qp-part transport-padding | ||
980 | */ | ||
981 | |||
982 | /* | ||
983 | qp-part := qp-section | ||
984 | ; Maximum length of 76 characters | ||
985 | */ | ||
986 | |||
987 | /* | ||
988 | qp-section := [*(ptext / SPACE / TAB) ptext] | ||
989 | */ | ||
990 | |||
991 | /* | ||
992 | qp-segment := qp-section *(SPACE / TAB) "=" | ||
993 | ; Maximum length of 76 characters | ||
994 | */ | ||
995 | |||
996 | /* | ||
997 | quoted-printable := qp-line *(CRLF qp-line) | ||
998 | */ | ||
999 | |||
1000 | /* | ||
1001 | safe-char := <any octet with decimal value of 33 through | ||
1002 | 60 inclusive, and 62 through 126> | ||
1003 | ; Characters not listed as "mail-safe" in | ||
1004 | ; RFC 2049 are also not recommended. | ||
1005 | */ | ||
1006 | |||
1007 | /* | ||
1008 | x subtype := extension-token / iana-token | ||
1009 | */ | ||
1010 | |||
1011 | static int mailmime_subtype_parse(const char * message, size_t length, | ||
1012 | size_t * index, char ** result) | ||
1013 | { | ||
1014 | return mailmime_extension_token_parse(message, length, index, result); | ||
1015 | } | ||
1016 | |||
1017 | /* | ||
1018 | x token := 1*<any (US-ASCII) CHAR except SPACE, CTLs, | ||
1019 | or tspecials> | ||
1020 | */ | ||
1021 | |||
1022 | static int is_token(char ch) | ||
1023 | { | ||
1024 | unsigned char uch = (unsigned char) ch; | ||
1025 | |||
1026 | if (uch > 0x7F) | ||
1027 | return FALSE; | ||
1028 | |||
1029 | if (uch == ' ') | ||
1030 | return FALSE; | ||
1031 | |||
1032 | if (is_tspecials(ch)) | ||
1033 | return FALSE; | ||
1034 | |||
1035 | return TRUE; | ||
1036 | } | ||
1037 | |||
1038 | |||
1039 | static int mailmime_token_parse(const char * message, size_t length, | ||
1040 | size_t * index, | ||
1041 | char ** token) | ||
1042 | { | ||
1043 | return mailimf_custom_string_parse(message, length, | ||
1044 | index, token, | ||
1045 | is_token); | ||
1046 | } | ||
1047 | |||
1048 | /* | ||
1049 | transport-padding := *LWSP-char | ||
1050 | ; Composers MUST NOT generate | ||
1051 | ; non-zero length transport | ||
1052 | ; padding, but receivers MUST | ||
1053 | ; be able to handle padding | ||
1054 | ; added by message transports. | ||
1055 | */ | ||
1056 | |||
1057 | /* | ||
1058 | enum { | ||
1059 | LWSP_1, | ||
1060 | LWSP_2, | ||
1061 | LWSP_3, | ||
1062 | LWSP_4, | ||
1063 | LWSP_OK | ||
1064 | }; | ||
1065 | |||
1066 | gboolean mailmime_transport_padding_parse(gconst char * message, guint32 length, | ||
1067 | guint32 * index) | ||
1068 | { | ||
1069 | guint32 cur_token; | ||
1070 | gint state; | ||
1071 | guint32 last_valid_pos; | ||
1072 | |||
1073 | cur_token = * index; | ||
1074 | |||
1075 | if (cur_token >= length) | ||
1076 | return FALSE; | ||
1077 | |||
1078 | state = LWSP_1; | ||
1079 | |||
1080 | while (state != LWSP_OUT) { | ||
1081 | |||
1082 | if (cur_token >= length) | ||
1083 | return FALSE; | ||
1084 | |||
1085 | switch (state) { | ||
1086 | case LWSP_1: | ||
1087 | last_valid_pos = cur_token; | ||
1088 | |||
1089 | switch (message[cur_token]) { | ||
1090 | case '\r': | ||
1091 | state = LWSP_2; | ||
1092 | break; | ||
1093 | case '\n': | ||
1094 | state = LWSP_3; | ||
1095 | break; | ||
1096 | case ' ': | ||
1097 | case '\t': | ||
1098 | state = LWSP_4; | ||
1099 | break; | ||
1100 | default: | ||
1101 | state = LWSP_OK; | ||
1102 | break; | ||
1103 | } | ||
1104 | case LWSP_2: | ||
1105 | switch (message[cur_token]) { | ||
1106 | case '\n': | ||
1107 | state = LWSP_3; | ||
1108 | break; | ||
1109 | default: | ||
1110 | state = LWSP_OUT; | ||
1111 | cur_token = last_valid_pos; | ||
1112 | break; | ||
1113 | } | ||
1114 | case LWSP_3: | ||
1115 | switch (message[cur_token]) { | ||
1116 | case ' ': | ||
1117 | case '\t': | ||
1118 | state = LWSP_1; | ||
1119 | break; | ||
1120 | default: | ||
1121 | state = LWSP_OUT; | ||
1122 | cur_token = last_valid_pos; | ||
1123 | break; | ||
1124 | } | ||
1125 | |||
1126 | cur_token ++; | ||
1127 | } | ||
1128 | } | ||
1129 | |||
1130 | * index = cur_token; | ||
1131 | |||
1132 | return TRUE; | ||
1133 | } | ||
1134 | */ | ||
1135 | |||
1136 | /* | ||
1137 | x tspecials := "(" / ")" / "<" / ">" / "@" / | ||
1138 | "," / ";" / ":" / "\" / <"> | ||
1139 | "/" / "[" / "]" / "?" / "=" | ||
1140 | ; Must be in quoted-string, | ||
1141 | ; to use within parameter values | ||
1142 | */ | ||
1143 | |||
1144 | static int is_tspecials(char ch) | ||
1145 | { | ||
1146 | switch (ch) { | ||
1147 | case '(': | ||
1148 | case ')': | ||
1149 | case '<': | ||
1150 | case '>': | ||
1151 | case '@': | ||
1152 | case ',': | ||
1153 | case ';': | ||
1154 | case ':': | ||
1155 | case '\\': | ||
1156 | case '\"': | ||
1157 | case '/': | ||
1158 | case '[': | ||
1159 | case ']': | ||
1160 | case '?': | ||
1161 | case '=': | ||
1162 | return TRUE; | ||
1163 | default: | ||
1164 | return FALSE; | ||
1165 | } | ||
1166 | } | ||
1167 | |||
1168 | /* | ||
1169 | x type := discrete-type / composite-type | ||
1170 | */ | ||
1171 | |||
1172 | static int mailmime_type_parse(const char * message, size_t length, | ||
1173 | size_t * index, | ||
1174 | struct mailmime_type ** result) | ||
1175 | { | ||
1176 | struct mailmime_discrete_type * discrete_type; | ||
1177 | struct mailmime_composite_type * composite_type; | ||
1178 | size_t cur_token; | ||
1179 | struct mailmime_type * mime_type; | ||
1180 | int type; | ||
1181 | int res; | ||
1182 | int r; | ||
1183 | |||
1184 | cur_token = * index; | ||
1185 | |||
1186 | discrete_type = NULL; | ||
1187 | composite_type = NULL; | ||
1188 | |||
1189 | type = MAILMIME_TYPE_ERROR; /* XXX - removes a gcc warning */ | ||
1190 | |||
1191 | r = mailmime_composite_type_parse(message, length, &cur_token, | ||
1192 | &composite_type); | ||
1193 | if (r == MAILIMF_NO_ERROR) | ||
1194 | type = MAILMIME_TYPE_COMPOSITE_TYPE; | ||
1195 | |||
1196 | if (r == MAILIMF_ERROR_PARSE) { | ||
1197 | r = mailmime_discrete_type_parse(message, length, &cur_token, | ||
1198 | &discrete_type); | ||
1199 | if (r == MAILIMF_NO_ERROR) | ||
1200 | type = MAILMIME_TYPE_DISCRETE_TYPE; | ||
1201 | } | ||
1202 | |||
1203 | if (r != MAILIMF_NO_ERROR) { | ||
1204 | res = r; | ||
1205 | goto err; | ||
1206 | } | ||
1207 | |||
1208 | mime_type = mailmime_type_new(type, discrete_type, composite_type); | ||
1209 | if (mime_type == NULL) { | ||
1210 | res = r; | ||
1211 | goto free; | ||
1212 | } | ||
1213 | |||
1214 | * result = mime_type; | ||
1215 | * index = cur_token; | ||
1216 | |||
1217 | return MAILIMF_NO_ERROR; | ||
1218 | |||
1219 | free: | ||
1220 | if (discrete_type != NULL) | ||
1221 | mailmime_discrete_type_free(discrete_type); | ||
1222 | if (composite_type != NULL) | ||
1223 | mailmime_composite_type_free(composite_type); | ||
1224 | err: | ||
1225 | return res; | ||
1226 | } | ||
1227 | |||
1228 | /* | ||
1229 | x value := token / quoted-string | ||
1230 | */ | ||
1231 | |||
1232 | int mailmime_value_parse(const char * message, size_t length, | ||
1233 | size_t * index, char ** result) | ||
1234 | { | ||
1235 | int r; | ||
1236 | |||
1237 | r = mailmime_token_parse(message, length, index, result); | ||
1238 | |||
1239 | if (r == MAILIMF_ERROR_PARSE) | ||
1240 | r = mailimf_quoted_string_parse(message, length, index, result); | ||
1241 | |||
1242 | if (r != MAILIMF_NO_ERROR) | ||
1243 | return r; | ||
1244 | |||
1245 | return MAILIMF_NO_ERROR; | ||
1246 | } | ||
1247 | |||
1248 | /* | ||
1249 | x version := "MIME-Version" ":" 1*DIGIT "." 1*DIGIT | ||
1250 | */ | ||
1251 | |||
1252 | int mailmime_version_parse(const char * message, size_t length, | ||
1253 | size_t * index, | ||
1254 | uint32_t * result) | ||
1255 | { | ||
1256 | size_t cur_token; | ||
1257 | uint32_t hi; | ||
1258 | uint32_t low; | ||
1259 | uint32_t version; | ||
1260 | int r; | ||
1261 | |||
1262 | cur_token = * index; | ||
1263 | |||
1264 | r = mailimf_number_parse(message, length, &cur_token, &hi); | ||
1265 | if (r != MAILIMF_NO_ERROR) | ||
1266 | return r; | ||
1267 | |||
1268 | r = mailimf_unstrict_char_parse(message, length, &cur_token, '.'); | ||
1269 | if (r != MAILIMF_NO_ERROR) | ||
1270 | return r; | ||
1271 | |||
1272 | r = mailimf_cfws_parse(message, length, &cur_token); | ||
1273 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) | ||
1274 | return r; | ||
1275 | |||
1276 | r = mailimf_number_parse(message, length, &cur_token, &low); | ||
1277 | if (r != MAILIMF_NO_ERROR) | ||
1278 | return r; | ||
1279 | |||
1280 | version = (hi << 16) + low; | ||
1281 | |||
1282 | * result = version; | ||
1283 | * index = cur_token; | ||
1284 | |||
1285 | return MAILIMF_NO_ERROR; | ||
1286 | } | ||
1287 | |||
1288 | /* | ||
1289 | x x-token := <The two characters "X-" or "x-" followed, with | ||
1290 | no intervening white space, by any token> | ||
1291 | */ | ||
1292 | |||
1293 | /* | ||
1294 | static gboolean mailmime_x_token_parse(gconst char * message, guint32 length, | ||
1295 | guint32 * index, | ||
1296 | gchar ** result) | ||
1297 | { | ||
1298 | guint32 cur_token; | ||
1299 | gchar * token; | ||
1300 | gchar * x_token; | ||
1301 | gboolean min_x; | ||
1302 | |||
1303 | cur_token = * index; | ||
1304 | |||
1305 | if (!mailimf_char_parse(message, length, &cur_token, 'x')) { | ||
1306 | if (!mailimf_char_parse(message, length, &cur_token, 'X')) | ||
1307 | return FALSE; | ||
1308 | min_x = FALSE; | ||
1309 | } | ||
1310 | else | ||
1311 | min_x = TRUE; | ||
1312 | |||
1313 | if (!mailimf_char_parse(message, length, &cur_token, '-')) | ||
1314 | return FALSE; | ||
1315 | |||
1316 | if (!mailmime_token_parse(message, length, &cur_token, &token)) | ||
1317 | return FALSE; | ||
1318 | |||
1319 | if (min_x) | ||
1320 | x_token = g_strconcat("x-", token, NULL); | ||
1321 | else | ||
1322 | x_token = g_strconcat("X-", token, NULL); | ||
1323 | mailmime_token_free(token); | ||
1324 | |||
1325 | if (x_token == NULL) | ||
1326 | return FALSE; | ||
1327 | |||
1328 | * result = x_token; | ||
1329 | * index = cur_token; | ||
1330 | |||
1331 | return TRUE; | ||
1332 | } | ||
1333 | */ | ||
1334 | |||
1335 | |||
1336 | int mailmime_language_parse(const char * message, size_t length, | ||
1337 | size_t * index, | ||
1338 | struct mailmime_language ** result) | ||
1339 | { | ||
1340 | size_t cur_token; | ||
1341 | int r; | ||
1342 | int res; | ||
1343 | clist * list; | ||
1344 | int first; | ||
1345 | struct mailmime_language * language; | ||
1346 | |||
1347 | cur_token = * index; | ||
1348 | |||
1349 | list = clist_new(); | ||
1350 | if (list == NULL) { | ||
1351 | res = MAILIMF_ERROR_MEMORY; | ||
1352 | goto err; | ||
1353 | } | ||
1354 | |||
1355 | first = TRUE; | ||
1356 | |||
1357 | while (1) { | ||
1358 | char * atom; | ||
1359 | |||
1360 | r = mailimf_unstrict_char_parse(message, length, &cur_token, ','); | ||
1361 | if (r == MAILIMF_NO_ERROR) { | ||
1362 | /* do nothing */ | ||
1363 | } | ||
1364 | else if (r == MAILIMF_ERROR_PARSE) { | ||
1365 | break; | ||
1366 | } | ||
1367 | else { | ||
1368 | res = r; | ||
1369 | goto err; | ||
1370 | } | ||
1371 | |||
1372 | r = mailimf_atom_parse(message, length, &cur_token, &atom); | ||
1373 | if (r == MAILIMF_NO_ERROR) { | ||
1374 | /* do nothing */ | ||
1375 | } | ||
1376 | else if (r == MAILIMF_ERROR_PARSE) { | ||
1377 | break; | ||
1378 | } | ||
1379 | else { | ||
1380 | res = r; | ||
1381 | goto err; | ||
1382 | } | ||
1383 | |||
1384 | r = clist_append(list, atom); | ||
1385 | if (r < 0) { | ||
1386 | mailimf_atom_free(atom); | ||
1387 | res = MAILIMF_ERROR_MEMORY; | ||
1388 | goto free; | ||
1389 | } | ||
1390 | } | ||
1391 | |||
1392 | language = mailmime_language_new(list); | ||
1393 | if (language == NULL) { | ||
1394 | res = MAILIMF_ERROR_MEMORY; | ||
1395 | goto free; | ||
1396 | } | ||
1397 | |||
1398 | * result = language; | ||
1399 | * index = cur_token; | ||
1400 | |||
1401 | return MAILIMF_NO_ERROR; | ||
1402 | |||
1403 | free: | ||
1404 | clist_foreach(list, (clist_func) mailimf_atom_free, NULL); | ||
1405 | clist_free(list); | ||
1406 | err: | ||
1407 | return res; | ||
1408 | } | ||
diff --git a/kmicromail/libetpan/mime/mailmime.h b/kmicromail/libetpan/mime/mailmime.h new file mode 100644 index 0000000..c834967 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime.h | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #ifndef MAILMIME_H | ||
37 | |||
38 | #define MAILMIME_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <libetpan/mailimf.h> | ||
45 | #include <libetpan/mailmime_types.h> | ||
46 | #include <libetpan/mailmime_types_helper.h> | ||
47 | #include <libetpan/mailmime_content.h> | ||
48 | #include <libetpan/mailmime_decode.h> | ||
49 | #include <libetpan/mailmime_disposition.h> | ||
50 | #include <libetpan/mailmime_write.h> | ||
51 | |||
52 | int mailmime_content_parse(const char * message, size_t length, | ||
53 | size_t * index, | ||
54 | struct mailmime_content ** result); | ||
55 | |||
56 | int mailmime_description_parse(const char * message, size_t length, | ||
57 | size_t * index, | ||
58 | char ** result); | ||
59 | |||
60 | int mailmime_encoding_parse(const char * message, size_t length, | ||
61 | size_t * index, | ||
62 | struct mailmime_mechanism ** result); | ||
63 | |||
64 | int | ||
65 | mailmime_field_parse(struct mailimf_optional_field * field, | ||
66 | struct mailmime_field ** result); | ||
67 | |||
68 | int mailmime_id_parse(const char * message, size_t length, | ||
69 | size_t * index, char ** result); | ||
70 | |||
71 | int | ||
72 | mailmime_fields_parse(struct mailimf_fields * | ||
73 | fields, | ||
74 | struct mailmime_fields ** | ||
75 | result); | ||
76 | |||
77 | int mailmime_version_parse(const char * message, size_t length, | ||
78 | size_t * index, | ||
79 | uint32_t * result); | ||
80 | |||
81 | int | ||
82 | mailmime_extension_token_parse(const char * message, size_t length, | ||
83 | size_t * index, char ** result); | ||
84 | |||
85 | int mailmime_parameter_parse(const char * message, size_t length, | ||
86 | size_t * index, | ||
87 | struct mailmime_parameter ** result); | ||
88 | |||
89 | int mailmime_value_parse(const char * message, size_t length, | ||
90 | size_t * index, char ** result); | ||
91 | |||
92 | int mailmime_language_parse(const char * message, size_t length, | ||
93 | size_t * index, | ||
94 | struct mailmime_language ** result); | ||
95 | |||
96 | #ifdef __cplusplus | ||
97 | } | ||
98 | #endif | ||
99 | |||
100 | #endif | ||
diff --git a/kmicromail/libetpan/mime/mailmime_content.c b/kmicromail/libetpan/mime/mailmime_content.c new file mode 100644 index 0000000..c73812d --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_content.c | |||
@@ -0,0 +1,2164 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #include "mailimf.h" | ||
37 | |||
38 | #include <string.h> | ||
39 | #include <stdlib.h> | ||
40 | |||
41 | #include "mailmime.h" | ||
42 | #include "mailmime_types.h" | ||
43 | #include "mmapstring.h" | ||
44 | |||
45 | #ifndef TRUE | ||
46 | #define TRUE 1 | ||
47 | #endif | ||
48 | |||
49 | #ifndef FALSE | ||
50 | #define FALSE 0 | ||
51 | #endif | ||
52 | |||
53 | /* | ||
54 | RFC 2045 | ||
55 | RFC 2046 | ||
56 | RFC 2047 | ||
57 | |||
58 | RFC 2231 | ||
59 | */ | ||
60 | |||
61 | |||
62 | static int mailmime_parse_with_default(const char * message, size_t length, | ||
63 | size_t * index, int default_type, | ||
64 | struct mailmime_content * content_type, | ||
65 | struct mailmime_fields * mime_fields, | ||
66 | struct mailmime ** result); | ||
67 | |||
68 | |||
69 | |||
70 | char * mailmime_content_charset_get(struct mailmime_content * content) | ||
71 | { | ||
72 | char * charset; | ||
73 | |||
74 | charset = mailmime_content_param_get(content, "charset"); | ||
75 | if (charset == NULL) | ||
76 | return "us-ascii"; | ||
77 | else | ||
78 | return charset; | ||
79 | } | ||
80 | |||
81 | char * mailmime_content_param_get(struct mailmime_content * content, | ||
82 | char * name) | ||
83 | { | ||
84 | clistiter * cur; | ||
85 | |||
86 | for(cur = clist_begin(content->ct_parameters) ; | ||
87 | cur != NULL ; cur = clist_next(cur)) { | ||
88 | struct mailmime_parameter * param; | ||
89 | |||
90 | param = clist_content(cur); | ||
91 | |||
92 | if (strcasecmp(param->pa_name, name) == 0) | ||
93 | return param->pa_value; | ||
94 | } | ||
95 | |||
96 | return NULL; | ||
97 | } | ||
98 | |||
99 | |||
100 | /* | ||
101 | boundary := 0*69<bchars> bcharsnospace | ||
102 | */ | ||
103 | |||
104 | /* | ||
105 | bchars := bcharsnospace / " " | ||
106 | */ | ||
107 | |||
108 | /* | ||
109 | bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / | ||
110 | "+" / "_" / "," / "-" / "." / | ||
111 | "/" / ":" / "=" / "?" | ||
112 | */ | ||
113 | |||
114 | /* | ||
115 | body-part := <"message" as defined in RFC 822, with all | ||
116 | header fields optional, not starting with the | ||
117 | specified dash-boundary, and with the | ||
118 | delimiter not occurring anywhere in the | ||
119 | body part. Note that the semantics of a | ||
120 | part differ from the semantics of a message, | ||
121 | as described in the text.> | ||
122 | */ | ||
123 | |||
124 | /* | ||
125 | close-delimiter := delimiter "--" | ||
126 | */ | ||
127 | |||
128 | /* | ||
129 | dash-boundary := "--" boundary | ||
130 | ; boundary taken from the value of | ||
131 | ; boundary parameter of the | ||
132 | ; Content-Type field. | ||
133 | */ | ||
134 | |||
135 | /* | ||
136 | delimiter := CRLF dash-boundary | ||
137 | */ | ||
138 | |||
139 | /* | ||
140 | discard-text := *(*text CRLF) | ||
141 | ; May be ignored or discarded. | ||
142 | */ | ||
143 | |||
144 | /* | ||
145 | encapsulation := delimiter transport-padding | ||
146 | CRLF body-part | ||
147 | */ | ||
148 | |||
149 | /* | ||
150 | epilogue := discard-text | ||
151 | */ | ||
152 | |||
153 | /* | ||
154 | multipart-body := [preamble CRLF] | ||
155 | dash-boundary transport-padding CRLF | ||
156 | body-part *encapsulation | ||
157 | close-delimiter transport-padding | ||
158 | [CRLF epilogue] | ||
159 | */ | ||
160 | |||
161 | /* | ||
162 | preamble := discard-text | ||
163 | */ | ||
164 | |||
165 | /* | ||
166 | transport-padding := *LWSP-char | ||
167 | ; Composers MUST NOT generate | ||
168 | ; non-zero length transport | ||
169 | ; padding, but receivers MUST | ||
170 | ; be able to handle padding | ||
171 | ; added by message transports. | ||
172 | */ | ||
173 | |||
174 | |||
175 | /* | ||
176 | ACCESS-TYPE | ||
177 | EXPIRATION | ||
178 | SIZE | ||
179 | PERMISSION | ||
180 | */ | ||
181 | |||
182 | /* | ||
183 | 5.2.3.2. The 'ftp' and 'tftp' Access-Types | ||
184 | NAME | ||
185 | SITE | ||
186 | |||
187 | (3) Before any data are retrieved, using FTP, the user will | ||
188 | generally need to be asked to provide a login id and a | ||
189 | password for the machine named by the site parameter. | ||
190 | For security reasons, such an id and password are not | ||
191 | specified as content-type parameters, but must be | ||
192 | obtained from the user. | ||
193 | |||
194 | optional : | ||
195 | DIRECTORY | ||
196 | MODE | ||
197 | */ | ||
198 | |||
199 | /* | ||
200 | 5.2.3.3. The 'anon-ftp' Access-Type | ||
201 | */ | ||
202 | |||
203 | /* | ||
204 | 5.2.3.4. The 'local-file' Access-Type | ||
205 | NAME | ||
206 | SITE | ||
207 | */ | ||
208 | |||
209 | /* | ||
210 | 5.2.3.5. The 'mail-server' Access-Type | ||
211 | SERVER | ||
212 | SUBJECT | ||
213 | */ | ||
214 | |||
215 | |||
216 | enum { | ||
217 | PREAMBLE_STATE_A0, | ||
218 | PREAMBLE_STATE_A, | ||
219 | PREAMBLE_STATE_A1, | ||
220 | PREAMBLE_STATE_B, | ||
221 | PREAMBLE_STATE_C, | ||
222 | PREAMBLE_STATE_D, | ||
223 | PREAMBLE_STATE_E | ||
224 | }; | ||
225 | |||
226 | static int mailmime_preamble_parse(const char * message, size_t length, | ||
227 | size_t * index, int beol) | ||
228 | { | ||
229 | int state; | ||
230 | size_t cur_token; | ||
231 | |||
232 | cur_token = * index; | ||
233 | if (beol) | ||
234 | state = PREAMBLE_STATE_A0; | ||
235 | else | ||
236 | state = PREAMBLE_STATE_A; | ||
237 | |||
238 | while (state != PREAMBLE_STATE_E) { | ||
239 | |||
240 | if (cur_token >= length) | ||
241 | return MAILIMF_ERROR_PARSE; | ||
242 | |||
243 | switch (state) { | ||
244 | case PREAMBLE_STATE_A0: | ||
245 | switch (message[cur_token]) { | ||
246 | case '-': | ||
247 | state = PREAMBLE_STATE_A1; | ||
248 | break; | ||
249 | case '\r': | ||
250 | state = PREAMBLE_STATE_B; | ||
251 | break; | ||
252 | case '\n': | ||
253 | state = PREAMBLE_STATE_C; | ||
254 | break; | ||
255 | default: | ||
256 | state = PREAMBLE_STATE_A; | ||
257 | break; | ||
258 | } | ||
259 | break; | ||
260 | |||
261 | case PREAMBLE_STATE_A: | ||
262 | switch (message[cur_token]) { | ||
263 | case '\r': | ||
264 | state = PREAMBLE_STATE_B; | ||
265 | break; | ||
266 | case '\n': | ||
267 | state = PREAMBLE_STATE_C; | ||
268 | break; | ||
269 | default: | ||
270 | state = PREAMBLE_STATE_A; | ||
271 | break; | ||
272 | } | ||
273 | break; | ||
274 | |||
275 | case PREAMBLE_STATE_A1: | ||
276 | switch (message[cur_token]) { | ||
277 | case '-': | ||
278 | state = PREAMBLE_STATE_E; | ||
279 | break; | ||
280 | case '\r': | ||
281 | state = PREAMBLE_STATE_B; | ||
282 | break; | ||
283 | case '\n': | ||
284 | state = PREAMBLE_STATE_C; | ||
285 | break; | ||
286 | default: | ||
287 | state = PREAMBLE_STATE_A; | ||
288 | break; | ||
289 | } | ||
290 | break; | ||
291 | |||
292 | case PREAMBLE_STATE_B: | ||
293 | switch (message[cur_token]) { | ||
294 | case '\r': | ||
295 | state = PREAMBLE_STATE_B; | ||
296 | break; | ||
297 | case '\n': | ||
298 | state = PREAMBLE_STATE_C; | ||
299 | break; | ||
300 | case '-': | ||
301 | state = PREAMBLE_STATE_D; | ||
302 | break; | ||
303 | default: | ||
304 | state = PREAMBLE_STATE_A0; | ||
305 | break; | ||
306 | } | ||
307 | break; | ||
308 | |||
309 | case PREAMBLE_STATE_C: | ||
310 | switch (message[cur_token]) { | ||
311 | case '-': | ||
312 | state = PREAMBLE_STATE_D; | ||
313 | break; | ||
314 | case '\r': | ||
315 | state = PREAMBLE_STATE_B; | ||
316 | break; | ||
317 | case '\n': | ||
318 | state = PREAMBLE_STATE_C; | ||
319 | break; | ||
320 | default: | ||
321 | state = PREAMBLE_STATE_A0; | ||
322 | break; | ||
323 | } | ||
324 | break; | ||
325 | |||
326 | case PREAMBLE_STATE_D: | ||
327 | switch (message[cur_token]) { | ||
328 | case '-': | ||
329 | state = PREAMBLE_STATE_E; | ||
330 | break; | ||
331 | default: | ||
332 | state = PREAMBLE_STATE_A; | ||
333 | break; | ||
334 | } | ||
335 | break; | ||
336 | } | ||
337 | |||
338 | cur_token ++; | ||
339 | } | ||
340 | |||
341 | * index = cur_token; | ||
342 | |||
343 | return MAILIMF_NO_ERROR; | ||
344 | } | ||
345 | |||
346 | static int mailmime_boundary_parse(const char * message, size_t length, | ||
347 | size_t * index, char * boundary) | ||
348 | { | ||
349 | size_t cur_token; | ||
350 | size_t len; | ||
351 | |||
352 | cur_token = * index; | ||
353 | |||
354 | len = strlen(boundary); | ||
355 | |||
356 | if (cur_token + len >= length) | ||
357 | return MAILIMF_ERROR_PARSE; | ||
358 | |||
359 | if (strncmp(message + cur_token, boundary, len) != 0) | ||
360 | return MAILIMF_ERROR_PARSE; | ||
361 | |||
362 | cur_token += len; | ||
363 | |||
364 | * index = cur_token; | ||
365 | |||
366 | return MAILIMF_NO_ERROR; | ||
367 | } | ||
368 | |||
369 | static int is_wsp(char ch) | ||
370 | { | ||
371 | if ((ch == ' ') || (ch == '\t')) | ||
372 | return TRUE; | ||
373 | |||
374 | return FALSE; | ||
375 | } | ||
376 | |||
377 | static int mailmime_lwsp_parse(const char * message, size_t length, | ||
378 | size_t * index) | ||
379 | { | ||
380 | size_t cur_token; | ||
381 | |||
382 | cur_token = * index; | ||
383 | |||
384 | if (cur_token >= length) | ||
385 | return MAILIMF_ERROR_PARSE; | ||
386 | |||
387 | while (is_wsp(message[cur_token])) { | ||
388 | cur_token ++; | ||
389 | if (cur_token >= length) | ||
390 | break; | ||
391 | } | ||
392 | |||
393 | if (cur_token == * index) | ||
394 | return MAILIMF_ERROR_PARSE; | ||
395 | |||
396 | * index = cur_token; | ||
397 | |||
398 | return MAILIMF_NO_ERROR; | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | gboolean mailimf_crlf_parse(gchar * message, guint32 length, guint32 * index) | ||
403 | */ | ||
404 | |||
405 | enum { | ||
406 | BODY_PART_DASH2_STATE_0, | ||
407 | BODY_PART_DASH2_STATE_1, | ||
408 | BODY_PART_DASH2_STATE_2, | ||
409 | BODY_PART_DASH2_STATE_3, | ||
410 | BODY_PART_DASH2_STATE_4, | ||
411 | BODY_PART_DASH2_STATE_5, | ||
412 | BODY_PART_DASH2_STATE_6 | ||
413 | }; | ||
414 | |||
415 | static int | ||
416 | mailmime_body_part_dash2_parse(const char * message, size_t length, | ||
417 | size_t * index, char * boundary, | ||
418 | const char ** result, size_t * result_size) | ||
419 | { | ||
420 | int state; | ||
421 | size_t cur_token; | ||
422 | size_t size; | ||
423 | size_t begin_text; | ||
424 | size_t end_text; | ||
425 | int r; | ||
426 | |||
427 | cur_token = * index; | ||
428 | state = BODY_PART_DASH2_STATE_0; | ||
429 | |||
430 | begin_text = cur_token; | ||
431 | end_text = length; | ||
432 | |||
433 | while (state != BODY_PART_DASH2_STATE_5) { | ||
434 | |||
435 | if (cur_token >= length) | ||
436 | break; | ||
437 | |||
438 | switch(state) { | ||
439 | |||
440 | case BODY_PART_DASH2_STATE_0: | ||
441 | switch (message[cur_token]) { | ||
442 | case '\r': | ||
443 | state = BODY_PART_DASH2_STATE_1; | ||
444 | break; | ||
445 | case '\n': | ||
446 | state = BODY_PART_DASH2_STATE_2; | ||
447 | break; | ||
448 | default: | ||
449 | state = BODY_PART_DASH2_STATE_0; | ||
450 | break; | ||
451 | } | ||
452 | break; | ||
453 | |||
454 | case BODY_PART_DASH2_STATE_1: | ||
455 | switch (message[cur_token]) { | ||
456 | case '\n': | ||
457 | state = BODY_PART_DASH2_STATE_2; | ||
458 | break; | ||
459 | default: | ||
460 | state = BODY_PART_DASH2_STATE_0; | ||
461 | break; | ||
462 | } | ||
463 | break; | ||
464 | |||
465 | case BODY_PART_DASH2_STATE_2: | ||
466 | switch (message[cur_token]) { | ||
467 | case '-': | ||
468 | end_text = cur_token; | ||
469 | state = BODY_PART_DASH2_STATE_3; | ||
470 | break; | ||
471 | case '\r': | ||
472 | state = BODY_PART_DASH2_STATE_1; | ||
473 | break; | ||
474 | case '\n': | ||
475 | state = BODY_PART_DASH2_STATE_2; | ||
476 | break; | ||
477 | default: | ||
478 | state = BODY_PART_DASH2_STATE_0; | ||
479 | break; | ||
480 | } | ||
481 | break; | ||
482 | |||
483 | case BODY_PART_DASH2_STATE_3: | ||
484 | switch (message[cur_token]) { | ||
485 | case '\r': | ||
486 | state = BODY_PART_DASH2_STATE_1; | ||
487 | break; | ||
488 | case '\n': | ||
489 | state = BODY_PART_DASH2_STATE_2; | ||
490 | break; | ||
491 | case '-': | ||
492 | state = BODY_PART_DASH2_STATE_4; | ||
493 | break; | ||
494 | default: | ||
495 | state = BODY_PART_DASH2_STATE_0; | ||
496 | break; | ||
497 | } | ||
498 | break; | ||
499 | |||
500 | case BODY_PART_DASH2_STATE_4: | ||
501 | r = mailmime_boundary_parse(message, length, &cur_token, boundary); | ||
502 | if (r == MAILIMF_NO_ERROR) | ||
503 | state = BODY_PART_DASH2_STATE_5; | ||
504 | else | ||
505 | state = BODY_PART_DASH2_STATE_6; | ||
506 | |||
507 | break; | ||
508 | } | ||
509 | |||
510 | if ((state != BODY_PART_DASH2_STATE_5) && | ||
511 | (state != BODY_PART_DASH2_STATE_6)) | ||
512 | cur_token ++; | ||
513 | |||
514 | if (state == BODY_PART_DASH2_STATE_6) | ||
515 | state = BODY_PART_DASH2_STATE_0; | ||
516 | } | ||
517 | |||
518 | end_text --; | ||
519 | if (end_text >= 1) | ||
520 | if (message[end_text - 1] == '\r') | ||
521 | end_text --; | ||
522 | |||
523 | size = end_text - begin_text; | ||
524 | |||
525 | #if 0 | ||
526 | body_part = mailimf_body_new(message + begin_text, size); | ||
527 | if (body_part == NULL) | ||
528 | goto err; | ||
529 | #endif | ||
530 | |||
531 | * result = message + begin_text; | ||
532 | * result_size = size; | ||
533 | * index = cur_token; | ||
534 | |||
535 | return MAILIMF_NO_ERROR; | ||
536 | #if 0 | ||
537 | err: | ||
538 | return MAILIMF_ERROR_PARSE; | ||
539 | #endif | ||
540 | } | ||
541 | |||
542 | enum { | ||
543 | MULTIPART_CLOSE_STATE_0, | ||
544 | MULTIPART_CLOSE_STATE_1, | ||
545 | MULTIPART_CLOSE_STATE_2, | ||
546 | MULTIPART_CLOSE_STATE_3, | ||
547 | MULTIPART_CLOSE_STATE_4 | ||
548 | }; | ||
549 | |||
550 | static int mailmime_multipart_close_parse(const char * message, size_t length, | ||
551 | size_t * index) | ||
552 | { | ||
553 | int state; | ||
554 | size_t cur_token; | ||
555 | |||
556 | cur_token = * index; | ||
557 | state = MULTIPART_CLOSE_STATE_0; | ||
558 | |||
559 | while (state != MULTIPART_CLOSE_STATE_4) { | ||
560 | |||
561 | switch(state) { | ||
562 | |||
563 | case MULTIPART_CLOSE_STATE_0: | ||
564 | if (cur_token >= length) | ||
565 | return MAILIMF_ERROR_PARSE; | ||
566 | |||
567 | switch (message[cur_token]) { | ||
568 | case '-': | ||
569 | state = MULTIPART_CLOSE_STATE_1; | ||
570 | break; | ||
571 | default: | ||
572 | return MAILIMF_ERROR_PARSE; | ||
573 | } | ||
574 | break; | ||
575 | |||
576 | case MULTIPART_CLOSE_STATE_1: | ||
577 | if (cur_token >= length) | ||
578 | return MAILIMF_ERROR_PARSE; | ||
579 | |||
580 | switch (message[cur_token]) { | ||
581 | case '-': | ||
582 | state = MULTIPART_CLOSE_STATE_2; | ||
583 | break; | ||
584 | default: | ||
585 | return MAILIMF_ERROR_PARSE; | ||
586 | } | ||
587 | break; | ||
588 | |||
589 | case MULTIPART_CLOSE_STATE_2: | ||
590 | if (cur_token >= length) { | ||
591 | state = MULTIPART_CLOSE_STATE_4; | ||
592 | break; | ||
593 | } | ||
594 | |||
595 | switch (message[cur_token]) { | ||
596 | case ' ': | ||
597 | state = MULTIPART_CLOSE_STATE_2; | ||
598 | break; | ||
599 | case '\t': | ||
600 | state = MULTIPART_CLOSE_STATE_2; | ||
601 | break; | ||
602 | case '\r': | ||
603 | state = MULTIPART_CLOSE_STATE_3; | ||
604 | break; | ||
605 | case '\n': | ||
606 | state = MULTIPART_CLOSE_STATE_4; | ||
607 | break; | ||
608 | default: | ||
609 | state = MULTIPART_CLOSE_STATE_4; | ||
610 | break; | ||
611 | } | ||
612 | break; | ||
613 | |||
614 | case MULTIPART_CLOSE_STATE_3: | ||
615 | if (cur_token >= length) { | ||
616 | state = MULTIPART_CLOSE_STATE_4; | ||
617 | break; | ||
618 | } | ||
619 | |||
620 | switch (message[cur_token]) { | ||
621 | case '\n': | ||
622 | state = MULTIPART_CLOSE_STATE_4; | ||
623 | break; | ||
624 | default: | ||
625 | state = MULTIPART_CLOSE_STATE_4; | ||
626 | break; | ||
627 | } | ||
628 | break; | ||
629 | } | ||
630 | |||
631 | cur_token ++; | ||
632 | } | ||
633 | |||
634 | * index = cur_token; | ||
635 | |||
636 | return MAILIMF_NO_ERROR; | ||
637 | } | ||
638 | |||
639 | enum { | ||
640 | MULTIPART_NEXT_STATE_0, | ||
641 | MULTIPART_NEXT_STATE_1, | ||
642 | MULTIPART_NEXT_STATE_2 | ||
643 | }; | ||
644 | |||
645 | int mailmime_multipart_next_parse(const char * message, size_t length, | ||
646 | size_t * index) | ||
647 | { | ||
648 | int state; | ||
649 | size_t cur_token; | ||
650 | |||
651 | cur_token = * index; | ||
652 | state = MULTIPART_NEXT_STATE_0; | ||
653 | |||
654 | while (state != MULTIPART_NEXT_STATE_2) { | ||
655 | |||
656 | if (cur_token >= length) | ||
657 | return MAILIMF_ERROR_PARSE; | ||
658 | |||
659 | switch(state) { | ||
660 | |||
661 | case MULTIPART_NEXT_STATE_0: | ||
662 | switch (message[cur_token]) { | ||
663 | case ' ': | ||
664 | state = MULTIPART_NEXT_STATE_0; | ||
665 | break; | ||
666 | case '\t': | ||
667 | state = MULTIPART_NEXT_STATE_0; | ||
668 | break; | ||
669 | case '\r': | ||
670 | state = MULTIPART_NEXT_STATE_1; | ||
671 | break; | ||
672 | case '\n': | ||
673 | state = MULTIPART_NEXT_STATE_2; | ||
674 | break; | ||
675 | default: | ||
676 | return MAILIMF_ERROR_PARSE; | ||
677 | } | ||
678 | break; | ||
679 | |||
680 | case MULTIPART_NEXT_STATE_1: | ||
681 | switch (message[cur_token]) { | ||
682 | case '\n': | ||
683 | state = MULTIPART_NEXT_STATE_2; | ||
684 | break; | ||
685 | default: | ||
686 | return MAILIMF_ERROR_PARSE; | ||
687 | } | ||
688 | break; | ||
689 | } | ||
690 | |||
691 | cur_token ++; | ||
692 | } | ||
693 | |||
694 | * index = cur_token; | ||
695 | |||
696 | return MAILIMF_NO_ERROR; | ||
697 | } | ||
698 | |||
699 | static int | ||
700 | mailmime_multipart_body_parse(const char * message, size_t length, | ||
701 | size_t * index, char * boundary, | ||
702 | int default_subtype, | ||
703 | clist ** result, | ||
704 | struct mailmime_data ** p_preamble, | ||
705 | struct mailmime_data ** p_epilogue) | ||
706 | { | ||
707 | size_t cur_token; | ||
708 | clist * list; | ||
709 | int r; | ||
710 | int res; | ||
711 | #if 0 | ||
712 | size_t begin; | ||
713 | #endif | ||
714 | size_t preamble_begin; | ||
715 | size_t preamble_length; | ||
716 | size_t preamble_end; | ||
717 | #if 0 | ||
718 | int no_preamble; | ||
719 | size_t before_crlf; | ||
720 | #endif | ||
721 | size_t epilogue_begin; | ||
722 | size_t epilogue_length; | ||
723 | struct mailmime_data * preamble; | ||
724 | struct mailmime_data * epilogue; | ||
725 | size_t part_begin; | ||
726 | |||
727 | preamble = NULL; | ||
728 | epilogue = NULL; | ||
729 | |||
730 | cur_token = * index; | ||
731 | preamble_begin = cur_token; | ||
732 | |||
733 | #if 0 | ||
734 | no_preamble = FALSE; | ||
735 | #endif | ||
736 | preamble_end = preamble_begin; | ||
737 | |||
738 | #if 0 | ||
739 | r = mailmime_preamble_parse(message, length, &cur_token); | ||
740 | if (r == MAILIMF_NO_ERROR) { | ||
741 | /* do nothing */ | ||
742 | #if 0 | ||
743 | preamble_end = cur_token - 2; | ||
744 | #endif | ||
745 | } | ||
746 | else if (r == MAILIMF_ERROR_PARSE) { | ||
747 | /* do nothing */ | ||
748 | no_preamble = TRUE; | ||
749 | } | ||
750 | else { | ||
751 | res = r; | ||
752 | goto err; | ||
753 | } | ||
754 | |||
755 | while (1) { | ||
756 | |||
757 | preamble_end = cur_token; | ||
758 | r = mailmime_boundary_parse(message, length, &cur_token, boundary); | ||
759 | if (r == MAILIMF_NO_ERROR) { | ||
760 | break; | ||
761 | } | ||
762 | else if (r == MAILIMF_ERROR_PARSE) { | ||
763 | /* do nothing */ | ||
764 | } | ||
765 | else { | ||
766 | res = r; | ||
767 | goto err; | ||
768 | } | ||
769 | |||
770 | r = mailmime_preamble_parse(message, length, &cur_token); | ||
771 | if (r == MAILIMF_NO_ERROR) { | ||
772 | #if 0 | ||
773 | preamble_end = cur_token - 2; | ||
774 | #endif | ||
775 | } | ||
776 | else if (r == MAILIMF_ERROR_PARSE) { | ||
777 | no_preamble = TRUE; | ||
778 | break; | ||
779 | } | ||
780 | else { | ||
781 | res = r; | ||
782 | goto err; | ||
783 | } | ||
784 | } | ||
785 | |||
786 | if (no_preamble) { | ||
787 | #if 0 | ||
788 | preamble_end = cur_token; | ||
789 | #endif | ||
790 | } | ||
791 | else { | ||
792 | |||
793 | r = mailmime_lwsp_parse(message, length, &cur_token); | ||
794 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
795 | res = r; | ||
796 | goto err; | ||
797 | } | ||
798 | |||
799 | before_crlf = cur_token; | ||
800 | r = mailimf_crlf_parse(message, length, &cur_token); | ||
801 | if (r == MAILIMF_NO_ERROR) { | ||
802 | #if 0 | ||
803 | preamble_end = before_crlf; | ||
804 | #endif | ||
805 | /* remove the CR LF at the end of preamble if any */ | ||
806 | } | ||
807 | else if (r == MAILIMF_ERROR_PARSE) { | ||
808 | /* do nothing */ | ||
809 | } | ||
810 | else { | ||
811 | res = r; | ||
812 | goto err; | ||
813 | } | ||
814 | } | ||
815 | preamble_length = preamble_end - begin; | ||
816 | #endif | ||
817 | |||
818 | r = mailmime_preamble_parse(message, length, &cur_token, 1); | ||
819 | if (r == MAILIMF_NO_ERROR) { | ||
820 | while (1) { | ||
821 | |||
822 | preamble_end = cur_token; | ||
823 | r = mailmime_boundary_parse(message, length, &cur_token, boundary); | ||
824 | if (r == MAILIMF_NO_ERROR) { | ||
825 | break; | ||
826 | } | ||
827 | else if (r == MAILIMF_ERROR_PARSE) { | ||
828 | /* do nothing */ | ||
829 | } | ||
830 | else { | ||
831 | res = r; | ||
832 | goto err; | ||
833 | } | ||
834 | |||
835 | r = mailmime_preamble_parse(message, length, &cur_token, 0); | ||
836 | if (r == MAILIMF_NO_ERROR) { | ||
837 | } | ||
838 | else if (r == MAILIMF_ERROR_PARSE) { | ||
839 | break; | ||
840 | } | ||
841 | else { | ||
842 | res = r; | ||
843 | goto err; | ||
844 | } | ||
845 | } | ||
846 | } | ||
847 | |||
848 | preamble_end -= 2; | ||
849 | if (preamble_end != preamble_begin) { | ||
850 | /* try to find the real end of the preamble (strip CR LF) */ | ||
851 | if (message[preamble_end - 1] == '\n') { | ||
852 | preamble_end --; | ||
853 | if (preamble_end - 1 >= preamble_begin) { | ||
854 | if (message[preamble_end - 1] == '\r') | ||
855 | preamble_end --; | ||
856 | } | ||
857 | } | ||
858 | else if (message[preamble_end - 1] == '\r') { | ||
859 | preamble_end --; | ||
860 | } | ||
861 | } | ||
862 | preamble_length = preamble_end - preamble_begin; | ||
863 | |||
864 | part_begin = cur_token; | ||
865 | while (1) { | ||
866 | r = mailmime_lwsp_parse(message, length, &cur_token); | ||
867 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
868 | res = r; | ||
869 | goto err; | ||
870 | } | ||
871 | #if 0 | ||
872 | if (r == MAILIMF_ERROR_PARSE) | ||
873 | break; | ||
874 | #endif | ||
875 | |||
876 | r = mailimf_crlf_parse(message, length, &cur_token); | ||
877 | if (r == MAILIMF_NO_ERROR) { | ||
878 | part_begin = cur_token; | ||
879 | } | ||
880 | else if (r == MAILIMF_ERROR_PARSE) { | ||
881 | /* do nothing */ | ||
882 | break; | ||
883 | } | ||
884 | else { | ||
885 | res = r; | ||
886 | goto err; | ||
887 | } | ||
888 | } | ||
889 | |||
890 | cur_token = part_begin; | ||
891 | |||
892 | list = clist_new(); | ||
893 | if (list == NULL) { | ||
894 | res = MAILIMF_ERROR_MEMORY; | ||
895 | goto err; | ||
896 | } | ||
897 | |||
898 | while (1) { | ||
899 | size_t bp_token; | ||
900 | struct mailmime * mime_bp; | ||
901 | const char * data_str; | ||
902 | size_t data_size; | ||
903 | struct mailimf_fields * fields; | ||
904 | struct mailmime_fields * mime_fields; | ||
905 | |||
906 | r = mailmime_body_part_dash2_parse(message, length, &cur_token, | ||
907 | boundary, &data_str, &data_size); | ||
908 | if (r == MAILIMF_NO_ERROR) { | ||
909 | /* do nothing */ | ||
910 | } | ||
911 | else if (r == MAILIMF_ERROR_PARSE) { | ||
912 | break; | ||
913 | } | ||
914 | else { | ||
915 | res = r; | ||
916 | goto free; | ||
917 | } | ||
918 | |||
919 | bp_token = 0; | ||
920 | |||
921 | |||
922 | r = mailimf_optional_fields_parse(data_str, data_size, | ||
923 | &bp_token, &fields); | ||
924 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
925 | res = r; | ||
926 | goto free; | ||
927 | } | ||
928 | |||
929 | r = mailimf_crlf_parse(data_str, data_size, &bp_token); | ||
930 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
931 | mailimf_fields_free(fields); | ||
932 | res = r; | ||
933 | goto free; | ||
934 | } | ||
935 | |||
936 | mime_fields = NULL; | ||
937 | r = mailmime_fields_parse(fields, &mime_fields); | ||
938 | mailimf_fields_free(fields); | ||
939 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
940 | res = r; | ||
941 | goto free; | ||
942 | } | ||
943 | |||
944 | r = mailmime_parse_with_default(data_str, data_size, | ||
945 | &bp_token, default_subtype, NULL, | ||
946 | mime_fields, &mime_bp); | ||
947 | if (r == MAILIMF_NO_ERROR) { | ||
948 | r = clist_append(list, mime_bp); | ||
949 | if (r < 0) { | ||
950 | mailmime_free(mime_bp); | ||
951 | res = MAILIMF_ERROR_MEMORY; | ||
952 | goto free; | ||
953 | } | ||
954 | } | ||
955 | else if (r == MAILIMF_ERROR_PARSE) { | ||
956 | mailmime_fields_free(mime_fields); | ||
957 | break; | ||
958 | } | ||
959 | else { | ||
960 | mailmime_fields_free(mime_fields); | ||
961 | res = r; | ||
962 | goto free; | ||
963 | } | ||
964 | |||
965 | r = mailmime_multipart_next_parse(message, length, &cur_token); | ||
966 | if (r == MAILIMF_NO_ERROR) { | ||
967 | /* do nothing */ | ||
968 | } | ||
969 | else if (r == MAILIMF_ERROR_PARSE) { | ||
970 | r = mailmime_multipart_close_parse(message, length, &cur_token); | ||
971 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
972 | res = r; | ||
973 | goto free; | ||
974 | } | ||
975 | break; | ||
976 | } | ||
977 | else { | ||
978 | res = r; | ||
979 | goto free; | ||
980 | } | ||
981 | } | ||
982 | |||
983 | epilogue_begin = length; | ||
984 | /* parse transport-padding */ | ||
985 | while (1) { | ||
986 | r = mailmime_lwsp_parse(message, length, &cur_token); | ||
987 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
988 | res = r; | ||
989 | goto free; | ||
990 | } | ||
991 | #if 0 | ||
992 | if (r == MAILIMF_ERROR_PARSE) | ||
993 | break; | ||
994 | #endif | ||
995 | |||
996 | #if 0 | ||
997 | before_crlf = cur_token; | ||
998 | #endif | ||
999 | r = mailimf_crlf_parse(message, length, &cur_token); | ||
1000 | if (r == MAILIMF_NO_ERROR) { | ||
1001 | epilogue_begin = cur_token; | ||
1002 | break; | ||
1003 | } | ||
1004 | else if (r == MAILIMF_ERROR_PARSE) { | ||
1005 | /* do nothing */ | ||
1006 | break; | ||
1007 | } | ||
1008 | else { | ||
1009 | res = r; | ||
1010 | goto free; | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | /* add preamble and epilogue */ | ||
1015 | |||
1016 | epilogue_length = length - epilogue_begin; | ||
1017 | |||
1018 | if (preamble_length != 0) { | ||
1019 | preamble = mailmime_data_new(MAILMIME_DATA_TEXT, | ||
1020 | MAILMIME_MECHANISM_8BIT, 1, | ||
1021 | message + preamble_begin, preamble_length, | ||
1022 | NULL); | ||
1023 | if (preamble == NULL) { | ||
1024 | res = MAILIMF_ERROR_MEMORY; | ||
1025 | goto free; | ||
1026 | } | ||
1027 | } | ||
1028 | |||
1029 | if (epilogue_length != 0) { | ||
1030 | epilogue = mailmime_data_new(MAILMIME_DATA_TEXT, | ||
1031 | MAILMIME_MECHANISM_8BIT, 1, | ||
1032 | message + epilogue_begin, epilogue_length, | ||
1033 | NULL); | ||
1034 | if (epilogue == NULL) { | ||
1035 | res = MAILIMF_ERROR_MEMORY; | ||
1036 | goto free; | ||
1037 | } | ||
1038 | } | ||
1039 | |||
1040 | /* end of preamble and epilogue */ | ||
1041 | |||
1042 | cur_token = length; | ||
1043 | |||
1044 | * result = list; | ||
1045 | * p_preamble = preamble; | ||
1046 | * p_epilogue = epilogue; | ||
1047 | * index = cur_token; | ||
1048 | |||
1049 | return MAILIMF_NO_ERROR; | ||
1050 | |||
1051 | free: | ||
1052 | if (epilogue != NULL) | ||
1053 | mailmime_data_free(epilogue); | ||
1054 | if (preamble != NULL) | ||
1055 | mailmime_data_free(preamble); | ||
1056 | clist_foreach(list, (clist_func) mailmime_free, NULL); | ||
1057 | clist_free(list); | ||
1058 | err: | ||
1059 | return res; | ||
1060 | } | ||
1061 | |||
1062 | enum { | ||
1063 | MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, | ||
1064 | MAILMIME_DEFAULT_TYPE_MESSAGE | ||
1065 | }; | ||
1066 | |||
1067 | |||
1068 | int mailmime_parse(const char * message, size_t length, | ||
1069 | size_t * index, struct mailmime ** result) | ||
1070 | { | ||
1071 | struct mailmime * mime; | ||
1072 | int r; | ||
1073 | int res; | ||
1074 | struct mailmime_content * content_message; | ||
1075 | size_t cur_token; | ||
1076 | struct mailmime_fields * mime_fields; | ||
1077 | const char * data_str; | ||
1078 | size_t data_size; | ||
1079 | size_t bp_token; | ||
1080 | |||
1081 | cur_token = * index; | ||
1082 | |||
1083 | content_message = mailmime_get_content_message(); | ||
1084 | if (content_message == NULL) { | ||
1085 | res = MAILIMF_ERROR_MEMORY; | ||
1086 | goto err; | ||
1087 | } | ||
1088 | |||
1089 | #if 0 | ||
1090 | mime_fields = mailmime_fields_new_with_data(content_message, | ||
1091 | NULL, | ||
1092 | NULL, | ||
1093 | NULL, | ||
1094 | NULL, | ||
1095 | NULL); | ||
1096 | if (mime_fields == NULL) { | ||
1097 | mailmime_content_free(content_message); | ||
1098 | res = MAILIMF_ERROR_MEMORY; | ||
1099 | goto err; | ||
1100 | } | ||
1101 | #endif | ||
1102 | mime_fields = mailmime_fields_new_empty(); | ||
1103 | if (mime_fields == NULL) { | ||
1104 | mailmime_content_free(content_message); | ||
1105 | res = MAILIMF_ERROR_MEMORY; | ||
1106 | goto err; | ||
1107 | } | ||
1108 | |||
1109 | data_str = message + cur_token; | ||
1110 | data_size = length - cur_token; | ||
1111 | |||
1112 | bp_token = 0; | ||
1113 | r = mailmime_parse_with_default(data_str, data_size, | ||
1114 | &bp_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, | ||
1115 | content_message, mime_fields, &mime); | ||
1116 | cur_token += bp_token; | ||
1117 | if (r != MAILIMF_NO_ERROR) { | ||
1118 | mailmime_fields_free(mime_fields); | ||
1119 | res = r; | ||
1120 | goto free; | ||
1121 | } | ||
1122 | |||
1123 | * index = cur_token; | ||
1124 | * result = mime; | ||
1125 | |||
1126 | return MAILIMF_NO_ERROR; | ||
1127 | |||
1128 | free: | ||
1129 | mailmime_fields_free(mime_fields); | ||
1130 | err: | ||
1131 | return res; | ||
1132 | } | ||
1133 | |||
1134 | |||
1135 | char * mailmime_extract_boundary(struct mailmime_content * content_type) | ||
1136 | { | ||
1137 | char * boundary; | ||
1138 | |||
1139 | boundary = mailmime_content_param_get(content_type, "boundary"); | ||
1140 | |||
1141 | if (boundary != NULL) { | ||
1142 | int len; | ||
1143 | char * new_boundary; | ||
1144 | |||
1145 | len = strlen(boundary); | ||
1146 | new_boundary = malloc(len + 1); | ||
1147 | if (new_boundary == NULL) | ||
1148 | return NULL; | ||
1149 | |||
1150 | if (boundary[0] == '"') { | ||
1151 | strncpy(new_boundary, boundary + 1, len - 2); | ||
1152 | new_boundary[len - 2] = 0; | ||
1153 | } | ||
1154 | else | ||
1155 | strcpy(new_boundary, boundary); | ||
1156 | |||
1157 | boundary = new_boundary; | ||
1158 | } | ||
1159 | |||
1160 | return boundary; | ||
1161 | } | ||
1162 | |||
1163 | static void remove_unparsed_mime_headers(struct mailimf_fields * fields) | ||
1164 | { | ||
1165 | clistiter * cur; | ||
1166 | |||
1167 | cur = clist_begin(fields->fld_list); | ||
1168 | while (cur != NULL) { | ||
1169 | struct mailimf_field * field; | ||
1170 | int delete; | ||
1171 | |||
1172 | field = clist_content(cur); | ||
1173 | |||
1174 | switch (field->fld_type) { | ||
1175 | case MAILIMF_FIELD_OPTIONAL_FIELD: | ||
1176 | delete = 0; | ||
1177 | if (strncasecmp(field->fld_data.fld_optional_field->fld_name, | ||
1178 | "Content-", 8) == 0) { | ||
1179 | char * name; | ||
1180 | |||
1181 | name = field->fld_data.fld_optional_field->fld_name + 8; | ||
1182 | if ((strcasecmp(name, "Type") == 0) | ||
1183 | || (strcasecmp(name, "Transfer-Encoding") == 0) | ||
1184 | || (strcasecmp(name, "ID") == 0) | ||
1185 | || (strcasecmp(name, "Description") == 0) | ||
1186 | || (strcasecmp(name, "Disposition") == 0) | ||
1187 | || (strcasecmp(name, "Language") == 0)) { | ||
1188 | delete = 1; | ||
1189 | } | ||
1190 | } | ||
1191 | else if (strcasecmp(field->fld_data.fld_optional_field->fld_name, | ||
1192 | "MIME-Version") == 0) { | ||
1193 | delete = 1; | ||
1194 | } | ||
1195 | |||
1196 | if (delete) { | ||
1197 | cur = clist_delete(fields->fld_list, cur); | ||
1198 | mailimf_field_free(field); | ||
1199 | } | ||
1200 | else { | ||
1201 | cur = clist_next(cur); | ||
1202 | } | ||
1203 | break; | ||
1204 | |||
1205 | default: | ||
1206 | cur = clist_next(cur); | ||
1207 | } | ||
1208 | } | ||
1209 | } | ||
1210 | |||
1211 | static int mailmime_parse_with_default(const char * message, size_t length, | ||
1212 | size_t * index, int default_type, | ||
1213 | struct mailmime_content * content_type, | ||
1214 | struct mailmime_fields * mime_fields, | ||
1215 | struct mailmime ** result) | ||
1216 | { | ||
1217 | size_t cur_token; | ||
1218 | |||
1219 | int body_type; | ||
1220 | |||
1221 | int encoding; | ||
1222 | struct mailmime_data * body; | ||
1223 | char * boundary; | ||
1224 | struct mailimf_fields * fields; | ||
1225 | clist * list; | ||
1226 | struct mailmime * msg_mime; | ||
1227 | |||
1228 | struct mailmime * mime; | ||
1229 | |||
1230 | int r; | ||
1231 | int res; | ||
1232 | struct mailmime_data * preamble; | ||
1233 | struct mailmime_data * epilogue; | ||
1234 | |||
1235 | /* | ||
1236 | note that when this function is called, content type is always detached, | ||
1237 | even if the function fails | ||
1238 | */ | ||
1239 | |||
1240 | preamble = NULL; | ||
1241 | epilogue = NULL; | ||
1242 | |||
1243 | cur_token = * index; | ||
1244 | |||
1245 | /* get content type */ | ||
1246 | |||
1247 | if (content_type == NULL) { | ||
1248 | if (mime_fields != NULL) { | ||
1249 | clistiter * cur; | ||
1250 | |||
1251 | for(cur = clist_begin(mime_fields->fld_list) ; cur != NULL ; | ||
1252 | cur = clist_next(cur)) { | ||
1253 | struct mailmime_field * field; | ||
1254 | |||
1255 | field = clist_content(cur); | ||
1256 | if (field->fld_type == MAILMIME_FIELD_TYPE) { | ||
1257 | content_type = field->fld_data.fld_content; | ||
1258 | |||
1259 | /* detach content type from list */ | ||
1260 | field->fld_data.fld_content = NULL; | ||
1261 | clist_delete(mime_fields->fld_list, cur); | ||
1262 | mailmime_field_free(field); | ||
1263 | /* | ||
1264 | there may be a leak due to the detached content type | ||
1265 | in case the function fails | ||
1266 | */ | ||
1267 | break; | ||
1268 | } | ||
1269 | } | ||
1270 | } | ||
1271 | } | ||
1272 | |||
1273 | /* set default type if no content type */ | ||
1274 | |||
1275 | if (content_type == NULL) { | ||
1276 | /* content_type is detached, in any case, we will have to free it */ | ||
1277 | if (default_type == MAILMIME_DEFAULT_TYPE_TEXT_PLAIN) { | ||
1278 | content_type = mailmime_get_content_text(); | ||
1279 | if (content_type == NULL) { | ||
1280 | res = MAILIMF_ERROR_MEMORY; | ||
1281 | goto err; | ||
1282 | } | ||
1283 | } | ||
1284 | else /* message */ { | ||
1285 | body_type = MAILMIME_MESSAGE; | ||
1286 | |||
1287 | content_type = mailmime_get_content_message(); | ||
1288 | if (content_type == NULL) { | ||
1289 | res = MAILIMF_ERROR_MEMORY; | ||
1290 | goto err; | ||
1291 | } | ||
1292 | } | ||
1293 | } | ||
1294 | |||
1295 | /* get the body type */ | ||
1296 | |||
1297 | boundary = NULL; /* XXX - removes a gcc warning */ | ||
1298 | |||
1299 | switch (content_type->ct_type->tp_type) { | ||
1300 | case MAILMIME_TYPE_COMPOSITE_TYPE: | ||
1301 | switch (content_type->ct_type->tp_data.tp_composite_type->ct_type) { | ||
1302 | case MAILMIME_COMPOSITE_TYPE_MULTIPART: | ||
1303 | boundary = mailmime_extract_boundary(content_type); | ||
1304 | |||
1305 | if (boundary == NULL) | ||
1306 | body_type = MAILMIME_SINGLE; | ||
1307 | else | ||
1308 | body_type = MAILMIME_MULTIPLE; | ||
1309 | break; | ||
1310 | |||
1311 | case MAILMIME_COMPOSITE_TYPE_MESSAGE: | ||
1312 | |||
1313 | if (strcasecmp(content_type->ct_subtype, "rfc822") == 0) | ||
1314 | body_type = MAILMIME_MESSAGE; | ||
1315 | else | ||
1316 | body_type = MAILMIME_SINGLE; | ||
1317 | break; | ||
1318 | |||
1319 | default: | ||
1320 | res = MAILIMF_ERROR_INVAL; | ||
1321 | goto free_content; | ||
1322 | } | ||
1323 | break; | ||
1324 | |||
1325 | default: /* MAILMIME_TYPE_DISCRETE_TYPE */ | ||
1326 | body_type = MAILMIME_SINGLE; | ||
1327 | break; | ||
1328 | } | ||
1329 | |||
1330 | /* set body */ | ||
1331 | |||
1332 | if (mime_fields != NULL) | ||
1333 | encoding = mailmime_transfer_encoding_get(mime_fields); | ||
1334 | else | ||
1335 | encoding = MAILMIME_MECHANISM_8BIT; | ||
1336 | |||
1337 | cur_token = * index; | ||
1338 | body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1, | ||
1339 | message + cur_token, length - cur_token, | ||
1340 | NULL); | ||
1341 | if (body == NULL) { | ||
1342 | res = MAILIMF_ERROR_MEMORY; | ||
1343 | goto free_content; | ||
1344 | } | ||
1345 | |||
1346 | /* in case of composite, parse the sub-part(s) */ | ||
1347 | |||
1348 | list = NULL; | ||
1349 | msg_mime = NULL; | ||
1350 | fields = NULL; | ||
1351 | |||
1352 | switch (body_type) { | ||
1353 | case MAILMIME_MESSAGE: | ||
1354 | { | ||
1355 | struct mailmime_fields * submime_fields; | ||
1356 | |||
1357 | r = mailimf_envelope_and_optional_fields_parse(message, length, | ||
1358 | &cur_token, &fields); | ||
1359 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
1360 | res = r; | ||
1361 | goto free_content; | ||
1362 | } | ||
1363 | |||
1364 | r = mailimf_crlf_parse(message, length, &cur_token); | ||
1365 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
1366 | mailimf_fields_free(fields); | ||
1367 | res = r; | ||
1368 | goto free_content; | ||
1369 | } | ||
1370 | |||
1371 | submime_fields = NULL; | ||
1372 | r = mailmime_fields_parse(fields, &submime_fields); | ||
1373 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
1374 | mailimf_fields_free(fields); | ||
1375 | res = r; | ||
1376 | goto free_content; | ||
1377 | } | ||
1378 | |||
1379 | remove_unparsed_mime_headers(fields); | ||
1380 | |||
1381 | r = mailmime_parse_with_default(message, length, | ||
1382 | &cur_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN, | ||
1383 | NULL, submime_fields, &msg_mime); | ||
1384 | if (r == MAILIMF_NO_ERROR) { | ||
1385 | /* do nothing */ | ||
1386 | } | ||
1387 | else if (r == MAILIMF_ERROR_PARSE) { | ||
1388 | mailmime_fields_free(mime_fields); | ||
1389 | msg_mime = NULL; | ||
1390 | } | ||
1391 | else { | ||
1392 | mailmime_fields_free(mime_fields); | ||
1393 | res = r; | ||
1394 | goto free_content; | ||
1395 | } | ||
1396 | } | ||
1397 | |||
1398 | break; | ||
1399 | |||
1400 | case MAILMIME_MULTIPLE: | ||
1401 | { | ||
1402 | int default_subtype; | ||
1403 | |||
1404 | default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN; | ||
1405 | if (content_type != NULL) | ||
1406 | if (strcasecmp(content_type->ct_subtype, "digest") == 0) | ||
1407 | default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE; | ||
1408 | |||
1409 | cur_token = * index; | ||
1410 | r = mailmime_multipart_body_parse(message, length, | ||
1411 | &cur_token, boundary, | ||
1412 | default_subtype, | ||
1413 | &list, &preamble, &epilogue); | ||
1414 | if (r == MAILIMF_NO_ERROR) { | ||
1415 | /* do nothing */ | ||
1416 | } | ||
1417 | else if (r == MAILIMF_ERROR_PARSE) { | ||
1418 | list = clist_new(); | ||
1419 | if (list == NULL) { | ||
1420 | res = MAILIMF_ERROR_MEMORY; | ||
1421 | goto free_content; | ||
1422 | } | ||
1423 | } | ||
1424 | else { | ||
1425 | res = r; | ||
1426 | goto free_content; | ||
1427 | } | ||
1428 | |||
1429 | free(boundary); | ||
1430 | } | ||
1431 | break; | ||
1432 | |||
1433 | default: /* MAILMIME_SINGLE */ | ||
1434 | /* do nothing */ | ||
1435 | break; | ||
1436 | } | ||
1437 | |||
1438 | mime = mailmime_new(body_type, message, length, | ||
1439 | mime_fields, content_type, | ||
1440 | body, preamble, /* preamble */ | ||
1441 | epilogue, /* epilogue */ | ||
1442 | list, fields, msg_mime); | ||
1443 | if (mime == NULL) { | ||
1444 | res = MAILIMF_ERROR_MEMORY; | ||
1445 | goto free; | ||
1446 | } | ||
1447 | |||
1448 | * result = mime; | ||
1449 | * index = length; | ||
1450 | |||
1451 | return MAILIMF_NO_ERROR; | ||
1452 | |||
1453 | free: | ||
1454 | if (epilogue != NULL) | ||
1455 | mailmime_data_free(epilogue); | ||
1456 | if (preamble != NULL) | ||
1457 | mailmime_data_free(preamble); | ||
1458 | if (msg_mime != NULL) | ||
1459 | mailmime_free(msg_mime); | ||
1460 | if (list != NULL) { | ||
1461 | clist_foreach(list, (clist_func) mailmime_free, NULL); | ||
1462 | clist_free(list); | ||
1463 | } | ||
1464 | free_content: | ||
1465 | mailmime_content_free(content_type); | ||
1466 | err: | ||
1467 | return res; | ||
1468 | } | ||
1469 | |||
1470 | static int mailmime_get_section_list(struct mailmime * mime, | ||
1471 | clistiter * list, struct mailmime ** result) | ||
1472 | { | ||
1473 | uint32_t id; | ||
1474 | struct mailmime * data; | ||
1475 | struct mailmime * submime; | ||
1476 | |||
1477 | if (list == NULL) { | ||
1478 | * result = mime; | ||
1479 | return MAILIMF_NO_ERROR; | ||
1480 | } | ||
1481 | |||
1482 | id = * ((uint32_t *) clist_content(list)); | ||
1483 | |||
1484 | data = NULL; | ||
1485 | switch (mime->mm_type) { | ||
1486 | case MAILMIME_SINGLE: | ||
1487 | return MAILIMF_ERROR_INVAL; | ||
1488 | |||
1489 | case MAILMIME_MULTIPLE: | ||
1490 | data = clist_nth_data(mime->mm_data.mm_multipart.mm_mp_list, id - 1); | ||
1491 | if (data == NULL) | ||
1492 | return MAILIMF_ERROR_INVAL; | ||
1493 | |||
1494 | if (clist_next(list) != NULL) | ||
1495 | return mailmime_get_section_list(data, clist_next(list), result); | ||
1496 | else { | ||
1497 | * result = data; | ||
1498 | return MAILIMF_NO_ERROR; | ||
1499 | } | ||
1500 | |||
1501 | case MAILMIME_MESSAGE: | ||
1502 | submime = mime->mm_data.mm_message.mm_msg_mime; | ||
1503 | switch (submime->mm_type) { | ||
1504 | case MAILMIME_MULTIPLE: | ||
1505 | data = clist_nth_data(submime->mm_data.mm_multipart.mm_mp_list, id - 1); | ||
1506 | if (data == NULL) | ||
1507 | return MAILIMF_ERROR_INVAL; | ||
1508 | return mailmime_get_section_list(data, clist_next(list), result); | ||
1509 | |||
1510 | default: | ||
1511 | if (id != 1) | ||
1512 | return MAILIMF_ERROR_INVAL; | ||
1513 | |||
1514 | data = submime; | ||
1515 | if (data == NULL) | ||
1516 | return MAILIMF_ERROR_INVAL; | ||
1517 | |||
1518 | return mailmime_get_section_list(data, clist_next(list), result); | ||
1519 | } | ||
1520 | break; | ||
1521 | |||
1522 | default: | ||
1523 | return MAILIMF_ERROR_INVAL; | ||
1524 | } | ||
1525 | } | ||
1526 | |||
1527 | int mailmime_get_section(struct mailmime * mime, | ||
1528 | struct mailmime_section * section, | ||
1529 | struct mailmime ** result) | ||
1530 | { | ||
1531 | return mailmime_get_section_list(mime, | ||
1532 | clist_begin(section->sec_list), result); | ||
1533 | } | ||
1534 | |||
1535 | |||
1536 | |||
1537 | |||
1538 | |||
1539 | |||
1540 | |||
1541 | |||
1542 | |||
1543 | |||
1544 | |||
1545 | |||
1546 | |||
1547 | |||
1548 | |||
1549 | /* ************************************************************************* */ | ||
1550 | /* MIME part decoding */ | ||
1551 | |||
1552 | static inline signed char get_base64_value(char ch) | ||
1553 | { | ||
1554 | if ((ch >= 'A') && (ch <= 'Z')) | ||
1555 | return ch - 'A'; | ||
1556 | if ((ch >= 'a') && (ch <= 'z')) | ||
1557 | return ch - 'a' + 26; | ||
1558 | if ((ch >= '0') && (ch <= '9')) | ||
1559 | return ch - '0' + 52; | ||
1560 | switch (ch) { | ||
1561 | case '+': | ||
1562 | return 62; | ||
1563 | case '/': | ||
1564 | return 63; | ||
1565 | case '=': /* base64 padding */ | ||
1566 | return -1; | ||
1567 | default: | ||
1568 | return -1; | ||
1569 | } | ||
1570 | } | ||
1571 | |||
1572 | int mailmime_base64_body_parse(const char * message, size_t length, | ||
1573 | size_t * index, char ** result, | ||
1574 | size_t * result_len) | ||
1575 | { | ||
1576 | size_t cur_token; | ||
1577 | size_t i; | ||
1578 | char chunk[4]; | ||
1579 | int chunk_index; | ||
1580 | char out[3]; | ||
1581 | MMAPString * mmapstr; | ||
1582 | int res; | ||
1583 | int r; | ||
1584 | size_t written; | ||
1585 | |||
1586 | cur_token = * index; | ||
1587 | chunk_index = 0; | ||
1588 | written = 0; | ||
1589 | |||
1590 | mmapstr = mmap_string_sized_new((length - cur_token) * 3 / 4); | ||
1591 | if (mmapstr == NULL) { | ||
1592 | res = MAILIMF_ERROR_MEMORY; | ||
1593 | goto err; | ||
1594 | } | ||
1595 | |||
1596 | i = 0; | ||
1597 | while (1) { | ||
1598 | signed char value; | ||
1599 | |||
1600 | value = -1; | ||
1601 | while (value == -1) { | ||
1602 | |||
1603 | if (cur_token >= length) | ||
1604 | break; | ||
1605 | |||
1606 | value = get_base64_value(message[cur_token]); | ||
1607 | cur_token ++; | ||
1608 | } | ||
1609 | |||
1610 | if (value == -1) | ||
1611 | break; | ||
1612 | |||
1613 | chunk[chunk_index] = value; | ||
1614 | chunk_index ++; | ||
1615 | |||
1616 | if (chunk_index == 4) { | ||
1617 | out[0] = (chunk[0] << 2) | (chunk[1] >> 4); | ||
1618 | out[1] = (chunk[1] << 4) | (chunk[2] >> 2); | ||
1619 | out[2] = (chunk[2] << 6) | (chunk[3]); | ||
1620 | |||
1621 | chunk[0] = 0; | ||
1622 | chunk[1] = 0; | ||
1623 | chunk[2] = 0; | ||
1624 | chunk[3] = 0; | ||
1625 | |||
1626 | chunk_index = 0; | ||
1627 | |||
1628 | if (mmap_string_append_len(mmapstr, out, 3) == NULL) { | ||
1629 | res = MAILIMF_ERROR_MEMORY; | ||
1630 | goto free; | ||
1631 | } | ||
1632 | written += 3; | ||
1633 | } | ||
1634 | } | ||
1635 | |||
1636 | if (chunk_index != 0) { | ||
1637 | size_t len; | ||
1638 | |||
1639 | len = 0; | ||
1640 | out[0] = (chunk[0] << 2) | (chunk[1] >> 4); | ||
1641 | len ++; | ||
1642 | |||
1643 | if (chunk_index >= 3) { | ||
1644 | out[1] = (chunk[1] << 4) | (chunk[2] >> 2); | ||
1645 | len ++; | ||
1646 | } | ||
1647 | |||
1648 | if (mmap_string_append_len(mmapstr, out, len) == NULL) { | ||
1649 | res = MAILIMF_ERROR_MEMORY; | ||
1650 | goto free; | ||
1651 | } | ||
1652 | written += len; | ||
1653 | } | ||
1654 | |||
1655 | r = mmap_string_ref(mmapstr); | ||
1656 | if (r < 0) { | ||
1657 | res = MAILIMF_ERROR_MEMORY; | ||
1658 | goto free; | ||
1659 | } | ||
1660 | |||
1661 | * index = cur_token; | ||
1662 | * result = mmapstr->str; | ||
1663 | * result_len = written; | ||
1664 | |||
1665 | return MAILIMF_NO_ERROR; | ||
1666 | |||
1667 | free: | ||
1668 | mmap_string_free(mmapstr); | ||
1669 | err: | ||
1670 | return res; | ||
1671 | } | ||
1672 | |||
1673 | |||
1674 | |||
1675 | static inline int hexa_to_char(char hexdigit) | ||
1676 | { | ||
1677 | if ((hexdigit >= '0') && (hexdigit <= '9')) | ||
1678 | return hexdigit - '0'; | ||
1679 | if ((hexdigit >= 'a') && (hexdigit <= 'f')) | ||
1680 | return hexdigit - 'a' + 10; | ||
1681 | if ((hexdigit >= 'A') && (hexdigit <= 'F')) | ||
1682 | return hexdigit - 'A' + 10; | ||
1683 | return 0; | ||
1684 | } | ||
1685 | |||
1686 | static inline char to_char(const char * hexa) | ||
1687 | { | ||
1688 | return (hexa_to_char(hexa[0]) << 4) | hexa_to_char(hexa[1]); | ||
1689 | } | ||
1690 | |||
1691 | enum { | ||
1692 | STATE_NORMAL, | ||
1693 | STATE_CODED, | ||
1694 | STATE_OUT, | ||
1695 | STATE_CR, | ||
1696 | }; | ||
1697 | |||
1698 | |||
1699 | static int write_decoded_qp(MMAPString * mmapstr, | ||
1700 | const char * start, size_t count) | ||
1701 | { | ||
1702 | if (mmap_string_append_len(mmapstr, start, count) == NULL) | ||
1703 | return MAILIMF_ERROR_MEMORY; | ||
1704 | |||
1705 | return MAILIMF_NO_ERROR; | ||
1706 | } | ||
1707 | |||
1708 | |||
1709 | #define WRITE_MAX_QP 512 | ||
1710 | |||
1711 | int mailmime_quoted_printable_body_parse(const char * message, size_t length, | ||
1712 | size_t * index, char ** result, | ||
1713 | size_t * result_len, int in_header) | ||
1714 | { | ||
1715 | size_t cur_token; | ||
1716 | int state; | ||
1717 | int r; | ||
1718 | char ch; | ||
1719 | size_t count; | ||
1720 | const char * start; | ||
1721 | MMAPString * mmapstr; | ||
1722 | int res; | ||
1723 | size_t written; | ||
1724 | |||
1725 | state = STATE_NORMAL; | ||
1726 | cur_token = * index; | ||
1727 | |||
1728 | count = 0; | ||
1729 | start = message + cur_token; | ||
1730 | written = 0; | ||
1731 | |||
1732 | mmapstr = mmap_string_sized_new(length - cur_token); | ||
1733 | if (mmapstr == NULL) { | ||
1734 | res = MAILIMF_ERROR_MEMORY; | ||
1735 | goto err; | ||
1736 | } | ||
1737 | |||
1738 | #if 0 | ||
1739 | if (length >= 1) { | ||
1740 | if (message[length - 1] == '\n') { | ||
1741 | length --; | ||
1742 | if (length >= 1) | ||
1743 | if (message[length - 1] == '\r') { | ||
1744 | length --; | ||
1745 | } | ||
1746 | } | ||
1747 | } | ||
1748 | #endif | ||
1749 | |||
1750 | while (state != STATE_OUT) { | ||
1751 | |||
1752 | if (cur_token >= length) { | ||
1753 | state = STATE_OUT; | ||
1754 | break; | ||
1755 | } | ||
1756 | |||
1757 | switch (state) { | ||
1758 | |||
1759 | case STATE_CODED: | ||
1760 | |||
1761 | if (count > 0) { | ||
1762 | r = write_decoded_qp(mmapstr, start, count); | ||
1763 | if (r != MAILIMF_NO_ERROR) { | ||
1764 | res = r; | ||
1765 | goto free; | ||
1766 | } | ||
1767 | written += count; | ||
1768 | count = 0; | ||
1769 | } | ||
1770 | |||
1771 | switch (message[cur_token]) { | ||
1772 | case '=': | ||
1773 | if (cur_token + 1 >= length) { | ||
1774 | /* error but ignore it */ | ||
1775 | state = STATE_NORMAL; | ||
1776 | start = message + cur_token; | ||
1777 | cur_token ++; | ||
1778 | count ++; | ||
1779 | break; | ||
1780 | } | ||
1781 | |||
1782 | switch (message[cur_token + 1]) { | ||
1783 | |||
1784 | case '\n': | ||
1785 | cur_token += 2; | ||
1786 | |||
1787 | start = message + cur_token; | ||
1788 | |||
1789 | state = STATE_NORMAL; | ||
1790 | break; | ||
1791 | |||
1792 | case '\r': | ||
1793 | if (cur_token + 2 >= length) { | ||
1794 | state = STATE_OUT; | ||
1795 | break; | ||
1796 | } | ||
1797 | |||
1798 | if (message[cur_token + 2] == '\n') | ||
1799 | cur_token += 3; | ||
1800 | else | ||
1801 | cur_token += 2; | ||
1802 | |||
1803 | start = message + cur_token; | ||
1804 | |||
1805 | state = STATE_NORMAL; | ||
1806 | |||
1807 | break; | ||
1808 | |||
1809 | default: | ||
1810 | if (cur_token + 2 >= length) { | ||
1811 | /* error but ignore it */ | ||
1812 | cur_token ++; | ||
1813 | |||
1814 | start = message + cur_token; | ||
1815 | |||
1816 | count ++; | ||
1817 | state = STATE_NORMAL; | ||
1818 | break; | ||
1819 | } | ||
1820 | |||
1821 | #if 0 | ||
1822 | /* flush before writing additionnal information */ | ||
1823 | r = write_decoded_qp(mmapstr, start, count); | ||
1824 | if (r != MAILIMF_NO_ERROR) { | ||
1825 | res = r; | ||
1826 | goto free; | ||
1827 | } | ||
1828 | written += count; | ||
1829 | count = 0; | ||
1830 | #endif | ||
1831 | |||
1832 | ch = to_char(message + cur_token + 1); | ||
1833 | |||
1834 | if (mmap_string_append_c(mmapstr, ch) == NULL) { | ||
1835 | res = MAILIMF_ERROR_MEMORY; | ||
1836 | goto free; | ||
1837 | } | ||
1838 | |||
1839 | cur_token += 3; | ||
1840 | written ++; | ||
1841 | |||
1842 | start = message + cur_token; | ||
1843 | |||
1844 | state = STATE_NORMAL; | ||
1845 | break; | ||
1846 | } | ||
1847 | break; | ||
1848 | } | ||
1849 | break; /* end of STATE_ENCODED */ | ||
1850 | |||
1851 | case STATE_NORMAL: | ||
1852 | |||
1853 | switch (message[cur_token]) { | ||
1854 | |||
1855 | case '=': | ||
1856 | state = STATE_CODED; | ||
1857 | break; | ||
1858 | |||
1859 | case '\n': | ||
1860 | /* flush before writing additionnal information */ | ||
1861 | if (count > 0) { | ||
1862 | r = write_decoded_qp(mmapstr, start, count); | ||
1863 | if (r != MAILIMF_NO_ERROR) { | ||
1864 | res = r; | ||
1865 | goto free; | ||
1866 | } | ||
1867 | written += count; | ||
1868 | |||
1869 | count = 0; | ||
1870 | } | ||
1871 | |||
1872 | r = write_decoded_qp(mmapstr, "\r\n", 2); | ||
1873 | if (r != MAILIMF_NO_ERROR) { | ||
1874 | res = r; | ||
1875 | goto free; | ||
1876 | } | ||
1877 | written += 2; | ||
1878 | cur_token ++; | ||
1879 | start = message + cur_token; | ||
1880 | break; | ||
1881 | |||
1882 | case '\r': | ||
1883 | state = STATE_CR; | ||
1884 | cur_token ++; | ||
1885 | break; | ||
1886 | |||
1887 | case '_': | ||
1888 | if (in_header) { | ||
1889 | if (count > 0) { | ||
1890 | r = write_decoded_qp(mmapstr, start, count); | ||
1891 | if (r != MAILIMF_NO_ERROR) { | ||
1892 | res = r; | ||
1893 | goto free; | ||
1894 | } | ||
1895 | written += count; | ||
1896 | count = 0; | ||
1897 | } | ||
1898 | |||
1899 | if (mmap_string_append_c(mmapstr, ' ') == NULL) { | ||
1900 | res = MAILIMF_ERROR_MEMORY; | ||
1901 | goto free; | ||
1902 | } | ||
1903 | |||
1904 | written ++; | ||
1905 | cur_token ++; | ||
1906 | start = message + cur_token; | ||
1907 | |||
1908 | break; | ||
1909 | } | ||
1910 | /* WARINING : must be followed by switch default action */ | ||
1911 | |||
1912 | default: | ||
1913 | if (count >= WRITE_MAX_QP) { | ||
1914 | r = write_decoded_qp(mmapstr, start, count); | ||
1915 | if (r != MAILIMF_NO_ERROR) { | ||
1916 | res = r; | ||
1917 | goto free; | ||
1918 | } | ||
1919 | written += count; | ||
1920 | count = 0; | ||
1921 | start = message + cur_token; | ||
1922 | } | ||
1923 | |||
1924 | count ++; | ||
1925 | cur_token ++; | ||
1926 | break; | ||
1927 | } | ||
1928 | break; /* end of STATE_NORMAL */ | ||
1929 | |||
1930 | case STATE_CR: | ||
1931 | switch (message[cur_token]) { | ||
1932 | |||
1933 | case '\n': | ||
1934 | /* flush before writing additionnal information */ | ||
1935 | if (count > 0) { | ||
1936 | r = write_decoded_qp(mmapstr, start, count); | ||
1937 | if (r != MAILIMF_NO_ERROR) { | ||
1938 | res = r; | ||
1939 | goto free; | ||
1940 | } | ||
1941 | written += count; | ||
1942 | count = 0; | ||
1943 | } | ||
1944 | |||
1945 | r = write_decoded_qp(mmapstr, "\r\n", 2); | ||
1946 | if (r != MAILIMF_NO_ERROR) { | ||
1947 | res = r; | ||
1948 | goto free; | ||
1949 | } | ||
1950 | written += 2; | ||
1951 | cur_token ++; | ||
1952 | start = message + cur_token; | ||
1953 | state = STATE_NORMAL; | ||
1954 | break; | ||
1955 | |||
1956 | default: | ||
1957 | /* flush before writing additionnal information */ | ||
1958 | if (count > 0) { | ||
1959 | r = write_decoded_qp(mmapstr, start, count); | ||
1960 | if (r != MAILIMF_NO_ERROR) { | ||
1961 | res = r; | ||
1962 | goto free; | ||
1963 | } | ||
1964 | written += count; | ||
1965 | count = 0; | ||
1966 | } | ||
1967 | |||
1968 | start = message + cur_token; | ||
1969 | |||
1970 | r = write_decoded_qp(mmapstr, "\r\n", 2); | ||
1971 | if (r != MAILIMF_NO_ERROR) { | ||
1972 | res = r; | ||
1973 | goto free; | ||
1974 | } | ||
1975 | written += 2; | ||
1976 | state = STATE_NORMAL; | ||
1977 | } | ||
1978 | break; /* end of STATE_CR */ | ||
1979 | } | ||
1980 | } | ||
1981 | |||
1982 | if (count > 0) { | ||
1983 | r = write_decoded_qp(mmapstr, start, count); | ||
1984 | if (r != MAILIMF_NO_ERROR) { | ||
1985 | res = r; | ||
1986 | goto free; | ||
1987 | } | ||
1988 | written += count; | ||
1989 | count = 0; | ||
1990 | } | ||
1991 | |||
1992 | r = mmap_string_ref(mmapstr); | ||
1993 | if (r < 0) { | ||
1994 | res = MAILIMF_ERROR_MEMORY; | ||
1995 | goto free; | ||
1996 | } | ||
1997 | |||
1998 | * index = cur_token; | ||
1999 | * result = mmapstr->str; | ||
2000 | * result_len = written; | ||
2001 | |||
2002 | return MAILIMF_NO_ERROR; | ||
2003 | |||
2004 | free: | ||
2005 | mmap_string_free(mmapstr); | ||
2006 | err: | ||
2007 | return res; | ||
2008 | } | ||
2009 | |||
2010 | int mailmime_binary_body_parse(const char * message, size_t length, | ||
2011 | size_t * index, char ** result, | ||
2012 | size_t * result_len) | ||
2013 | { | ||
2014 | MMAPString * mmapstr; | ||
2015 | size_t cur_token; | ||
2016 | int r; | ||
2017 | int res; | ||
2018 | |||
2019 | cur_token = * index; | ||
2020 | |||
2021 | if (length >= 1) { | ||
2022 | if (message[length - 1] == '\n') { | ||
2023 | length --; | ||
2024 | if (length >= 1) | ||
2025 | if (message[length - 1] == '\r') | ||
2026 | length --; | ||
2027 | } | ||
2028 | } | ||
2029 | |||
2030 | mmapstr = mmap_string_new_len(message + cur_token, length - cur_token); | ||
2031 | if (mmapstr == NULL) { | ||
2032 | res = MAILIMF_ERROR_MEMORY; | ||
2033 | goto err; | ||
2034 | } | ||
2035 | |||
2036 | r = mmap_string_ref(mmapstr); | ||
2037 | if (r < 0) { | ||
2038 | res = MAILIMF_ERROR_MEMORY; | ||
2039 | goto free; | ||
2040 | } | ||
2041 | |||
2042 | * index = length; | ||
2043 | * result = mmapstr->str; | ||
2044 | * result_len = length - cur_token; | ||
2045 | |||
2046 | return MAILIMF_NO_ERROR; | ||
2047 | |||
2048 | free: | ||
2049 | mmap_string_free(mmapstr); | ||
2050 | err: | ||
2051 | return res; | ||
2052 | } | ||
2053 | |||
2054 | |||
2055 | int mailmime_part_parse(const char * message, size_t length, | ||
2056 | size_t * index, | ||
2057 | int encoding, char ** result, size_t * result_len) | ||
2058 | { | ||
2059 | switch (encoding) { | ||
2060 | case MAILMIME_MECHANISM_BASE64: | ||
2061 | return mailmime_base64_body_parse(message, length, index, | ||
2062 | result, result_len); | ||
2063 | |||
2064 | case MAILMIME_MECHANISM_QUOTED_PRINTABLE: | ||
2065 | return mailmime_quoted_printable_body_parse(message, length, index, | ||
2066 | result, result_len, FALSE); | ||
2067 | |||
2068 | case MAILMIME_MECHANISM_7BIT: | ||
2069 | case MAILMIME_MECHANISM_8BIT: | ||
2070 | case MAILMIME_MECHANISM_BINARY: | ||
2071 | default: | ||
2072 | return mailmime_binary_body_parse(message, length, index, | ||
2073 | result, result_len); | ||
2074 | } | ||
2075 | } | ||
2076 | |||
2077 | int mailmime_get_section_id(struct mailmime * mime, | ||
2078 | struct mailmime_section ** result) | ||
2079 | { | ||
2080 | clist * list; | ||
2081 | int res; | ||
2082 | struct mailmime_section * section_id; | ||
2083 | int r; | ||
2084 | |||
2085 | if (mime->mm_parent == NULL) { | ||
2086 | list = clist_new(); | ||
2087 | if (list == NULL) { | ||
2088 | res = MAILIMF_ERROR_MEMORY; | ||
2089 | goto err; | ||
2090 | } | ||
2091 | |||
2092 | section_id = mailmime_section_new(list); | ||
2093 | if (section_id == NULL) { | ||
2094 | res = MAILIMF_ERROR_MEMORY; | ||
2095 | goto err; | ||
2096 | } | ||
2097 | } | ||
2098 | else { | ||
2099 | uint32_t id; | ||
2100 | uint32_t * p_id; | ||
2101 | clistiter * cur; | ||
2102 | struct mailmime * parent; | ||
2103 | |||
2104 | r = mailmime_get_section_id(mime->mm_parent, §ion_id); | ||
2105 | if (r != MAILIMF_NO_ERROR) { | ||
2106 | res = r; | ||
2107 | goto err; | ||
2108 | } | ||
2109 | |||
2110 | parent = mime->mm_parent; | ||
2111 | switch (parent->mm_type) { | ||
2112 | case MAILMIME_MULTIPLE: | ||
2113 | id = 1; | ||
2114 | for(cur = clist_begin(parent->mm_data.mm_multipart.mm_mp_list) ; | ||
2115 | cur != NULL ; cur = clist_next(cur)) { | ||
2116 | if (clist_content(cur) == mime) | ||
2117 | break; | ||
2118 | id ++; | ||
2119 | } | ||
2120 | |||
2121 | p_id = malloc(sizeof(* p_id)); | ||
2122 | if (p_id == NULL) { | ||
2123 | res = MAILIMF_ERROR_MEMORY; | ||
2124 | goto free; | ||
2125 | } | ||
2126 | * p_id = id; | ||
2127 | |||
2128 | r = clist_append(section_id->sec_list, p_id); | ||
2129 | if (r < 0) { | ||
2130 | free(p_id); | ||
2131 | res = MAILIMF_ERROR_MEMORY; | ||
2132 | goto free; | ||
2133 | } | ||
2134 | break; | ||
2135 | |||
2136 | case MAILMIME_MESSAGE: | ||
2137 | if ((mime->mm_type == MAILMIME_SINGLE) || | ||
2138 | (mime->mm_type == MAILMIME_MESSAGE)) { | ||
2139 | p_id = malloc(sizeof(* p_id)); | ||
2140 | if (p_id == NULL) { | ||
2141 | res = MAILIMF_ERROR_MEMORY; | ||
2142 | goto free; | ||
2143 | } | ||
2144 | * p_id = 1; | ||
2145 | |||
2146 | r = clist_append(section_id->sec_list, p_id); | ||
2147 | if (r < 0) { | ||
2148 | free(p_id); | ||
2149 | res = MAILIMF_ERROR_MEMORY; | ||
2150 | goto free; | ||
2151 | } | ||
2152 | } | ||
2153 | } | ||
2154 | } | ||
2155 | |||
2156 | * result = section_id; | ||
2157 | |||
2158 | return MAILIMF_NO_ERROR; | ||
2159 | |||
2160 | free: | ||
2161 | mailmime_section_free(section_id); | ||
2162 | err: | ||
2163 | return res; | ||
2164 | } | ||
diff --git a/kmicromail/libetpan/mime/mailmime_content.h b/kmicromail/libetpan/mime/mailmime_content.h new file mode 100644 index 0000000..df4b232 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_content.h | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #ifndef MAILMIME_CONTENT_H | ||
37 | |||
38 | #define MAILMIME_CONTENT_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <libetpan/mailmime_types.h> | ||
45 | |||
46 | char * mailmime_content_charset_get(struct mailmime_content * content); | ||
47 | |||
48 | char * mailmime_content_param_get(struct mailmime_content * content, | ||
49 | char * name); | ||
50 | |||
51 | int mailmime_parse(const char * message, size_t length, | ||
52 | size_t * index, struct mailmime ** result); | ||
53 | |||
54 | int mailmime_get_section(struct mailmime * mime, | ||
55 | struct mailmime_section * section, | ||
56 | struct mailmime ** result); | ||
57 | |||
58 | |||
59 | char * mailmime_extract_boundary(struct mailmime_content * content_type); | ||
60 | |||
61 | |||
62 | /* decode */ | ||
63 | |||
64 | int mailmime_base64_body_parse(const char * message, size_t length, | ||
65 | size_t * index, char ** result, | ||
66 | size_t * result_len); | ||
67 | |||
68 | int mailmime_quoted_printable_body_parse(const char * message, size_t length, | ||
69 | size_t * index, char ** result, | ||
70 | size_t * result_len, int in_header); | ||
71 | |||
72 | |||
73 | int mailmime_binary_body_parse(const char * message, size_t length, | ||
74 | size_t * index, char ** result, | ||
75 | size_t * result_len); | ||
76 | |||
77 | int mailmime_part_parse(const char * message, size_t length, | ||
78 | size_t * index, | ||
79 | int encoding, char ** result, size_t * result_len); | ||
80 | |||
81 | |||
82 | int mailmime_get_section_id(struct mailmime * mime, | ||
83 | struct mailmime_section ** result); | ||
84 | |||
85 | #ifdef __cplusplus | ||
86 | } | ||
87 | #endif | ||
88 | |||
89 | #endif | ||
diff --git a/kmicromail/libetpan/mime/mailmime_decode.c b/kmicromail/libetpan/mime/mailmime_decode.c new file mode 100644 index 0000000..3025dcb --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_decode.c | |||
@@ -0,0 +1,533 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | /* | ||
37 | RFC 2047 : MIME (Multipurpose Internet Mail Extensions) Part Three: | ||
38 | Message Header Extensions for Non-ASCII Text | ||
39 | */ | ||
40 | |||
41 | #include "mailmime_decode.h" | ||
42 | |||
43 | #include <ctype.h> | ||
44 | #include <unistd.h> | ||
45 | #include <sys/mman.h> | ||
46 | #include <string.h> | ||
47 | #include <stdlib.h> | ||
48 | |||
49 | #include "mailmime_content.h" | ||
50 | |||
51 | #include "charconv.h" | ||
52 | #include "mmapstring.h" | ||
53 | #include "mailimf.h" | ||
54 | |||
55 | #ifndef TRUE | ||
56 | #define TRUE 1 | ||
57 | #endif | ||
58 | |||
59 | #ifndef FALSE | ||
60 | #define FALSE 0 | ||
61 | #endif | ||
62 | |||
63 | static int mailmime_charset_parse(const char * message, size_t length, | ||
64 | size_t * index, char ** charset); | ||
65 | |||
66 | enum { | ||
67 | MAILMIME_ENCODING_B, | ||
68 | MAILMIME_ENCODING_Q | ||
69 | }; | ||
70 | |||
71 | static int mailmime_encoding_parse(const char * message, size_t length, | ||
72 | size_t * index, int * result); | ||
73 | |||
74 | static int mailmime_etoken_parse(const char * message, size_t length, | ||
75 | size_t * index, char ** result); | ||
76 | |||
77 | static int | ||
78 | mailmime_non_encoded_word_parse(const char * message, size_t length, | ||
79 | size_t * index, | ||
80 | char ** result); | ||
81 | |||
82 | static int | ||
83 | mailmime_encoded_word_parse(const char * message, size_t length, | ||
84 | size_t * index, | ||
85 | struct mailmime_encoded_word ** result); | ||
86 | |||
87 | |||
88 | enum { | ||
89 | TYPE_ERROR, | ||
90 | TYPE_WORD, | ||
91 | TYPE_ENCODED_WORD, | ||
92 | }; | ||
93 | |||
94 | int mailmime_encoded_phrase_parse(const char * default_fromcode, | ||
95 | const char * message, size_t length, | ||
96 | size_t * index, const char * tocode, | ||
97 | char ** result) | ||
98 | { | ||
99 | MMAPString * gphrase; | ||
100 | struct mailmime_encoded_word * word; | ||
101 | int first; | ||
102 | size_t cur_token; | ||
103 | int r; | ||
104 | int res; | ||
105 | char * str; | ||
106 | char * wordutf8; | ||
107 | int type; | ||
108 | |||
109 | cur_token = * index; | ||
110 | |||
111 | gphrase = mmap_string_new(""); | ||
112 | if (gphrase == NULL) { | ||
113 | res = MAILIMF_ERROR_MEMORY; | ||
114 | goto err; | ||
115 | } | ||
116 | |||
117 | first = TRUE; | ||
118 | |||
119 | type = TYPE_ERROR; /* XXX - removes a gcc warning */ | ||
120 | |||
121 | while (1) { | ||
122 | |||
123 | r = mailmime_encoded_word_parse(message, length, &cur_token, &word); | ||
124 | if (r == MAILIMF_NO_ERROR) { | ||
125 | if (!first) { | ||
126 | if (type != TYPE_ENCODED_WORD) { | ||
127 | if (mmap_string_append_c(gphrase, ' ') == NULL) { | ||
128 | mailmime_encoded_word_free(word); | ||
129 | res = MAILIMF_ERROR_MEMORY; | ||
130 | goto free; | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | type = TYPE_ENCODED_WORD; | ||
135 | wordutf8 = NULL; | ||
136 | r = charconv(tocode, word->wd_charset, word->wd_text, | ||
137 | strlen(word->wd_text), &wordutf8); | ||
138 | switch (r) { | ||
139 | case MAIL_CHARCONV_ERROR_MEMORY: | ||
140 | mailmime_encoded_word_free(word); | ||
141 | res = MAILIMF_ERROR_MEMORY; | ||
142 | goto free; | ||
143 | |||
144 | case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET: | ||
145 | case MAIL_CHARCONV_ERROR_CONV: | ||
146 | mailmime_encoded_word_free(word); | ||
147 | res = MAILIMF_ERROR_PARSE; | ||
148 | goto free; | ||
149 | } | ||
150 | |||
151 | if (wordutf8 != NULL) { | ||
152 | if (mmap_string_append(gphrase, wordutf8) == NULL) { | ||
153 | mailmime_encoded_word_free(word); | ||
154 | free(wordutf8); | ||
155 | res = MAILIMF_ERROR_MEMORY; | ||
156 | goto free; | ||
157 | } | ||
158 | free(wordutf8); | ||
159 | } | ||
160 | mailmime_encoded_word_free(word); | ||
161 | first = FALSE; | ||
162 | } | ||
163 | else if (r == MAILIMF_ERROR_PARSE) { | ||
164 | /* do nothing */ | ||
165 | } | ||
166 | else { | ||
167 | res = r; | ||
168 | goto free; | ||
169 | } | ||
170 | |||
171 | if (r == MAILIMF_ERROR_PARSE) { | ||
172 | char * raw_word; | ||
173 | |||
174 | r = mailmime_non_encoded_word_parse(message, length, | ||
175 | &cur_token, &raw_word); | ||
176 | if (r == MAILIMF_NO_ERROR) { | ||
177 | if (!first) { | ||
178 | if (mmap_string_append_c(gphrase, ' ') == NULL) { | ||
179 | free(raw_word); | ||
180 | res = MAILIMF_ERROR_MEMORY; | ||
181 | goto free; | ||
182 | } | ||
183 | } | ||
184 | type = TYPE_WORD; | ||
185 | |||
186 | wordutf8 = NULL; | ||
187 | r = charconv(tocode, default_fromcode, raw_word, | ||
188 | strlen(raw_word), &wordutf8); | ||
189 | |||
190 | if (wordutf8 != NULL) { | ||
191 | if (mmap_string_append(gphrase, wordutf8) == NULL) { | ||
192 | free(wordutf8); | ||
193 | free(raw_word); | ||
194 | res = MAILIMF_ERROR_MEMORY; | ||
195 | goto free; | ||
196 | } | ||
197 | |||
198 | free(wordutf8); | ||
199 | } | ||
200 | free(raw_word); | ||
201 | first = FALSE; | ||
202 | } | ||
203 | else if (r == MAILIMF_ERROR_PARSE) { | ||
204 | break; | ||
205 | } | ||
206 | else { | ||
207 | res = r; | ||
208 | goto free; | ||
209 | } | ||
210 | } | ||
211 | } | ||
212 | |||
213 | if (first) { | ||
214 | res = MAILIMF_ERROR_PARSE; | ||
215 | goto free; | ||
216 | } | ||
217 | |||
218 | str = strdup(gphrase->str); | ||
219 | if (str == NULL) { | ||
220 | res = MAILIMF_ERROR_MEMORY; | ||
221 | goto free; | ||
222 | } | ||
223 | mmap_string_free(gphrase); | ||
224 | |||
225 | * result = str; | ||
226 | * index = cur_token; | ||
227 | |||
228 | return MAILIMF_NO_ERROR; | ||
229 | |||
230 | free: | ||
231 | mmap_string_free(gphrase); | ||
232 | err: | ||
233 | return res; | ||
234 | } | ||
235 | |||
236 | static int | ||
237 | mailmime_non_encoded_word_parse(const char * message, size_t length, | ||
238 | size_t * index, | ||
239 | char ** result) | ||
240 | { | ||
241 | int end; | ||
242 | size_t cur_token; | ||
243 | int res; | ||
244 | char * text; | ||
245 | int r; | ||
246 | size_t begin; | ||
247 | |||
248 | cur_token = * index; | ||
249 | |||
250 | r = mailimf_fws_parse(message, length, &cur_token); | ||
251 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
252 | res = r; | ||
253 | goto err; | ||
254 | } | ||
255 | |||
256 | begin = cur_token; | ||
257 | |||
258 | end = FALSE; | ||
259 | while (1) { | ||
260 | if (cur_token >= length) | ||
261 | break; | ||
262 | |||
263 | switch (message[cur_token]) { | ||
264 | case ' ': | ||
265 | case '\t': | ||
266 | case '\r': | ||
267 | case '\n': | ||
268 | end = TRUE; | ||
269 | break; | ||
270 | } | ||
271 | |||
272 | if (end) | ||
273 | break; | ||
274 | |||
275 | cur_token ++; | ||
276 | } | ||
277 | |||
278 | if (cur_token - begin == 0) { | ||
279 | res = MAILIMF_ERROR_PARSE; | ||
280 | goto err; | ||
281 | } | ||
282 | |||
283 | text = malloc(cur_token - begin + 1); | ||
284 | if (text == NULL) { | ||
285 | res = MAILIMF_ERROR_MEMORY; | ||
286 | goto err; | ||
287 | } | ||
288 | |||
289 | memcpy(text, message + begin, cur_token - begin); | ||
290 | text[cur_token - begin] = '\0'; | ||
291 | |||
292 | * index = cur_token; | ||
293 | * result = text; | ||
294 | |||
295 | return MAILIMF_NO_ERROR; | ||
296 | |||
297 | err: | ||
298 | return res; | ||
299 | } | ||
300 | |||
301 | static int mailmime_encoded_word_parse(const char * message, size_t length, | ||
302 | size_t * index, | ||
303 | struct mailmime_encoded_word ** result) | ||
304 | { | ||
305 | size_t cur_token; | ||
306 | char * charset; | ||
307 | int encoding; | ||
308 | char * text; | ||
309 | size_t end_encoding; | ||
310 | char * decoded; | ||
311 | size_t decoded_len; | ||
312 | struct mailmime_encoded_word * ew; | ||
313 | int r; | ||
314 | int res; | ||
315 | int opening_quote; | ||
316 | int end; | ||
317 | |||
318 | cur_token = * index; | ||
319 | |||
320 | r = mailimf_fws_parse(message, length, &cur_token); | ||
321 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
322 | res = r; | ||
323 | goto err; | ||
324 | } | ||
325 | |||
326 | opening_quote = FALSE; | ||
327 | r = mailimf_char_parse(message, length, &cur_token, '\"'); | ||
328 | if (r == MAILIMF_NO_ERROR) { | ||
329 | opening_quote = TRUE; | ||
330 | } | ||
331 | else if (r == MAILIMF_ERROR_PARSE) { | ||
332 | /* do nothing */ | ||
333 | } | ||
334 | else { | ||
335 | res = r; | ||
336 | goto err; | ||
337 | } | ||
338 | |||
339 | r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "=?"); | ||
340 | if (r != MAILIMF_NO_ERROR) { | ||
341 | res = r; | ||
342 | goto err; | ||
343 | } | ||
344 | |||
345 | r = mailmime_charset_parse(message, length, &cur_token, &charset); | ||
346 | if (r != MAILIMF_NO_ERROR) { | ||
347 | res = r; | ||
348 | goto err; | ||
349 | } | ||
350 | |||
351 | r = mailimf_char_parse(message, length, &cur_token, '?'); | ||
352 | if (r != MAILIMF_NO_ERROR) { | ||
353 | res = r; | ||
354 | goto free_charset; | ||
355 | } | ||
356 | |||
357 | r = mailmime_encoding_parse(message, length, &cur_token, &encoding); | ||
358 | if (r != MAILIMF_NO_ERROR) { | ||
359 | res = r; | ||
360 | goto free_charset; | ||
361 | } | ||
362 | |||
363 | r = mailimf_char_parse(message, length, &cur_token, '?'); | ||
364 | if (r != MAILIMF_NO_ERROR) { | ||
365 | res = r; | ||
366 | goto free_charset; | ||
367 | } | ||
368 | |||
369 | end = FALSE; | ||
370 | end_encoding = cur_token; | ||
371 | while (1) { | ||
372 | if (end_encoding >= length) | ||
373 | break; | ||
374 | |||
375 | switch (message[end_encoding]) { | ||
376 | case '?': | ||
377 | #if 0 | ||
378 | case ' ': | ||
379 | #endif | ||
380 | end = TRUE; | ||
381 | break; | ||
382 | } | ||
383 | |||
384 | if (end) | ||
385 | break; | ||
386 | |||
387 | end_encoding ++; | ||
388 | } | ||
389 | |||
390 | decoded_len = 0; | ||
391 | decoded = NULL; | ||
392 | switch (encoding) { | ||
393 | case MAILMIME_ENCODING_B: | ||
394 | r = mailmime_base64_body_parse(message, end_encoding, | ||
395 | &cur_token, &decoded, | ||
396 | &decoded_len); | ||
397 | |||
398 | if (r != MAILIMF_NO_ERROR) { | ||
399 | res = r; | ||
400 | goto free_charset; | ||
401 | } | ||
402 | break; | ||
403 | case MAILMIME_ENCODING_Q: | ||
404 | r = mailmime_quoted_printable_body_parse(message, end_encoding, | ||
405 | &cur_token, &decoded, | ||
406 | &decoded_len, TRUE); | ||
407 | |||
408 | if (r != MAILIMF_NO_ERROR) { | ||
409 | res = r; | ||
410 | goto free_charset; | ||
411 | } | ||
412 | |||
413 | break; | ||
414 | } | ||
415 | |||
416 | text = malloc(decoded_len + 1); | ||
417 | if (text == NULL) { | ||
418 | res = MAILIMF_ERROR_MEMORY; | ||
419 | goto free_charset; | ||
420 | } | ||
421 | |||
422 | if (decoded_len > 0) | ||
423 | memcpy(text, decoded, decoded_len); | ||
424 | text[decoded_len] = '\0'; | ||
425 | |||
426 | mailmime_decoded_part_free(decoded); | ||
427 | |||
428 | r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "?="); | ||
429 | if (r != MAILIMF_NO_ERROR) { | ||
430 | res = r; | ||
431 | goto free_encoded_text; | ||
432 | } | ||
433 | |||
434 | if (opening_quote) { | ||
435 | r = mailimf_char_parse(message, length, &cur_token, '\"'); | ||
436 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
437 | res = r; | ||
438 | goto free_encoded_text; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | ew = mailmime_encoded_word_new(charset, text); | ||
443 | if (ew == NULL) { | ||
444 | res = MAILIMF_ERROR_MEMORY; | ||
445 | goto free_encoded_text; | ||
446 | } | ||
447 | |||
448 | * result = ew; | ||
449 | * index = cur_token; | ||
450 | |||
451 | return MAILIMF_NO_ERROR; | ||
452 | |||
453 | free_encoded_text: | ||
454 | mailmime_encoded_text_free(text); | ||
455 | free_charset: | ||
456 | mailmime_charset_free(charset); | ||
457 | err: | ||
458 | return res; | ||
459 | } | ||
460 | |||
461 | static int mailmime_charset_parse(const char * message, size_t length, | ||
462 | size_t * index, char ** charset) | ||
463 | { | ||
464 | return mailmime_etoken_parse(message, length, index, charset); | ||
465 | } | ||
466 | |||
467 | static int mailmime_encoding_parse(const char * message, size_t length, | ||
468 | size_t * index, int * result) | ||
469 | { | ||
470 | size_t cur_token; | ||
471 | int encoding; | ||
472 | |||
473 | cur_token = * index; | ||
474 | |||
475 | if (cur_token >= length) | ||
476 | return MAILIMF_ERROR_PARSE; | ||
477 | |||
478 | switch ((char) toupper((unsigned char) message[cur_token])) { | ||
479 | case 'Q': | ||
480 | encoding = MAILMIME_ENCODING_Q; | ||
481 | break; | ||
482 | case 'B': | ||
483 | encoding = MAILMIME_ENCODING_B; | ||
484 | break; | ||
485 | default: | ||
486 | return MAILIMF_ERROR_INVAL; | ||
487 | } | ||
488 | |||
489 | cur_token ++; | ||
490 | |||
491 | * result = encoding; | ||
492 | * index = cur_token; | ||
493 | |||
494 | return MAILIMF_NO_ERROR; | ||
495 | } | ||
496 | |||
497 | int is_etoken_char(char ch) | ||
498 | { | ||
499 | unsigned char uch = ch; | ||
500 | |||
501 | if (uch < 31) | ||
502 | return FALSE; | ||
503 | |||
504 | switch (uch) { | ||
505 | case ' ': | ||
506 | case '(': | ||
507 | case ')': | ||
508 | case '<': | ||
509 | case '>': | ||
510 | case '@': | ||
511 | case ',': | ||
512 | case ';': | ||
513 | case ':': | ||
514 | case '"': | ||
515 | case '/': | ||
516 | case '[': | ||
517 | case ']': | ||
518 | case '?': | ||
519 | case '.': | ||
520 | case '=': | ||
521 | return FALSE; | ||
522 | } | ||
523 | |||
524 | return TRUE; | ||
525 | } | ||
526 | |||
527 | static int mailmime_etoken_parse(const char * message, size_t length, | ||
528 | size_t * index, char ** result) | ||
529 | { | ||
530 | return mailimf_custom_string_parse(message, length, | ||
531 | index, result, | ||
532 | is_etoken_char); | ||
533 | } | ||
diff --git a/kmicromail/libetpan/mime/mailmime_decode.h b/kmicromail/libetpan/mime/mailmime_decode.h new file mode 100644 index 0000000..034db6f --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_decode.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #ifndef MAILMIME_DECODE_H | ||
37 | |||
38 | #define MAILMIME_DECODE_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <libetpan/mailmime_types.h> | ||
45 | |||
46 | int mailmime_encoded_phrase_parse(const char * default_fromcode, | ||
47 | const char * message, size_t length, | ||
48 | size_t * index, const char * tocode, | ||
49 | char ** result); | ||
50 | |||
51 | #ifdef __cplusplus | ||
52 | } | ||
53 | #endif | ||
54 | |||
55 | #endif | ||
diff --git a/kmicromail/libetpan/mime/mailmime_disposition.c b/kmicromail/libetpan/mime/mailmime_disposition.c new file mode 100644 index 0000000..9d8dfec --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_disposition.c | |||
@@ -0,0 +1,595 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #include "mailmime_disposition.h" | ||
37 | #include "mailmime.h" | ||
38 | |||
39 | #include <ctype.h> | ||
40 | #include <stdlib.h> | ||
41 | |||
42 | static int | ||
43 | mailmime_disposition_parm_parse(const char * message, size_t length, | ||
44 | size_t * index, | ||
45 | struct mailmime_disposition_parm ** | ||
46 | result); | ||
47 | |||
48 | static int | ||
49 | mailmime_creation_date_parm_parse(const char * message, size_t length, | ||
50 | size_t * index, char ** result); | ||
51 | |||
52 | static int | ||
53 | mailmime_filename_parm_parse(const char * message, size_t length, | ||
54 | size_t * index, char ** result); | ||
55 | |||
56 | static int | ||
57 | mailmime_modification_date_parm_parse(const char * message, size_t length, | ||
58 | size_t * index, char ** result); | ||
59 | |||
60 | static int | ||
61 | mailmime_read_date_parm_parse(const char * message, size_t length, | ||
62 | size_t * index, char ** result); | ||
63 | |||
64 | static int | ||
65 | mailmime_size_parm_parse(const char * message, size_t length, | ||
66 | size_t * index, size_t * result); | ||
67 | |||
68 | static int | ||
69 | mailmime_quoted_date_time_parse(const char * message, size_t length, | ||
70 | size_t * index, char ** result); | ||
71 | |||
72 | /* | ||
73 | disposition := "Content-Disposition" ":" | ||
74 | disposition-type | ||
75 | *(";" disposition-parm) | ||
76 | |||
77 | */ | ||
78 | |||
79 | |||
80 | int mailmime_disposition_parse(const char * message, size_t length, | ||
81 | size_t * index, | ||
82 | struct mailmime_disposition ** result) | ||
83 | { | ||
84 | size_t final_token; | ||
85 | size_t cur_token; | ||
86 | struct mailmime_disposition_type * dsp_type; | ||
87 | clist * list; | ||
88 | struct mailmime_disposition * dsp; | ||
89 | int r; | ||
90 | int res; | ||
91 | |||
92 | cur_token = * index; | ||
93 | |||
94 | r = mailmime_disposition_type_parse(message, length, &cur_token, | ||
95 | &dsp_type); | ||
96 | if (r != MAILIMF_NO_ERROR) { | ||
97 | res = r; | ||
98 | goto err; | ||
99 | } | ||
100 | |||
101 | list = clist_new(); | ||
102 | if (list == NULL) { | ||
103 | res = MAILIMF_ERROR_MEMORY; | ||
104 | goto free_type; | ||
105 | } | ||
106 | |||
107 | while (1) { | ||
108 | struct mailmime_disposition_parm * param; | ||
109 | |||
110 | final_token = cur_token; | ||
111 | r = mailimf_unstrict_char_parse(message, length, &cur_token, ';'); | ||
112 | if (r == MAILIMF_NO_ERROR) { | ||
113 | /* do nothing */ | ||
114 | } | ||
115 | else if (r == MAILIMF_ERROR_PARSE) { | ||
116 | break; | ||
117 | } | ||
118 | else { | ||
119 | res = r; | ||
120 | goto free_list; | ||
121 | } | ||
122 | |||
123 | r = mailmime_disposition_parm_parse(message, length, &cur_token, ¶m); | ||
124 | if (r == MAILIMF_NO_ERROR) { | ||
125 | /* do nothing */ | ||
126 | } | ||
127 | else if (r == MAILIMF_ERROR_PARSE) { | ||
128 | cur_token = final_token; | ||
129 | break; | ||
130 | } | ||
131 | else { | ||
132 | res = r; | ||
133 | goto free_list; | ||
134 | } | ||
135 | |||
136 | r = clist_append(list, param); | ||
137 | if (r < 0) { | ||
138 | res = MAILIMF_ERROR_MEMORY; | ||
139 | goto free_list; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | dsp = mailmime_disposition_new(dsp_type, list); | ||
144 | if (dsp == NULL) { | ||
145 | res = MAILIMF_ERROR_MEMORY; | ||
146 | goto free_list; | ||
147 | } | ||
148 | |||
149 | * result = dsp; | ||
150 | * index = cur_token; | ||
151 | |||
152 | return MAILIMF_NO_ERROR; | ||
153 | |||
154 | free_list: | ||
155 | clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL); | ||
156 | clist_free(list); | ||
157 | free_type: | ||
158 | mailmime_disposition_type_free(dsp_type); | ||
159 | err: | ||
160 | return res; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | disposition-type := "inline" | ||
165 | / "attachment" | ||
166 | / extension-token | ||
167 | ; values are not case-sensitive | ||
168 | |||
169 | */ | ||
170 | |||
171 | |||
172 | |||
173 | int | ||
174 | mailmime_disposition_type_parse(const char * message, size_t length, | ||
175 | size_t * index, | ||
176 | struct mailmime_disposition_type ** result) | ||
177 | { | ||
178 | size_t cur_token; | ||
179 | int type; | ||
180 | char * extension; | ||
181 | struct mailmime_disposition_type * dsp_type; | ||
182 | int r; | ||
183 | int res; | ||
184 | |||
185 | cur_token = * index; | ||
186 | |||
187 | r = mailimf_cfws_parse(message, length, &cur_token); | ||
188 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
189 | res = r; | ||
190 | goto err; | ||
191 | } | ||
192 | |||
193 | type = MAILMIME_DISPOSITION_TYPE_ERROR; /* XXX - removes a gcc warning */ | ||
194 | |||
195 | extension = NULL; | ||
196 | r = mailimf_token_case_insensitive_parse(message, length, | ||
197 | &cur_token, "inline"); | ||
198 | if (r == MAILIMF_NO_ERROR) | ||
199 | type = MAILMIME_DISPOSITION_TYPE_INLINE; | ||
200 | |||
201 | if (r == MAILIMF_ERROR_PARSE) { | ||
202 | r = mailimf_token_case_insensitive_parse(message, length, | ||
203 | &cur_token, "attachment"); | ||
204 | if (r == MAILIMF_NO_ERROR) | ||
205 | type = MAILMIME_DISPOSITION_TYPE_ATTACHMENT; | ||
206 | } | ||
207 | |||
208 | if (r == MAILIMF_ERROR_PARSE) { | ||
209 | r = mailmime_extension_token_parse(message, length, &cur_token, | ||
210 | &extension); | ||
211 | if (r == MAILIMF_NO_ERROR) | ||
212 | type = MAILMIME_DISPOSITION_TYPE_EXTENSION; | ||
213 | } | ||
214 | |||
215 | if (r != MAILIMF_NO_ERROR) { | ||
216 | res = r; | ||
217 | goto err; | ||
218 | } | ||
219 | |||
220 | dsp_type = mailmime_disposition_type_new(type, extension); | ||
221 | if (dsp_type == NULL) { | ||
222 | res = MAILIMF_ERROR_MEMORY; | ||
223 | goto free; | ||
224 | } | ||
225 | |||
226 | * result = dsp_type; | ||
227 | * index = cur_token; | ||
228 | |||
229 | return MAILIMF_NO_ERROR; | ||
230 | |||
231 | free: | ||
232 | if (extension != NULL) | ||
233 | free(extension); | ||
234 | err: | ||
235 | return res; | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | disposition-parm := filename-parm | ||
240 | / creation-date-parm | ||
241 | / modification-date-parm | ||
242 | / read-date-parm | ||
243 | / size-parm | ||
244 | / parameter | ||
245 | */ | ||
246 | |||
247 | |||
248 | int mailmime_disposition_guess_type(const char * message, size_t length, | ||
249 | size_t index) | ||
250 | { | ||
251 | if (index >= length) | ||
252 | return MAILMIME_DISPOSITION_PARM_PARAMETER; | ||
253 | |||
254 | switch ((char) toupper((unsigned char) message[index])) { | ||
255 | case 'F': | ||
256 | return MAILMIME_DISPOSITION_PARM_FILENAME; | ||
257 | case 'C': | ||
258 | return MAILMIME_DISPOSITION_PARM_CREATION_DATE; | ||
259 | case 'M': | ||
260 | return MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE; | ||
261 | case 'R': | ||
262 | return MAILMIME_DISPOSITION_PARM_READ_DATE; | ||
263 | case 'S': | ||
264 | return MAILMIME_DISPOSITION_PARM_SIZE; | ||
265 | default: | ||
266 | return MAILMIME_DISPOSITION_PARM_PARAMETER; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | static int | ||
271 | mailmime_disposition_parm_parse(const char * message, size_t length, | ||
272 | size_t * index, | ||
273 | struct mailmime_disposition_parm ** | ||
274 | result) | ||
275 | { | ||
276 | char * filename; | ||
277 | char * creation_date; | ||
278 | char * modification_date; | ||
279 | char * read_date; | ||
280 | size_t size; | ||
281 | struct mailmime_parameter * parameter; | ||
282 | size_t cur_token; | ||
283 | struct mailmime_disposition_parm * dsp_parm; | ||
284 | int type; | ||
285 | int guessed_type; | ||
286 | int r; | ||
287 | int res; | ||
288 | |||
289 | cur_token = * index; | ||
290 | |||
291 | filename = NULL; | ||
292 | creation_date = NULL; | ||
293 | modification_date = NULL; | ||
294 | read_date = NULL; | ||
295 | size = 0; | ||
296 | parameter = NULL; | ||
297 | |||
298 | r = mailimf_cfws_parse(message, length, &cur_token); | ||
299 | if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) { | ||
300 | res = r; | ||
301 | goto err; | ||
302 | } | ||
303 | |||
304 | guessed_type = mailmime_disposition_guess_type(message, length, cur_token); | ||
305 | |||
306 | type = MAILMIME_DISPOSITION_PARM_PARAMETER; | ||
307 | |||
308 | switch (guessed_type) { | ||
309 | case MAILMIME_DISPOSITION_PARM_FILENAME: | ||
310 | r = mailmime_filename_parm_parse(message, length, &cur_token, | ||
311 | &filename); | ||
312 | if (r == MAILIMF_NO_ERROR) | ||
313 | type = guessed_type; | ||
314 | else if (r == MAILIMF_ERROR_PARSE) { | ||
315 | /* do nothing */ | ||
316 | } | ||
317 | else { | ||
318 | res = r; | ||
319 | goto err; | ||
320 | } | ||
321 | break; | ||
322 | |||
323 | case MAILMIME_DISPOSITION_PARM_CREATION_DATE: | ||
324 | r = mailmime_creation_date_parm_parse(message, length, &cur_token, | ||
325 | &creation_date); | ||
326 | if (r == MAILIMF_NO_ERROR) | ||
327 | type = guessed_type; | ||
328 | else if (r == MAILIMF_ERROR_PARSE) { | ||
329 | /* do nothing */ | ||
330 | } | ||
331 | else { | ||
332 | res = r; | ||
333 | goto err; | ||
334 | } | ||
335 | break; | ||
336 | |||
337 | case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: | ||
338 | r = mailmime_modification_date_parm_parse(message, length, &cur_token, | ||
339 | &modification_date); | ||
340 | if (r == MAILIMF_NO_ERROR) | ||
341 | type = guessed_type; | ||
342 | else if (r == MAILIMF_ERROR_PARSE) { | ||
343 | /* do nothing */ | ||
344 | } | ||
345 | else { | ||
346 | res = r; | ||
347 | goto err; | ||
348 | } | ||
349 | break; | ||
350 | |||
351 | case MAILMIME_DISPOSITION_PARM_READ_DATE: | ||
352 | r = mailmime_read_date_parm_parse(message, length, &cur_token, | ||
353 | &read_date); | ||
354 | if (r == MAILIMF_NO_ERROR) | ||
355 | type = guessed_type; | ||
356 | else if (r == MAILIMF_ERROR_PARSE) { | ||
357 | /* do nothing */ | ||
358 | } | ||
359 | else { | ||
360 | res = r; | ||
361 | goto err; | ||
362 | } | ||
363 | break; | ||
364 | |||
365 | case MAILMIME_DISPOSITION_PARM_SIZE: | ||
366 | r = mailmime_size_parm_parse(message, length, &cur_token, | ||
367 | &size); | ||
368 | if (r == MAILIMF_NO_ERROR) | ||
369 | type = guessed_type; | ||
370 | else if (r == MAILIMF_ERROR_PARSE) { | ||
371 | /* do nothing */ | ||
372 | } | ||
373 | else { | ||
374 | res = r; | ||
375 | goto err; | ||
376 | } | ||
377 | break; | ||
378 | } | ||
379 | |||
380 | if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) { | ||
381 | r = mailmime_parameter_parse(message, length, &cur_token, | ||
382 | ¶meter); | ||
383 | if (r != MAILIMF_NO_ERROR) { | ||
384 | type = guessed_type; | ||
385 | res = r; | ||
386 | goto err; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | dsp_parm = mailmime_disposition_parm_new(type, filename, creation_date, | ||
391 | modification_date, read_date, | ||
392 | size, parameter); | ||
393 | |||
394 | if (dsp_parm == NULL) { | ||
395 | res = MAILIMF_ERROR_MEMORY; | ||
396 | goto free; | ||
397 | } | ||
398 | |||
399 | * result = dsp_parm; | ||
400 | * index = cur_token; | ||
401 | |||
402 | return MAILIMF_NO_ERROR; | ||
403 | |||
404 | free: | ||
405 | if (filename != NULL) | ||
406 | mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename); | ||
407 | if (creation_date != NULL) | ||
408 | mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date); | ||
409 | if (modification_date != NULL) | ||
410 | mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date); | ||
411 | if (read_date != NULL) | ||
412 | mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date); | ||
413 | if (parameter != NULL) | ||
414 | mailmime_parameter_free(dsp_parm->pa_data.pa_parameter); | ||
415 | err: | ||
416 | return res; | ||
417 | } | ||
418 | |||
419 | /* | ||
420 | filename-parm := "filename" "=" value | ||
421 | */ | ||
422 | |||
423 | static int | ||
424 | mailmime_filename_parm_parse(const char * message, size_t length, | ||
425 | size_t * index, char ** result) | ||
426 | { | ||
427 | char * value; | ||
428 | int r; | ||
429 | size_t cur_token; | ||
430 | |||
431 | cur_token = * index; | ||
432 | |||
433 | r = mailimf_token_case_insensitive_parse(message, length, | ||
434 | &cur_token, "filename"); | ||
435 | if (r != MAILIMF_NO_ERROR) | ||
436 | return r; | ||
437 | |||
438 | r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); | ||
439 | if (r != MAILIMF_NO_ERROR) | ||
440 | return r; | ||
441 | |||
442 | r = mailmime_value_parse(message, length, &cur_token, &value); | ||
443 | if (r != MAILIMF_NO_ERROR) | ||
444 | return r; | ||
445 | |||
446 | * index = cur_token; | ||
447 | * result = value; | ||
448 | |||
449 | return MAILIMF_NO_ERROR; | ||
450 | } | ||
451 | |||
452 | /* | ||
453 | creation-date-parm := "creation-date" "=" quoted-date-time | ||
454 | */ | ||
455 | |||
456 | static int | ||
457 | mailmime_creation_date_parm_parse(const char * message, size_t length, | ||
458 | size_t * index, char ** result) | ||
459 | { | ||
460 | char * value; | ||
461 | int r; | ||
462 | size_t cur_token; | ||
463 | |||
464 | cur_token = * index; | ||
465 | |||
466 | r = mailimf_token_case_insensitive_parse(message, length, | ||
467 | &cur_token, "creation-date"); | ||
468 | if (r != MAILIMF_NO_ERROR) | ||
469 | return r; | ||
470 | |||
471 | r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); | ||
472 | if (r != MAILIMF_NO_ERROR) | ||
473 | return r; | ||
474 | |||
475 | r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); | ||
476 | if (r != MAILIMF_NO_ERROR) | ||
477 | return r; | ||
478 | |||
479 | * index = cur_token; | ||
480 | * result = value; | ||
481 | |||
482 | return MAILIMF_NO_ERROR; | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | modification-date-parm := "modification-date" "=" quoted-date-time | ||
487 | */ | ||
488 | |||
489 | static int | ||
490 | mailmime_modification_date_parm_parse(const char * message, size_t length, | ||
491 | size_t * index, char ** result) | ||
492 | { | ||
493 | char * value; | ||
494 | size_t cur_token; | ||
495 | int r; | ||
496 | |||
497 | cur_token = * index; | ||
498 | |||
499 | r = mailimf_token_case_insensitive_parse(message, length, | ||
500 | &cur_token, "modification-date"); | ||
501 | if (r != MAILIMF_NO_ERROR) | ||
502 | return r; | ||
503 | |||
504 | r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); | ||
505 | if (r != MAILIMF_NO_ERROR) | ||
506 | return r; | ||
507 | |||
508 | r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); | ||
509 | if (r != MAILIMF_NO_ERROR) | ||
510 | return r; | ||
511 | |||
512 | * index = cur_token; | ||
513 | * result = value; | ||
514 | |||
515 | return MAILIMF_NO_ERROR; | ||
516 | } | ||
517 | |||
518 | /* | ||
519 | read-date-parm := "read-date" "=" quoted-date-time | ||
520 | */ | ||
521 | |||
522 | static int | ||
523 | mailmime_read_date_parm_parse(const char * message, size_t length, | ||
524 | size_t * index, char ** result) | ||
525 | { | ||
526 | char * value; | ||
527 | size_t cur_token; | ||
528 | int r; | ||
529 | |||
530 | cur_token = * index; | ||
531 | |||
532 | r = mailimf_token_case_insensitive_parse(message, length, | ||
533 | &cur_token, "read-date"); | ||
534 | if (r != MAILIMF_NO_ERROR) | ||
535 | return r; | ||
536 | |||
537 | r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); | ||
538 | if (r != MAILIMF_NO_ERROR) | ||
539 | return r; | ||
540 | |||
541 | r = mailmime_quoted_date_time_parse(message, length, &cur_token, &value); | ||
542 | if (r != MAILIMF_NO_ERROR) | ||
543 | return r; | ||
544 | |||
545 | * index = cur_token; | ||
546 | * result = value; | ||
547 | |||
548 | return MAILIMF_NO_ERROR; | ||
549 | } | ||
550 | |||
551 | /* | ||
552 | size-parm := "size" "=" 1*DIGIT | ||
553 | */ | ||
554 | |||
555 | static int | ||
556 | mailmime_size_parm_parse(const char * message, size_t length, | ||
557 | size_t * index, size_t * result) | ||
558 | { | ||
559 | uint32_t value; | ||
560 | size_t cur_token; | ||
561 | int r; | ||
562 | |||
563 | cur_token = * index; | ||
564 | |||
565 | r = mailimf_token_case_insensitive_parse(message, length, | ||
566 | &cur_token, "size"); | ||
567 | if (r != MAILIMF_NO_ERROR) | ||
568 | return r; | ||
569 | |||
570 | r = mailimf_unstrict_char_parse(message, length, &cur_token, '='); | ||
571 | if (r != MAILIMF_NO_ERROR) | ||
572 | return r; | ||
573 | |||
574 | r = mailimf_number_parse(message, length, &cur_token, &value); | ||
575 | if (r != MAILIMF_NO_ERROR) | ||
576 | return r; | ||
577 | |||
578 | * index = cur_token; | ||
579 | * result = value; | ||
580 | |||
581 | return MAILIMF_NO_ERROR; | ||
582 | } | ||
583 | |||
584 | /* | ||
585 | quoted-date-time := quoted-string | ||
586 | ; contents MUST be an RFC 822 `date-time' | ||
587 | ; numeric timezones (+HHMM or -HHMM) MUST be used | ||
588 | */ | ||
589 | |||
590 | static int | ||
591 | mailmime_quoted_date_time_parse(const char * message, size_t length, | ||
592 | size_t * index, char ** result) | ||
593 | { | ||
594 | return mailimf_quoted_string_parse(message, length, index, result); | ||
595 | } | ||
diff --git a/kmicromail/libetpan/mime/mailmime_disposition.h b/kmicromail/libetpan/mime/mailmime_disposition.h new file mode 100644 index 0000000..e3bba15 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_disposition.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #ifndef MAILMIME_DISPOSITION_H | ||
37 | |||
38 | #define MAILMIME_DISPOSITION_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <libetpan/mailmime_types.h> | ||
45 | |||
46 | int mailmime_disposition_parse(const char * message, size_t length, | ||
47 | size_t * index, | ||
48 | struct mailmime_disposition ** result); | ||
49 | |||
50 | int | ||
51 | mailmime_disposition_type_parse(const char * message, size_t length, | ||
52 | size_t * index, | ||
53 | struct mailmime_disposition_type ** result); | ||
54 | |||
55 | int mailmime_disposition_guess_type(const char * message, size_t length, | ||
56 | size_t index); | ||
57 | |||
58 | #ifdef __cplusplus | ||
59 | } | ||
60 | #endif | ||
61 | |||
62 | #endif | ||
diff --git a/kmicromail/libetpan/mime/mailmime_types.c b/kmicromail/libetpan/mime/mailmime_types.c new file mode 100644 index 0000000..a81c87a --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types.c | |||
@@ -0,0 +1,750 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #include "mailmime_types.h" | ||
37 | #include "mmapstring.h" | ||
38 | |||
39 | #include <string.h> | ||
40 | #include <stdlib.h> | ||
41 | |||
42 | void mailmime_attribute_free(char * attribute) | ||
43 | { | ||
44 | mailmime_token_free(attribute); | ||
45 | } | ||
46 | |||
47 | |||
48 | |||
49 | struct mailmime_composite_type * | ||
50 | mailmime_composite_type_new(int ct_type, char * ct_token) | ||
51 | { | ||
52 | struct mailmime_composite_type * ct; | ||
53 | |||
54 | ct = malloc(sizeof(* ct)); | ||
55 | if (ct == NULL) | ||
56 | return NULL; | ||
57 | |||
58 | ct->ct_type = ct_type; | ||
59 | ct->ct_token = ct_token; | ||
60 | |||
61 | return ct; | ||
62 | } | ||
63 | |||
64 | void mailmime_composite_type_free(struct mailmime_composite_type * ct) | ||
65 | { | ||
66 | if (ct->ct_token != NULL) | ||
67 | mailmime_extension_token_free(ct->ct_token); | ||
68 | free(ct); | ||
69 | } | ||
70 | |||
71 | |||
72 | struct mailmime_content * | ||
73 | mailmime_content_new(struct mailmime_type * ct_type, | ||
74 | char * ct_subtype, | ||
75 | clist * ct_parameters) | ||
76 | { | ||
77 | struct mailmime_content * content; | ||
78 | |||
79 | content = malloc(sizeof(* content)); | ||
80 | if (content == NULL) | ||
81 | return NULL; | ||
82 | |||
83 | content->ct_type = ct_type; | ||
84 | content->ct_subtype = ct_subtype; | ||
85 | content->ct_parameters = ct_parameters; | ||
86 | |||
87 | return content; | ||
88 | } | ||
89 | |||
90 | void mailmime_content_free(struct mailmime_content * content) | ||
91 | { | ||
92 | mailmime_type_free(content->ct_type); | ||
93 | mailmime_subtype_free(content->ct_subtype); | ||
94 | if (content->ct_parameters != NULL) { | ||
95 | clist_foreach(content->ct_parameters, | ||
96 | (clist_func) mailmime_parameter_free, NULL); | ||
97 | clist_free(content->ct_parameters); | ||
98 | } | ||
99 | |||
100 | free(content); | ||
101 | } | ||
102 | |||
103 | |||
104 | void mailmime_description_free(char * description) | ||
105 | { | ||
106 | free(description); | ||
107 | } | ||
108 | |||
109 | struct mailmime_discrete_type * | ||
110 | mailmime_discrete_type_new(int dt_type, char * dt_extension) | ||
111 | { | ||
112 | struct mailmime_discrete_type * discrete_type; | ||
113 | |||
114 | discrete_type = malloc(sizeof(* discrete_type)); | ||
115 | if (discrete_type == NULL) | ||
116 | return NULL; | ||
117 | |||
118 | discrete_type->dt_type = dt_type; | ||
119 | discrete_type->dt_extension = dt_extension; | ||
120 | |||
121 | return discrete_type; | ||
122 | } | ||
123 | |||
124 | void mailmime_discrete_type_free(struct mailmime_discrete_type * discrete_type) | ||
125 | { | ||
126 | if (discrete_type->dt_extension != NULL) | ||
127 | mailmime_extension_token_free(discrete_type->dt_extension); | ||
128 | free(discrete_type); | ||
129 | } | ||
130 | |||
131 | void mailmime_encoding_free(struct mailmime_mechanism * encoding) | ||
132 | { | ||
133 | mailmime_mechanism_free(encoding); | ||
134 | } | ||
135 | |||
136 | void mailmime_extension_token_free(char * extension) | ||
137 | { | ||
138 | mailmime_token_free(extension); | ||
139 | } | ||
140 | |||
141 | void mailmime_id_free(char * id) | ||
142 | { | ||
143 | mailimf_msg_id_free(id); | ||
144 | } | ||
145 | |||
146 | struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token) | ||
147 | { | ||
148 | struct mailmime_mechanism * mechanism; | ||
149 | |||
150 | mechanism = malloc(sizeof(* mechanism)); | ||
151 | if (mechanism == NULL) | ||
152 | return NULL; | ||
153 | |||
154 | mechanism->enc_type = enc_type; | ||
155 | mechanism->enc_token = enc_token; | ||
156 | |||
157 | return mechanism; | ||
158 | } | ||
159 | |||
160 | void mailmime_mechanism_free(struct mailmime_mechanism * mechanism) | ||
161 | { | ||
162 | if (mechanism->enc_token != NULL) | ||
163 | mailmime_token_free(mechanism->enc_token); | ||
164 | free(mechanism); | ||
165 | } | ||
166 | |||
167 | struct mailmime_parameter * | ||
168 | mailmime_parameter_new(char * pa_name, char * pa_value) | ||
169 | { | ||
170 | struct mailmime_parameter * parameter; | ||
171 | |||
172 | parameter = malloc(sizeof(* parameter)); | ||
173 | if (parameter == NULL) | ||
174 | return NULL; | ||
175 | |||
176 | parameter->pa_name = pa_name; | ||
177 | parameter->pa_value = pa_value; | ||
178 | |||
179 | return parameter; | ||
180 | } | ||
181 | |||
182 | void mailmime_parameter_free(struct mailmime_parameter * parameter) | ||
183 | { | ||
184 | mailmime_attribute_free(parameter->pa_name); | ||
185 | mailmime_value_free(parameter->pa_value); | ||
186 | free(parameter); | ||
187 | } | ||
188 | |||
189 | |||
190 | void mailmime_subtype_free(char * subtype) | ||
191 | { | ||
192 | mailmime_extension_token_free(subtype); | ||
193 | } | ||
194 | |||
195 | |||
196 | void mailmime_token_free(char * token) | ||
197 | { | ||
198 | free(token); | ||
199 | } | ||
200 | |||
201 | |||
202 | struct mailmime_type * | ||
203 | mailmime_type_new(int tp_type, | ||
204 | struct mailmime_discrete_type * tp_discrete_type, | ||
205 | struct mailmime_composite_type * tp_composite_type) | ||
206 | { | ||
207 | struct mailmime_type * mime_type; | ||
208 | |||
209 | mime_type = malloc(sizeof(* mime_type)); | ||
210 | if (mime_type == NULL) | ||
211 | return NULL; | ||
212 | |||
213 | mime_type->tp_type = tp_type; | ||
214 | switch (tp_type) { | ||
215 | case MAILMIME_TYPE_DISCRETE_TYPE: | ||
216 | mime_type->tp_data.tp_discrete_type = tp_discrete_type; | ||
217 | break; | ||
218 | case MAILMIME_TYPE_COMPOSITE_TYPE: | ||
219 | mime_type->tp_data.tp_composite_type = tp_composite_type; | ||
220 | break; | ||
221 | } | ||
222 | |||
223 | return mime_type; | ||
224 | } | ||
225 | |||
226 | void mailmime_type_free(struct mailmime_type * type) | ||
227 | { | ||
228 | switch (type->tp_type) { | ||
229 | case MAILMIME_TYPE_DISCRETE_TYPE: | ||
230 | mailmime_discrete_type_free(type->tp_data.tp_discrete_type); | ||
231 | break; | ||
232 | case MAILMIME_TYPE_COMPOSITE_TYPE: | ||
233 | mailmime_composite_type_free(type->tp_data.tp_composite_type); | ||
234 | break; | ||
235 | } | ||
236 | free(type); | ||
237 | } | ||
238 | |||
239 | void mailmime_value_free(char * value) | ||
240 | { | ||
241 | free(value); | ||
242 | } | ||
243 | |||
244 | |||
245 | /* | ||
246 | void mailmime_x_token_free(gchar * x_token) | ||
247 | { | ||
248 | g_free(x_token); | ||
249 | } | ||
250 | */ | ||
251 | |||
252 | struct mailmime_field * | ||
253 | mailmime_field_new(int fld_type, | ||
254 | struct mailmime_content * fld_content, | ||
255 | struct mailmime_mechanism * fld_encoding, | ||
256 | char * fld_id, | ||
257 | char * fld_description, | ||
258 | uint32_t fld_version, | ||
259 | struct mailmime_disposition * fld_disposition, | ||
260 | struct mailmime_language * fld_language) | ||
261 | { | ||
262 | struct mailmime_field * field; | ||
263 | |||
264 | field = malloc(sizeof(* field)); | ||
265 | if (field == NULL) | ||
266 | return NULL; | ||
267 | field->fld_type = fld_type; | ||
268 | |||
269 | switch (fld_type) { | ||
270 | case MAILMIME_FIELD_TYPE: | ||
271 | field->fld_data.fld_content = fld_content; | ||
272 | break; | ||
273 | case MAILMIME_FIELD_TRANSFER_ENCODING: | ||
274 | field->fld_data.fld_encoding = fld_encoding; | ||
275 | break; | ||
276 | case MAILMIME_FIELD_ID: | ||
277 | field->fld_data.fld_id = fld_id; | ||
278 | break; | ||
279 | case MAILMIME_FIELD_DESCRIPTION: | ||
280 | field->fld_data.fld_description = fld_description; | ||
281 | break; | ||
282 | case MAILMIME_FIELD_VERSION: | ||
283 | field->fld_data.fld_version = fld_version; | ||
284 | break; | ||
285 | case MAILMIME_FIELD_DISPOSITION: | ||
286 | field->fld_data.fld_disposition = fld_disposition; | ||
287 | break; | ||
288 | case MAILMIME_FIELD_LANGUAGE: | ||
289 | field->fld_data.fld_language = fld_language; | ||
290 | break; | ||
291 | } | ||
292 | return field; | ||
293 | } | ||
294 | |||
295 | void mailmime_field_free(struct mailmime_field * field) | ||
296 | { | ||
297 | switch (field->fld_type) { | ||
298 | case MAILMIME_FIELD_TYPE: | ||
299 | if (field->fld_data.fld_content != NULL) | ||
300 | mailmime_content_free(field->fld_data.fld_content); | ||
301 | break; | ||
302 | case MAILMIME_FIELD_TRANSFER_ENCODING: | ||
303 | if (field->fld_data.fld_encoding != NULL) | ||
304 | mailmime_encoding_free(field->fld_data.fld_encoding); | ||
305 | break; | ||
306 | case MAILMIME_FIELD_ID: | ||
307 | if (field->fld_data.fld_id != NULL) | ||
308 | mailmime_id_free(field->fld_data.fld_id); | ||
309 | break; | ||
310 | case MAILMIME_FIELD_DESCRIPTION: | ||
311 | if (field->fld_data.fld_description != NULL) | ||
312 | mailmime_description_free(field->fld_data.fld_description); | ||
313 | break; | ||
314 | case MAILMIME_FIELD_DISPOSITION: | ||
315 | if (field->fld_data.fld_disposition != NULL) | ||
316 | mailmime_disposition_free(field->fld_data.fld_disposition); | ||
317 | break; | ||
318 | case MAILMIME_FIELD_LANGUAGE: | ||
319 | if (field->fld_data.fld_language != NULL) | ||
320 | mailmime_language_free(field->fld_data.fld_language); | ||
321 | break; | ||
322 | } | ||
323 | |||
324 | free(field); | ||
325 | } | ||
326 | |||
327 | struct mailmime_fields * mailmime_fields_new(clist * fld_list) | ||
328 | { | ||
329 | struct mailmime_fields * fields; | ||
330 | |||
331 | fields = malloc(sizeof(* fields)); | ||
332 | if (fields == NULL) | ||
333 | return NULL; | ||
334 | |||
335 | fields->fld_list = fld_list; | ||
336 | |||
337 | return fields; | ||
338 | } | ||
339 | |||
340 | void mailmime_fields_free(struct mailmime_fields * fields) | ||
341 | { | ||
342 | clist_foreach(fields->fld_list, (clist_func) mailmime_field_free, NULL); | ||
343 | clist_free(fields->fld_list); | ||
344 | free(fields); | ||
345 | } | ||
346 | |||
347 | |||
348 | /* | ||
349 | struct mailmime_body_part * | ||
350 | mailmime_body_part_new(gchar * text, guint32 size) | ||
351 | { | ||
352 | struct mailmime_body_part * body_part; | ||
353 | |||
354 | body_part = g_new(struct mailmime_body_part, 1); | ||
355 | if (body_part == NULL) | ||
356 | return NULL; | ||
357 | |||
358 | body_part->text = text; | ||
359 | body_part->size = size; | ||
360 | |||
361 | return body_part; | ||
362 | } | ||
363 | |||
364 | void mailmime_body_part_free(struct mailmime_body_part * body_part) | ||
365 | { | ||
366 | g_free(body_part); | ||
367 | } | ||
368 | */ | ||
369 | |||
370 | struct mailmime_multipart_body * | ||
371 | mailmime_multipart_body_new(clist * bd_list) | ||
372 | { | ||
373 | struct mailmime_multipart_body * mp_body; | ||
374 | |||
375 | mp_body = malloc(sizeof(* mp_body)); | ||
376 | if (mp_body == NULL) | ||
377 | return NULL; | ||
378 | |||
379 | mp_body->bd_list = bd_list; | ||
380 | |||
381 | return mp_body; | ||
382 | } | ||
383 | |||
384 | void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body) | ||
385 | { | ||
386 | clist_foreach(mp_body->bd_list, (clist_func) mailimf_body_free, NULL); | ||
387 | clist_free(mp_body->bd_list); | ||
388 | free(mp_body); | ||
389 | } | ||
390 | |||
391 | |||
392 | |||
393 | |||
394 | struct mailmime * mailmime_new(int mm_type, | ||
395 | const char * mm_mime_start, size_t mm_length, | ||
396 | struct mailmime_fields * mm_mime_fields, | ||
397 | struct mailmime_content * mm_content_type, | ||
398 | struct mailmime_data * mm_body, | ||
399 | struct mailmime_data * mm_preamble, | ||
400 | struct mailmime_data * mm_epilogue, | ||
401 | clist * mm_mp_list, | ||
402 | struct mailimf_fields * mm_fields, | ||
403 | struct mailmime * mm_msg_mime) | ||
404 | { | ||
405 | struct mailmime * mime; | ||
406 | clistiter * cur; | ||
407 | |||
408 | mime = malloc(sizeof(* mime)); | ||
409 | if (mime == NULL) | ||
410 | return NULL; | ||
411 | |||
412 | mime->mm_parent = NULL; | ||
413 | mime->mm_parent_type = MAILMIME_NONE; | ||
414 | mime->mm_multipart_pos = NULL; | ||
415 | |||
416 | mime->mm_type = mm_type; | ||
417 | mime->mm_mime_start = mm_mime_start; | ||
418 | mime->mm_length = mm_length; | ||
419 | mime->mm_mime_fields = mm_mime_fields; | ||
420 | mime->mm_content_type = mm_content_type; | ||
421 | |||
422 | mime->mm_body = mm_body; | ||
423 | |||
424 | switch (mm_type) { | ||
425 | case MAILMIME_SINGLE: | ||
426 | mime->mm_data.mm_single = mm_body; | ||
427 | break; | ||
428 | |||
429 | case MAILMIME_MULTIPLE: | ||
430 | mime->mm_data.mm_multipart.mm_preamble = mm_preamble; | ||
431 | mime->mm_data.mm_multipart.mm_epilogue = mm_epilogue; | ||
432 | mime->mm_data.mm_multipart.mm_mp_list = mm_mp_list; | ||
433 | |||
434 | for(cur = clist_begin(mm_mp_list) ; cur != NULL ; | ||
435 | cur = clist_next(cur)) { | ||
436 | struct mailmime * submime; | ||
437 | |||
438 | submime = clist_content(cur); | ||
439 | submime->mm_parent = mime; | ||
440 | submime->mm_parent_type = MAILMIME_MULTIPLE; | ||
441 | submime->mm_multipart_pos = cur; | ||
442 | } | ||
443 | break; | ||
444 | |||
445 | case MAILMIME_MESSAGE: | ||
446 | mime->mm_data.mm_message.mm_fields = mm_fields; | ||
447 | mime->mm_data.mm_message.mm_msg_mime = mm_msg_mime; | ||
448 | if (mm_msg_mime != NULL) { | ||
449 | mm_msg_mime->mm_parent = mime; | ||
450 | mm_msg_mime->mm_parent_type = MAILMIME_MESSAGE; | ||
451 | } | ||
452 | break; | ||
453 | |||
454 | } | ||
455 | |||
456 | return mime; | ||
457 | } | ||
458 | |||
459 | void mailmime_free(struct mailmime * mime) | ||
460 | { | ||
461 | if (mime->mm_body != NULL) | ||
462 | mailmime_data_free(mime->mm_body); | ||
463 | switch (mime->mm_type) { | ||
464 | case MAILMIME_SINGLE: | ||
465 | /* do nothing */ | ||
466 | break; | ||
467 | |||
468 | case MAILMIME_MULTIPLE: | ||
469 | if (mime->mm_data.mm_multipart.mm_preamble != NULL) | ||
470 | mailmime_data_free(mime->mm_data.mm_multipart.mm_preamble); | ||
471 | if (mime->mm_data.mm_multipart.mm_epilogue != NULL) | ||
472 | mailmime_data_free(mime->mm_data.mm_multipart.mm_epilogue); | ||
473 | clist_foreach(mime->mm_data.mm_multipart.mm_mp_list, | ||
474 | (clist_func) mailmime_free, NULL); | ||
475 | clist_free(mime->mm_data.mm_multipart.mm_mp_list); | ||
476 | break; | ||
477 | |||
478 | case MAILMIME_MESSAGE: | ||
479 | if (mime->mm_data.mm_message.mm_fields != NULL) | ||
480 | mailimf_fields_free(mime->mm_data.mm_message.mm_fields); | ||
481 | if (mime->mm_data.mm_message.mm_msg_mime != NULL) | ||
482 | mailmime_free(mime->mm_data.mm_message.mm_msg_mime); | ||
483 | break; | ||
484 | |||
485 | } | ||
486 | if (mime->mm_mime_fields != NULL) | ||
487 | mailmime_fields_free(mime->mm_mime_fields); | ||
488 | if (mime->mm_content_type != NULL) | ||
489 | mailmime_content_free(mime->mm_content_type); | ||
490 | free(mime); | ||
491 | } | ||
492 | |||
493 | |||
494 | |||
495 | struct mailmime_encoded_word * | ||
496 | mailmime_encoded_word_new(char * wd_charset, char * wd_text) | ||
497 | { | ||
498 | struct mailmime_encoded_word * ew; | ||
499 | |||
500 | ew = malloc(sizeof(* ew)); | ||
501 | if (ew == NULL) | ||
502 | return NULL; | ||
503 | ew->wd_charset = wd_charset; | ||
504 | ew->wd_text = wd_text; | ||
505 | |||
506 | return ew; | ||
507 | } | ||
508 | |||
509 | void mailmime_charset_free(char * charset) | ||
510 | { | ||
511 | free(charset); | ||
512 | } | ||
513 | |||
514 | void mailmime_encoded_text_free(char * text) | ||
515 | { | ||
516 | free(text); | ||
517 | } | ||
518 | |||
519 | void mailmime_encoded_word_free(struct mailmime_encoded_word * ew) | ||
520 | { | ||
521 | mailmime_charset_free(ew->wd_charset); | ||
522 | mailmime_encoded_text_free(ew->wd_text); | ||
523 | free(ew); | ||
524 | } | ||
525 | |||
526 | |||
527 | |||
528 | /* mailmime_disposition */ | ||
529 | |||
530 | |||
531 | struct mailmime_disposition * | ||
532 | mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, | ||
533 | clist * dsp_parms) | ||
534 | { | ||
535 | struct mailmime_disposition * dsp; | ||
536 | |||
537 | dsp = malloc(sizeof(* dsp)); | ||
538 | if (dsp == NULL) | ||
539 | return NULL; | ||
540 | dsp->dsp_type = dsp_type; | ||
541 | dsp->dsp_parms = dsp_parms; | ||
542 | |||
543 | return dsp; | ||
544 | } | ||
545 | |||
546 | void mailmime_disposition_free(struct mailmime_disposition * dsp) | ||
547 | { | ||
548 | mailmime_disposition_type_free(dsp->dsp_type); | ||
549 | clist_foreach(dsp->dsp_parms, | ||
550 | (clist_func) mailmime_disposition_parm_free, NULL); | ||
551 | clist_free(dsp->dsp_parms); | ||
552 | free(dsp); | ||
553 | } | ||
554 | |||
555 | |||
556 | |||
557 | struct mailmime_disposition_type * | ||
558 | mailmime_disposition_type_new(int dsp_type, char * dsp_extension) | ||
559 | { | ||
560 | struct mailmime_disposition_type * m_dsp_type; | ||
561 | |||
562 | m_dsp_type = malloc(sizeof(* m_dsp_type)); | ||
563 | if (m_dsp_type == NULL) | ||
564 | return NULL; | ||
565 | |||
566 | m_dsp_type->dsp_type = dsp_type; | ||
567 | m_dsp_type->dsp_extension = dsp_extension; | ||
568 | |||
569 | return m_dsp_type; | ||
570 | } | ||
571 | |||
572 | void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type) | ||
573 | { | ||
574 | if (dsp_type->dsp_extension != NULL) | ||
575 | free(dsp_type->dsp_extension); | ||
576 | free(dsp_type); | ||
577 | } | ||
578 | |||
579 | |||
580 | struct mailmime_disposition_parm * | ||
581 | mailmime_disposition_parm_new(int pa_type, | ||
582 | char * pa_filename, | ||
583 | char * pa_creation_date, | ||
584 | char * pa_modification_date, | ||
585 | char * pa_read_date, | ||
586 | size_t pa_size, | ||
587 | struct mailmime_parameter * pa_parameter) | ||
588 | { | ||
589 | struct mailmime_disposition_parm * dsp_parm; | ||
590 | |||
591 | dsp_parm = malloc(sizeof(* dsp_parm)); | ||
592 | if (dsp_parm == NULL) | ||
593 | return NULL; | ||
594 | |||
595 | dsp_parm->pa_type = pa_type; | ||
596 | switch (pa_type) { | ||
597 | case MAILMIME_DISPOSITION_PARM_FILENAME: | ||
598 | dsp_parm->pa_data.pa_filename = pa_filename; | ||
599 | break; | ||
600 | case MAILMIME_DISPOSITION_PARM_CREATION_DATE: | ||
601 | dsp_parm->pa_data.pa_creation_date = pa_creation_date; | ||
602 | break; | ||
603 | case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: | ||
604 | dsp_parm->pa_data.pa_modification_date = pa_modification_date; | ||
605 | break; | ||
606 | case MAILMIME_DISPOSITION_PARM_READ_DATE: | ||
607 | dsp_parm->pa_data.pa_read_date = pa_read_date; | ||
608 | break; | ||
609 | case MAILMIME_DISPOSITION_PARM_SIZE: | ||
610 | dsp_parm->pa_data.pa_size = pa_size; | ||
611 | break; | ||
612 | case MAILMIME_DISPOSITION_PARM_PARAMETER: | ||
613 | dsp_parm->pa_data.pa_parameter = pa_parameter; | ||
614 | break; | ||
615 | } | ||
616 | |||
617 | return dsp_parm; | ||
618 | } | ||
619 | |||
620 | void mailmime_disposition_parm_free(struct mailmime_disposition_parm * | ||
621 | dsp_parm) | ||
622 | { | ||
623 | switch (dsp_parm->pa_type) { | ||
624 | case MAILMIME_DISPOSITION_PARM_FILENAME: | ||
625 | mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename); | ||
626 | break; | ||
627 | case MAILMIME_DISPOSITION_PARM_CREATION_DATE: | ||
628 | mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date); | ||
629 | break; | ||
630 | case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: | ||
631 | mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date); | ||
632 | break; | ||
633 | case MAILMIME_DISPOSITION_PARM_READ_DATE: | ||
634 | mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date); | ||
635 | break; | ||
636 | case MAILMIME_DISPOSITION_PARM_PARAMETER: | ||
637 | mailmime_parameter_free(dsp_parm->pa_data.pa_parameter); | ||
638 | break; | ||
639 | } | ||
640 | |||
641 | free(dsp_parm); | ||
642 | } | ||
643 | |||
644 | |||
645 | void mailmime_filename_parm_free(char * filename) | ||
646 | { | ||
647 | mailmime_value_free(filename); | ||
648 | } | ||
649 | |||
650 | void mailmime_creation_date_parm_free(char * date) | ||
651 | { | ||
652 | mailmime_quoted_date_time_free(date); | ||
653 | } | ||
654 | |||
655 | void mailmime_modification_date_parm_free(char * date) | ||
656 | { | ||
657 | mailmime_quoted_date_time_free(date); | ||
658 | } | ||
659 | |||
660 | void mailmime_read_date_parm_free(char * date) | ||
661 | { | ||
662 | mailmime_quoted_date_time_free(date); | ||
663 | } | ||
664 | |||
665 | void mailmime_quoted_date_time_free(char * date) | ||
666 | { | ||
667 | mailimf_quoted_string_free(date); | ||
668 | } | ||
669 | |||
670 | struct mailmime_section * mailmime_section_new(clist * sec_list) | ||
671 | { | ||
672 | struct mailmime_section * section; | ||
673 | |||
674 | section = malloc(sizeof(* section)); | ||
675 | if (section == NULL) | ||
676 | return NULL; | ||
677 | |||
678 | section->sec_list = sec_list; | ||
679 | |||
680 | return section; | ||
681 | } | ||
682 | |||
683 | void mailmime_section_free(struct mailmime_section * section) | ||
684 | { | ||
685 | clist_foreach(section->sec_list, (clist_func) free, NULL); | ||
686 | clist_free(section->sec_list); | ||
687 | free(section); | ||
688 | } | ||
689 | |||
690 | |||
691 | |||
692 | struct mailmime_language * mailmime_language_new(clist * lg_list) | ||
693 | { | ||
694 | struct mailmime_language * lang; | ||
695 | |||
696 | lang = malloc(sizeof(* lang)); | ||
697 | if (lang == NULL) | ||
698 | return NULL; | ||
699 | |||
700 | lang->lg_list = lg_list; | ||
701 | |||
702 | return lang; | ||
703 | } | ||
704 | |||
705 | void mailmime_language_free(struct mailmime_language * lang) | ||
706 | { | ||
707 | clist_foreach(lang->lg_list, (clist_func) mailimf_atom_free, NULL); | ||
708 | clist_free(lang->lg_list); | ||
709 | free(lang); | ||
710 | } | ||
711 | |||
712 | void mailmime_decoded_part_free(char * part) | ||
713 | { | ||
714 | mmap_string_unref(part); | ||
715 | } | ||
716 | |||
717 | struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, | ||
718 | int dt_encoded, const char * dt_data, size_t dt_length, char * dt_filename) | ||
719 | { | ||
720 | struct mailmime_data * mime_data; | ||
721 | |||
722 | mime_data = malloc(sizeof(* mime_data)); | ||
723 | if (mime_data == NULL) | ||
724 | return NULL; | ||
725 | |||
726 | mime_data->dt_type = dt_type; | ||
727 | mime_data->dt_encoding = dt_encoding; | ||
728 | mime_data->dt_encoded = dt_encoded; | ||
729 | switch (dt_type) { | ||
730 | case MAILMIME_DATA_TEXT: | ||
731 | mime_data->dt_data.dt_text.dt_data = dt_data; | ||
732 | mime_data->dt_data.dt_text.dt_length = dt_length; | ||
733 | break; | ||
734 | case MAILMIME_DATA_FILE: | ||
735 | mime_data->dt_data.dt_filename = dt_filename; | ||
736 | break; | ||
737 | } | ||
738 | |||
739 | return mime_data; | ||
740 | } | ||
741 | |||
742 | void mailmime_data_free(struct mailmime_data * mime_data) | ||
743 | { | ||
744 | switch (mime_data->dt_type) { | ||
745 | case MAILMIME_DATA_FILE: | ||
746 | free(mime_data->dt_data.dt_filename); | ||
747 | break; | ||
748 | } | ||
749 | free(mime_data); | ||
750 | } | ||
diff --git a/kmicromail/libetpan/mime/mailmime_types.h b/kmicromail/libetpan/mime/mailmime_types.h new file mode 100644 index 0000000..3bb3b10 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types.h | |||
@@ -0,0 +1,440 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #ifndef MAILMIME_TYPES_H | ||
37 | |||
38 | #define MAILMIME_TYPES_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <inttypes.h> | ||
45 | #include <libetpan/mailimf.h> | ||
46 | #include <libetpan/clist.h> | ||
47 | |||
48 | enum { | ||
49 | MAILMIME_COMPOSITE_TYPE_ERROR, | ||
50 | MAILMIME_COMPOSITE_TYPE_MESSAGE, | ||
51 | MAILMIME_COMPOSITE_TYPE_MULTIPART, | ||
52 | MAILMIME_COMPOSITE_TYPE_EXTENSION | ||
53 | }; | ||
54 | |||
55 | struct mailmime_composite_type { | ||
56 | int ct_type; | ||
57 | char * ct_token; | ||
58 | }; | ||
59 | |||
60 | |||
61 | struct mailmime_content { | ||
62 | struct mailmime_type * ct_type; | ||
63 | char * ct_subtype; | ||
64 | clist * ct_parameters; /* elements are (struct mailmime_parameter *) */ | ||
65 | }; | ||
66 | |||
67 | |||
68 | enum { | ||
69 | MAILMIME_DISCRETE_TYPE_ERROR, | ||
70 | MAILMIME_DISCRETE_TYPE_TEXT, | ||
71 | MAILMIME_DISCRETE_TYPE_IMAGE, | ||
72 | MAILMIME_DISCRETE_TYPE_AUDIO, | ||
73 | MAILMIME_DISCRETE_TYPE_VIDEO, | ||
74 | MAILMIME_DISCRETE_TYPE_APPLICATION, | ||
75 | MAILMIME_DISCRETE_TYPE_EXTENSION | ||
76 | }; | ||
77 | |||
78 | struct mailmime_discrete_type { | ||
79 | int dt_type; | ||
80 | char * dt_extension; | ||
81 | }; | ||
82 | |||
83 | enum { | ||
84 | MAILMIME_FIELD_NONE, | ||
85 | MAILMIME_FIELD_TYPE, | ||
86 | MAILMIME_FIELD_TRANSFER_ENCODING, | ||
87 | MAILMIME_FIELD_ID, | ||
88 | MAILMIME_FIELD_DESCRIPTION, | ||
89 | MAILMIME_FIELD_VERSION, | ||
90 | MAILMIME_FIELD_DISPOSITION, | ||
91 | MAILMIME_FIELD_LANGUAGE, | ||
92 | }; | ||
93 | |||
94 | struct mailmime_field { | ||
95 | int fld_type; | ||
96 | union { | ||
97 | struct mailmime_content * fld_content; | ||
98 | struct mailmime_mechanism * fld_encoding; | ||
99 | char * fld_id; | ||
100 | char * fld_description; | ||
101 | uint32_t fld_version; | ||
102 | struct mailmime_disposition * fld_disposition; | ||
103 | struct mailmime_language * fld_language; | ||
104 | } fld_data; | ||
105 | }; | ||
106 | |||
107 | enum { | ||
108 | MAILMIME_MECHANISM_ERROR, | ||
109 | MAILMIME_MECHANISM_7BIT, | ||
110 | MAILMIME_MECHANISM_8BIT, | ||
111 | MAILMIME_MECHANISM_BINARY, | ||
112 | MAILMIME_MECHANISM_QUOTED_PRINTABLE, | ||
113 | MAILMIME_MECHANISM_BASE64, | ||
114 | MAILMIME_MECHANISM_TOKEN | ||
115 | }; | ||
116 | |||
117 | struct mailmime_mechanism { | ||
118 | int enc_type; | ||
119 | char * enc_token; | ||
120 | }; | ||
121 | |||
122 | |||
123 | struct mailmime_fields { | ||
124 | clist * fld_list; /* list of (struct mailmime_field *) */ | ||
125 | }; | ||
126 | |||
127 | |||
128 | struct mailmime_parameter { | ||
129 | char * pa_name; | ||
130 | char * pa_value; | ||
131 | }; | ||
132 | |||
133 | enum { | ||
134 | MAILMIME_TYPE_ERROR, | ||
135 | MAILMIME_TYPE_DISCRETE_TYPE, | ||
136 | MAILMIME_TYPE_COMPOSITE_TYPE | ||
137 | }; | ||
138 | |||
139 | struct mailmime_type { | ||
140 | int tp_type; | ||
141 | union { | ||
142 | struct mailmime_discrete_type * tp_discrete_type; | ||
143 | struct mailmime_composite_type * tp_composite_type; | ||
144 | } tp_data; | ||
145 | }; | ||
146 | |||
147 | void mailmime_attribute_free(char * attribute); | ||
148 | |||
149 | struct mailmime_composite_type * | ||
150 | mailmime_composite_type_new(int ct_type, char * ct_token); | ||
151 | |||
152 | void mailmime_composite_type_free(struct mailmime_composite_type * ct); | ||
153 | |||
154 | struct mailmime_content * | ||
155 | mailmime_content_new(struct mailmime_type * ct_type, | ||
156 | char * ct_subtype, | ||
157 | clist * ct_parameters); | ||
158 | |||
159 | void mailmime_content_free(struct mailmime_content * content); | ||
160 | |||
161 | void mailmime_description_free(char * description); | ||
162 | |||
163 | struct mailmime_discrete_type * | ||
164 | mailmime_discrete_type_new(int dt_type, char * dt_extension); | ||
165 | |||
166 | void mailmime_discrete_type_free(struct mailmime_discrete_type * | ||
167 | discrete_type); | ||
168 | |||
169 | void mailmime_encoding_free(struct mailmime_mechanism * encoding); | ||
170 | |||
171 | void mailmime_extension_token_free(char * extension); | ||
172 | |||
173 | void mailmime_id_free(char * id); | ||
174 | |||
175 | struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token); | ||
176 | |||
177 | void mailmime_mechanism_free(struct mailmime_mechanism * mechanism); | ||
178 | |||
179 | struct mailmime_parameter * | ||
180 | mailmime_parameter_new(char * pa_name, char * pa_value); | ||
181 | |||
182 | void mailmime_parameter_free(struct mailmime_parameter * parameter); | ||
183 | |||
184 | void mailmime_subtype_free(char * subtype); | ||
185 | |||
186 | void mailmime_token_free(char * token); | ||
187 | |||
188 | struct mailmime_type * | ||
189 | mailmime_type_new(int tp_type, | ||
190 | struct mailmime_discrete_type * tp_discrete_type, | ||
191 | struct mailmime_composite_type * tp_composite_type); | ||
192 | |||
193 | void mailmime_type_free(struct mailmime_type * type); | ||
194 | |||
195 | void mailmime_value_free(char * value); | ||
196 | |||
197 | |||
198 | |||
199 | struct mailmime_language { | ||
200 | clist * lg_list; /* atom (char *) */ | ||
201 | }; | ||
202 | |||
203 | struct mailmime_language * mailmime_language_new(clist * lg_list); | ||
204 | |||
205 | void mailmime_language_free(struct mailmime_language * lang); | ||
206 | |||
207 | |||
208 | /* | ||
209 | void mailmime_x_token_free(gchar * x_token); | ||
210 | */ | ||
211 | |||
212 | struct mailmime_field * | ||
213 | mailmime_field_new(int fld_type, | ||
214 | struct mailmime_content * fld_content, | ||
215 | struct mailmime_mechanism * fld_encoding, | ||
216 | char * fld_id, | ||
217 | char * fld_description, | ||
218 | uint32_t fld_version, | ||
219 | struct mailmime_disposition * fld_disposition, | ||
220 | struct mailmime_language * fld_language); | ||
221 | |||
222 | void mailmime_field_free(struct mailmime_field * field); | ||
223 | |||
224 | struct mailmime_fields * mailmime_fields_new(clist * fld_list); | ||
225 | |||
226 | void mailmime_fields_free(struct mailmime_fields * fields); | ||
227 | |||
228 | |||
229 | struct mailmime_multipart_body { | ||
230 | clist * bd_list; | ||
231 | }; | ||
232 | |||
233 | struct mailmime_multipart_body * | ||
234 | mailmime_multipart_body_new(clist * bd_list); | ||
235 | |||
236 | void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body); | ||
237 | |||
238 | |||
239 | enum { | ||
240 | MAILMIME_DATA_TEXT, | ||
241 | MAILMIME_DATA_FILE, | ||
242 | }; | ||
243 | |||
244 | struct mailmime_data { | ||
245 | int dt_type; | ||
246 | int dt_encoding; | ||
247 | int dt_encoded; | ||
248 | union { | ||
249 | struct { | ||
250 | const char * dt_data; | ||
251 | size_t dt_length; | ||
252 | } dt_text; | ||
253 | char * dt_filename; | ||
254 | } dt_data; | ||
255 | }; | ||
256 | |||
257 | struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding, | ||
258 | int dt_encoded, const char * dt_data, size_t dt_length, | ||
259 | char * dt_filename); | ||
260 | |||
261 | void mailmime_data_free(struct mailmime_data * mime_data); | ||
262 | |||
263 | |||
264 | enum { | ||
265 | MAILMIME_NONE, | ||
266 | MAILMIME_SINGLE, | ||
267 | MAILMIME_MULTIPLE, | ||
268 | MAILMIME_MESSAGE, | ||
269 | }; | ||
270 | |||
271 | struct mailmime { | ||
272 | /* parent information */ | ||
273 | int mm_parent_type; | ||
274 | struct mailmime * mm_parent; | ||
275 | clistiter * mm_multipart_pos; | ||
276 | |||
277 | int mm_type; | ||
278 | const char * mm_mime_start; | ||
279 | size_t mm_length; | ||
280 | |||
281 | struct mailmime_fields * mm_mime_fields; | ||
282 | struct mailmime_content * mm_content_type; | ||
283 | |||
284 | struct mailmime_data * mm_body; | ||
285 | union { | ||
286 | /* single part */ | ||
287 | struct mailmime_data * mm_single; /* XXX - was body */ | ||
288 | |||
289 | /* multi-part */ | ||
290 | struct { | ||
291 | struct mailmime_data * mm_preamble; | ||
292 | struct mailmime_data * mm_epilogue; | ||
293 | clist * mm_mp_list; | ||
294 | } mm_multipart; | ||
295 | |||
296 | /* message */ | ||
297 | struct { | ||
298 | struct mailimf_fields * mm_fields; | ||
299 | struct mailmime * mm_msg_mime; | ||
300 | } mm_message; | ||
301 | |||
302 | } mm_data; | ||
303 | }; | ||
304 | |||
305 | struct mailmime * mailmime_new(int mm_type, | ||
306 | const char * mm_mime_start, size_t mm_length, | ||
307 | struct mailmime_fields * mm_mime_fields, | ||
308 | struct mailmime_content * mm_content_type, | ||
309 | struct mailmime_data * mm_body, | ||
310 | struct mailmime_data * mm_preamble, | ||
311 | struct mailmime_data * mm_epilogue, | ||
312 | clist * mm_mp_list, | ||
313 | struct mailimf_fields * mm_fields, | ||
314 | struct mailmime * mm_msg_mime); | ||
315 | |||
316 | void mailmime_free(struct mailmime * mime); | ||
317 | |||
318 | struct mailmime_encoded_word { | ||
319 | char * wd_charset; | ||
320 | char * wd_text; | ||
321 | }; | ||
322 | |||
323 | struct mailmime_encoded_word * | ||
324 | mailmime_encoded_word_new(char * wd_charset, char * wd_text); | ||
325 | |||
326 | void mailmime_encoded_word_free(struct mailmime_encoded_word * ew); | ||
327 | |||
328 | void mailmime_charset_free(char * charset); | ||
329 | |||
330 | void mailmime_encoded_text_free(char * text); | ||
331 | |||
332 | |||
333 | struct mailmime_disposition { | ||
334 | struct mailmime_disposition_type * dsp_type; | ||
335 | clist * dsp_parms; /* struct mailmime_disposition_parm */ | ||
336 | }; | ||
337 | |||
338 | |||
339 | enum { | ||
340 | MAILMIME_DISPOSITION_TYPE_ERROR, | ||
341 | MAILMIME_DISPOSITION_TYPE_INLINE, | ||
342 | MAILMIME_DISPOSITION_TYPE_ATTACHMENT, | ||
343 | MAILMIME_DISPOSITION_TYPE_EXTENSION | ||
344 | }; | ||
345 | |||
346 | struct mailmime_disposition_type { | ||
347 | int dsp_type; | ||
348 | char * dsp_extension; | ||
349 | }; | ||
350 | |||
351 | |||
352 | enum { | ||
353 | MAILMIME_DISPOSITION_PARM_FILENAME, | ||
354 | MAILMIME_DISPOSITION_PARM_CREATION_DATE, | ||
355 | MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, | ||
356 | MAILMIME_DISPOSITION_PARM_READ_DATE, | ||
357 | MAILMIME_DISPOSITION_PARM_SIZE, | ||
358 | MAILMIME_DISPOSITION_PARM_PARAMETER | ||
359 | }; | ||
360 | |||
361 | struct mailmime_disposition_parm { | ||
362 | int pa_type; | ||
363 | union { | ||
364 | char * pa_filename; | ||
365 | char * pa_creation_date; | ||
366 | char * pa_modification_date; | ||
367 | char * pa_read_date; | ||
368 | size_t pa_size; | ||
369 | struct mailmime_parameter * pa_parameter; | ||
370 | } pa_data; | ||
371 | }; | ||
372 | |||
373 | struct mailmime_disposition * | ||
374 | mailmime_disposition_new(struct mailmime_disposition_type * dsp_type, | ||
375 | clist * dsp_parms); | ||
376 | |||
377 | void mailmime_disposition_free(struct mailmime_disposition * dsp); | ||
378 | |||
379 | struct mailmime_disposition_type * | ||
380 | mailmime_disposition_type_new(int dt_type, char * dt_extension); | ||
381 | |||
382 | void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type); | ||
383 | |||
384 | struct mailmime_disposition_parm * | ||
385 | mailmime_disposition_parm_new(int pa_type, | ||
386 | char * pa_filename, | ||
387 | char * pa_creation_date, | ||
388 | char * pa_modification_date, | ||
389 | char * pa_read_date, | ||
390 | size_t pa_size, | ||
391 | struct mailmime_parameter * pa_parameter); | ||
392 | |||
393 | void mailmime_disposition_parm_free(struct mailmime_disposition_parm * | ||
394 | dsp_parm); | ||
395 | |||
396 | void mailmime_filename_parm_free(char * filename); | ||
397 | |||
398 | void mailmime_creation_date_parm_free(char * date); | ||
399 | |||
400 | void mailmime_modification_date_parm_free(char * date); | ||
401 | |||
402 | void mailmime_read_date_parm_free(char * date); | ||
403 | |||
404 | void mailmime_quoted_date_time_free(char * date); | ||
405 | |||
406 | struct mailmime_section { | ||
407 | clist * sec_list; /* list of (uint32 *) */ | ||
408 | }; | ||
409 | |||
410 | struct mailmime_section * mailmime_section_new(clist * list); | ||
411 | |||
412 | void mailmime_section_free(struct mailmime_section * section); | ||
413 | |||
414 | |||
415 | void mailmime_decoded_part_free(char * part); | ||
416 | |||
417 | struct mailmime_single_fields { | ||
418 | struct mailmime_content * fld_content; | ||
419 | char * fld_content_charset; | ||
420 | char * fld_content_boundary; | ||
421 | char * fld_content_name; | ||
422 | struct mailmime_mechanism * fld_encoding; | ||
423 | char * fld_id; | ||
424 | char * fld_description; | ||
425 | uint32_t fld_version; | ||
426 | struct mailmime_disposition * fld_disposition; | ||
427 | char * fld_disposition_filename; | ||
428 | char * fld_disposition_creation_date; | ||
429 | char * fld_disposition_modification_date; | ||
430 | char * fld_disposition_read_date; | ||
431 | size_t fld_disposition_size; | ||
432 | struct mailmime_language * fld_language; | ||
433 | }; | ||
434 | |||
435 | #ifdef __cplusplus | ||
436 | } | ||
437 | #endif | ||
438 | |||
439 | #endif | ||
440 | |||
diff --git a/kmicromail/libetpan/mime/mailmime_types_helper.c b/kmicromail/libetpan/mime/mailmime_types_helper.c new file mode 100644 index 0000000..83fa1d4 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types_helper.c | |||
@@ -0,0 +1,1385 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #include "mailmime_types_helper.h" | ||
37 | #include "clist.h" | ||
38 | |||
39 | #include "mailmime.h" | ||
40 | |||
41 | #include <string.h> | ||
42 | #include <time.h> | ||
43 | #include <sys/types.h> | ||
44 | #include <unistd.h> | ||
45 | #include <stdlib.h> | ||
46 | |||
47 | #define MIME_VERSION (1 << 16) | ||
48 | |||
49 | int mailmime_transfer_encoding_get(struct mailmime_fields * fields) | ||
50 | { | ||
51 | clistiter * cur; | ||
52 | |||
53 | for(cur = clist_begin(fields->fld_list) ; | ||
54 | cur != NULL ; cur = clist_next(cur)) { | ||
55 | struct mailmime_field * field; | ||
56 | |||
57 | field = clist_content(cur); | ||
58 | if (field->fld_type == MAILMIME_FIELD_TRANSFER_ENCODING) | ||
59 | return field->fld_data.fld_encoding->enc_type; | ||
60 | } | ||
61 | |||
62 | return MAILMIME_MECHANISM_8BIT; | ||
63 | } | ||
64 | |||
65 | struct mailmime_disposition * | ||
66 | mailmime_disposition_new_filename(int type, char * filename) | ||
67 | { | ||
68 | return mailmime_disposition_new_with_data(type, filename, | ||
69 | NULL, NULL, NULL, (size_t) -1); | ||
70 | |||
71 | } | ||
72 | |||
73 | struct mailmime_fields * mailmime_fields_new_empty(void) | ||
74 | { | ||
75 | clist * list; | ||
76 | struct mailmime_fields * fields; | ||
77 | |||
78 | list = clist_new(); | ||
79 | if (list == NULL) | ||
80 | goto err; | ||
81 | |||
82 | fields = mailmime_fields_new(list); | ||
83 | if (fields == NULL) | ||
84 | goto free; | ||
85 | |||
86 | return fields; | ||
87 | |||
88 | free: | ||
89 | clist_free(list); | ||
90 | err: | ||
91 | return NULL; | ||
92 | } | ||
93 | |||
94 | int mailmime_fields_add(struct mailmime_fields * fields, | ||
95 | struct mailmime_field * field) | ||
96 | { | ||
97 | int r; | ||
98 | |||
99 | r = clist_append(fields->fld_list, field); | ||
100 | if (r < 0) | ||
101 | return MAILIMF_ERROR_MEMORY; | ||
102 | |||
103 | return MAILIMF_NO_ERROR; | ||
104 | } | ||
105 | |||
106 | static void mailmime_field_detach(struct mailmime_field * field) | ||
107 | { | ||
108 | switch (field->fld_type) { | ||
109 | case MAILMIME_FIELD_TYPE: | ||
110 | field->fld_data.fld_content = NULL; | ||
111 | break; | ||
112 | case MAILMIME_FIELD_TRANSFER_ENCODING: | ||
113 | field->fld_data.fld_encoding = NULL; | ||
114 | break; | ||
115 | case MAILMIME_FIELD_ID: | ||
116 | field->fld_data.fld_id = NULL; | ||
117 | break; | ||
118 | case MAILMIME_FIELD_DESCRIPTION: | ||
119 | field->fld_data.fld_description = NULL; | ||
120 | break; | ||
121 | case MAILMIME_FIELD_DISPOSITION: | ||
122 | field->fld_data.fld_disposition = NULL; | ||
123 | break; | ||
124 | case MAILMIME_FIELD_LANGUAGE: | ||
125 | field->fld_data.fld_language = NULL; | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | struct mailmime_fields * | ||
131 | mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, | ||
132 | char * id, | ||
133 | char * description, | ||
134 | struct mailmime_disposition * disposition, | ||
135 | struct mailmime_language * language) | ||
136 | { | ||
137 | struct mailmime_field * field; | ||
138 | struct mailmime_fields * fields; | ||
139 | int r; | ||
140 | |||
141 | fields = mailmime_fields_new_empty(); | ||
142 | if (fields == NULL) | ||
143 | goto err; | ||
144 | |||
145 | #if 0 | ||
146 | if (content != NULL) { | ||
147 | field = mailmime_field_new(MAILMIME_FIELD_TYPE, | ||
148 | content, NULL, NULL, NULL, 0, NULL, NULL); | ||
149 | if (field == NULL) | ||
150 | goto free; | ||
151 | |||
152 | r = mailmime_fields_add(fields, field); | ||
153 | if (r != MAILIMF_NO_ERROR) { | ||
154 | mailmime_field_detach(field); | ||
155 | mailmime_field_free(field); | ||
156 | goto free; | ||
157 | } | ||
158 | } | ||
159 | #endif | ||
160 | |||
161 | if (encoding != NULL) { | ||
162 | field = mailmime_field_new(MAILMIME_FIELD_TRANSFER_ENCODING, | ||
163 | NULL, encoding, NULL, NULL, 0, NULL, NULL); | ||
164 | if (field == NULL) | ||
165 | goto free; | ||
166 | |||
167 | r = mailmime_fields_add(fields, field); | ||
168 | if (r != MAILIMF_NO_ERROR) { | ||
169 | mailmime_field_detach(field); | ||
170 | mailmime_field_free(field); | ||
171 | goto free; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | if (id != NULL) { | ||
176 | field = mailmime_field_new(MAILMIME_FIELD_ID, | ||
177 | NULL, NULL, id, NULL, 0, NULL, NULL); | ||
178 | if (field == NULL) | ||
179 | goto free; | ||
180 | |||
181 | r = mailmime_fields_add(fields, field); | ||
182 | if (r != MAILIMF_NO_ERROR) { | ||
183 | mailmime_field_detach(field); | ||
184 | mailmime_field_free(field); | ||
185 | goto free; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | if (description != NULL) { | ||
190 | field = mailmime_field_new(MAILMIME_FIELD_DESCRIPTION, | ||
191 | NULL, NULL, NULL, description, 0, NULL, NULL); | ||
192 | if (field == NULL) | ||
193 | goto free; | ||
194 | |||
195 | r = mailmime_fields_add(fields, field); | ||
196 | if (r != MAILIMF_NO_ERROR) { | ||
197 | mailmime_field_detach(field); | ||
198 | mailmime_field_free(field); | ||
199 | goto free; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | if (disposition != NULL) { | ||
204 | field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, | ||
205 | NULL, NULL, NULL, NULL, 0, disposition, NULL); | ||
206 | if (field == NULL) | ||
207 | goto free; | ||
208 | |||
209 | r = mailmime_fields_add(fields, field); | ||
210 | if (r != MAILIMF_NO_ERROR) { | ||
211 | mailmime_field_detach(field); | ||
212 | mailmime_field_free(field); | ||
213 | goto free; | ||
214 | } | ||
215 | } | ||
216 | |||
217 | if (language != NULL) { | ||
218 | field = mailmime_field_new(MAILMIME_FIELD_DISPOSITION, | ||
219 | NULL, NULL, NULL, NULL, 0, NULL, language); | ||
220 | if (field == NULL) | ||
221 | goto free; | ||
222 | |||
223 | r = mailmime_fields_add(fields, field); | ||
224 | if (r != MAILIMF_NO_ERROR) { | ||
225 | mailmime_field_detach(field); | ||
226 | mailmime_field_free(field); | ||
227 | goto free; | ||
228 | } | ||
229 | } | ||
230 | |||
231 | return fields; | ||
232 | |||
233 | free: | ||
234 | clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL); | ||
235 | mailmime_fields_free(fields); | ||
236 | err: | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | struct mailmime_fields * | ||
241 | mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, | ||
242 | char * id, | ||
243 | char * description, | ||
244 | struct mailmime_disposition * disposition, | ||
245 | struct mailmime_language * language) | ||
246 | { | ||
247 | struct mailmime_field * field; | ||
248 | struct mailmime_fields * fields; | ||
249 | int r; | ||
250 | |||
251 | fields = mailmime_fields_new_with_data(encoding, id, description, | ||
252 | disposition, language); | ||
253 | if (fields == NULL) | ||
254 | goto err; | ||
255 | |||
256 | field = mailmime_field_new(MAILMIME_FIELD_VERSION, | ||
257 | NULL, NULL, NULL, NULL, MIME_VERSION, NULL, NULL); | ||
258 | if (field == NULL) | ||
259 | goto free; | ||
260 | |||
261 | r = mailmime_fields_add(fields, field); | ||
262 | if (r != MAILIMF_NO_ERROR) { | ||
263 | mailmime_field_detach(field); | ||
264 | mailmime_field_free(field); | ||
265 | goto free; | ||
266 | } | ||
267 | |||
268 | return fields; | ||
269 | |||
270 | free: | ||
271 | clist_foreach(fields->fld_list, (clist_func) mailmime_field_detach, NULL); | ||
272 | mailmime_fields_free(fields); | ||
273 | err: | ||
274 | return NULL; | ||
275 | } | ||
276 | |||
277 | |||
278 | struct mailmime_content * mailmime_get_content_message(void) | ||
279 | { | ||
280 | clist * list; | ||
281 | struct mailmime_composite_type * composite_type; | ||
282 | struct mailmime_type * mime_type; | ||
283 | struct mailmime_content * content; | ||
284 | char * subtype; | ||
285 | |||
286 | composite_type = | ||
287 | mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE, | ||
288 | NULL); | ||
289 | if (composite_type == NULL) | ||
290 | goto err; | ||
291 | |||
292 | mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE, | ||
293 | NULL, composite_type); | ||
294 | if (mime_type == NULL) | ||
295 | goto free_composite; | ||
296 | composite_type = NULL; | ||
297 | |||
298 | list = clist_new(); | ||
299 | if (list == NULL) | ||
300 | goto free_mime_type; | ||
301 | |||
302 | subtype = strdup("rfc822"); | ||
303 | if (subtype == NULL) | ||
304 | goto free_list; | ||
305 | |||
306 | content = mailmime_content_new(mime_type, subtype, list); | ||
307 | if (content == NULL) | ||
308 | goto free_subtype; | ||
309 | |||
310 | return content; | ||
311 | |||
312 | free_subtype: | ||
313 | free(subtype); | ||
314 | free_list: | ||
315 | clist_free(list); | ||
316 | free_mime_type: | ||
317 | mailmime_type_free(mime_type); | ||
318 | free_composite: | ||
319 | if (composite_type != NULL) | ||
320 | mailmime_composite_type_free(composite_type); | ||
321 | err: | ||
322 | return NULL; | ||
323 | } | ||
324 | |||
325 | struct mailmime_content * mailmime_get_content_text(void) | ||
326 | { | ||
327 | clist * list; | ||
328 | struct mailmime_discrete_type * discrete_type; | ||
329 | struct mailmime_type * mime_type; | ||
330 | struct mailmime_content * content; | ||
331 | char * subtype; | ||
332 | |||
333 | discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT, | ||
334 | NULL); | ||
335 | if (discrete_type == NULL) | ||
336 | goto err; | ||
337 | |||
338 | mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE, | ||
339 | discrete_type, NULL); | ||
340 | if (mime_type == NULL) | ||
341 | goto free_discrete; | ||
342 | discrete_type = NULL; | ||
343 | |||
344 | list = clist_new(); | ||
345 | if (list == NULL) | ||
346 | goto free_type; | ||
347 | |||
348 | subtype = strdup("plain"); | ||
349 | if (subtype == NULL) | ||
350 | goto free_list; | ||
351 | |||
352 | content = mailmime_content_new(mime_type, subtype, list); | ||
353 | if (content == NULL) | ||
354 | goto free_subtype; | ||
355 | |||
356 | return content; | ||
357 | |||
358 | free_subtype: | ||
359 | free(subtype); | ||
360 | free_list: | ||
361 | clist_free(list); | ||
362 | free_type: | ||
363 | mailmime_type_free(mime_type); | ||
364 | free_discrete: | ||
365 | if (discrete_type != NULL) | ||
366 | mailmime_discrete_type_free(discrete_type); | ||
367 | err: | ||
368 | return NULL; | ||
369 | } | ||
370 | |||
371 | |||
372 | |||
373 | |||
374 | |||
375 | |||
376 | |||
377 | |||
378 | /* mailmime build */ | ||
379 | |||
380 | |||
381 | #if 0 | ||
382 | struct mailmime * | ||
383 | mailmime_new_message_file(char * filename) | ||
384 | { | ||
385 | struct mailmime_content * content; | ||
386 | struct mailmime * build_info; | ||
387 | struct mailmime_data * msg_content; | ||
388 | struct mailmime_fields * mime_fields; | ||
389 | |||
390 | content = mailmime_get_content_message(); | ||
391 | if (content == NULL) { | ||
392 | goto err; | ||
393 | } | ||
394 | |||
395 | mime_fields = mailmime_fields_new_with_version(NULL, NULL, | ||
396 | NULL, NULL, NULL); | ||
397 | if (mime_fields == NULL) | ||
398 | goto free_content; | ||
399 | |||
400 | msg_content = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, | ||
401 | 1, NULL, 0, filename); | ||
402 | if (msg_content == NULL) | ||
403 | goto free_fields; | ||
404 | |||
405 | build_info = mailmime_new(MAILMIME_MESSAGE, | ||
406 | NULL, 0, mime_fields, content, | ||
407 | msg_content, NULL, NULL, NULL, NULL, NULL); | ||
408 | if (build_info == NULL) | ||
409 | goto free_msg_content; | ||
410 | |||
411 | return build_info; | ||
412 | |||
413 | free_msg_content: | ||
414 | mailmime_data_free(msg_content); | ||
415 | free_fields: | ||
416 | mailmime_fields_free(mime_fields); | ||
417 | free_content: | ||
418 | mailmime_content_free(content); | ||
419 | err: | ||
420 | return NULL; | ||
421 | } | ||
422 | |||
423 | struct mailmime * | ||
424 | mailmime_new_message_text(char * data_str, size_t length) | ||
425 | { | ||
426 | struct mailmime_content * content; | ||
427 | struct mailmime * build_info; | ||
428 | struct mailmime_data * msg_content; | ||
429 | struct mailmime_fields * mime_fields; | ||
430 | |||
431 | content = mailmime_get_content_message(); | ||
432 | if (content == NULL) { | ||
433 | goto err; | ||
434 | } | ||
435 | |||
436 | mime_fields = mailmime_fields_new_with_version(NULL, NULL, | ||
437 | NULL, NULL, NULL); | ||
438 | if (mime_fields == NULL) | ||
439 | goto free_fields; | ||
440 | |||
441 | msg_content = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, | ||
442 | 1, data_str, length, NULL); | ||
443 | if (msg_content == NULL) | ||
444 | goto free_content; | ||
445 | |||
446 | build_info = mailmime_new(MAILMIME_MESSAGE, | ||
447 | NULL, 0, mime_fields, content, | ||
448 | msg_content, NULL, NULL, NULL, | ||
449 | NULL, NULL); | ||
450 | if (build_info == NULL) | ||
451 | goto free_msg_content; | ||
452 | |||
453 | return build_info; | ||
454 | |||
455 | free_msg_content: | ||
456 | mailmime_data_free(msg_content); | ||
457 | free_fields: | ||
458 | mailmime_fields_free(mime_fields); | ||
459 | free_content: | ||
460 | mailmime_content_free(content); | ||
461 | err: | ||
462 | return NULL; | ||
463 | } | ||
464 | #endif | ||
465 | |||
466 | struct mailmime * | ||
467 | mailmime_new_message_data(struct mailmime * msg_mime) | ||
468 | { | ||
469 | struct mailmime_content * content; | ||
470 | struct mailmime * build_info; | ||
471 | struct mailmime_fields * mime_fields; | ||
472 | |||
473 | content = mailmime_get_content_message(); | ||
474 | if (content == NULL) | ||
475 | goto err; | ||
476 | |||
477 | mime_fields = mailmime_fields_new_with_version(NULL, NULL, | ||
478 | NULL, NULL, NULL); | ||
479 | if (mime_fields == NULL) | ||
480 | goto free_content; | ||
481 | |||
482 | build_info = mailmime_new(MAILMIME_MESSAGE, | ||
483 | NULL, 0, mime_fields, content, | ||
484 | NULL, NULL, NULL, NULL, | ||
485 | NULL, msg_mime); | ||
486 | if (build_info == NULL) | ||
487 | goto free_fields; | ||
488 | |||
489 | return build_info; | ||
490 | |||
491 | free_fields: | ||
492 | mailmime_fields_free(mime_fields); | ||
493 | free_content: | ||
494 | mailmime_content_free(content); | ||
495 | err: | ||
496 | return NULL; | ||
497 | } | ||
498 | |||
499 | #define MAX_MESSAGE_ID 512 | ||
500 | |||
501 | static char * generate_boundary() | ||
502 | { | ||
503 | char id[MAX_MESSAGE_ID]; | ||
504 | time_t now; | ||
505 | char name[MAX_MESSAGE_ID]; | ||
506 | long value; | ||
507 | |||
508 | now = time(NULL); | ||
509 | value = random(); | ||
510 | |||
511 | gethostname(name, MAX_MESSAGE_ID); | ||
512 | snprintf(id, MAX_MESSAGE_ID, "%lx_%lx_%x", now, value, getpid()); | ||
513 | |||
514 | return strdup(id); | ||
515 | } | ||
516 | |||
517 | struct mailmime * | ||
518 | mailmime_new_empty(struct mailmime_content * content, | ||
519 | struct mailmime_fields * mime_fields) | ||
520 | { | ||
521 | struct mailmime * build_info; | ||
522 | clist * list; | ||
523 | int r; | ||
524 | int mime_type; | ||
525 | |||
526 | list = NULL; | ||
527 | |||
528 | switch (content->ct_type->tp_type) { | ||
529 | case MAILMIME_TYPE_DISCRETE_TYPE: | ||
530 | mime_type = MAILMIME_SINGLE; | ||
531 | break; | ||
532 | |||
533 | case MAILMIME_TYPE_COMPOSITE_TYPE: | ||
534 | switch (content->ct_type->tp_data.tp_composite_type->ct_type) { | ||
535 | case MAILMIME_COMPOSITE_TYPE_MULTIPART: | ||
536 | mime_type = MAILMIME_MULTIPLE; | ||
537 | break; | ||
538 | |||
539 | case MAILMIME_COMPOSITE_TYPE_MESSAGE: | ||
540 | if (strcasecmp(content->ct_subtype, "rfc822") == 0) | ||
541 | mime_type = MAILMIME_MESSAGE; | ||
542 | else | ||
543 | mime_type = MAILMIME_SINGLE; | ||
544 | break; | ||
545 | |||
546 | default: | ||
547 | goto err; | ||
548 | } | ||
549 | break; | ||
550 | |||
551 | default: | ||
552 | goto err; | ||
553 | } | ||
554 | |||
555 | if (mime_type == MAILMIME_MULTIPLE) { | ||
556 | char * attr_name; | ||
557 | char * attr_value; | ||
558 | struct mailmime_parameter * param; | ||
559 | clist * parameters; | ||
560 | char * boundary; | ||
561 | |||
562 | list = clist_new(); | ||
563 | if (list == NULL) | ||
564 | goto err; | ||
565 | |||
566 | attr_name = strdup("boundary"); | ||
567 | if (attr_name == NULL) | ||
568 | goto free_list; | ||
569 | |||
570 | boundary = generate_boundary(); | ||
571 | attr_value = boundary; | ||
572 | if (attr_name == NULL) { | ||
573 | free(attr_name); | ||
574 | goto free_list; | ||
575 | } | ||
576 | |||
577 | param = mailmime_parameter_new(attr_name, attr_value); | ||
578 | if (param == NULL) { | ||
579 | free(attr_value); | ||
580 | free(attr_name); | ||
581 | goto free_list; | ||
582 | } | ||
583 | |||
584 | if (content->ct_parameters == NULL) { | ||
585 | parameters = clist_new(); | ||
586 | if (parameters == NULL) { | ||
587 | mailmime_parameter_free(param); | ||
588 | goto free_list; | ||
589 | } | ||
590 | } | ||
591 | else | ||
592 | parameters = content->ct_parameters; | ||
593 | |||
594 | r = clist_append(parameters, param); | ||
595 | if (r != 0) { | ||
596 | clist_free(parameters); | ||
597 | mailmime_parameter_free(param); | ||
598 | goto free_list; | ||
599 | } | ||
600 | |||
601 | if (content->ct_parameters == NULL) | ||
602 | content->ct_parameters = parameters; | ||
603 | } | ||
604 | |||
605 | build_info = mailmime_new(mime_type, | ||
606 | NULL, 0, mime_fields, content, | ||
607 | NULL, NULL, NULL, list, | ||
608 | NULL, NULL); | ||
609 | if (build_info == NULL) { | ||
610 | clist_free(list); | ||
611 | return NULL; | ||
612 | } | ||
613 | |||
614 | return build_info; | ||
615 | |||
616 | free_list: | ||
617 | clist_free(list); | ||
618 | err: | ||
619 | return NULL; | ||
620 | } | ||
621 | |||
622 | |||
623 | int | ||
624 | mailmime_new_with_content(const char * content_type, | ||
625 | struct mailmime_fields * mime_fields, | ||
626 | struct mailmime ** result) | ||
627 | { | ||
628 | int r; | ||
629 | size_t cur_token; | ||
630 | struct mailmime_content * content; | ||
631 | struct mailmime * build_info; | ||
632 | #if 0 | ||
633 | int mime_type; | ||
634 | #endif | ||
635 | int res; | ||
636 | |||
637 | cur_token = 0; | ||
638 | r = mailmime_content_parse(content_type, strlen(content_type), | ||
639 | &cur_token, | ||
640 | &content); | ||
641 | if (r != MAILIMF_NO_ERROR) { | ||
642 | res = r; | ||
643 | goto err; | ||
644 | } | ||
645 | |||
646 | #if 0 | ||
647 | switch (content->type->type) { | ||
648 | case MAILMIME_TYPE_DISCRETE_TYPE: | ||
649 | mime_type = MAILMIME_SINGLE; | ||
650 | break; | ||
651 | |||
652 | case MAILMIME_TYPE_COMPOSITE_TYPE: | ||
653 | switch (content->type->composite_type->type) { | ||
654 | case MAILMIME_COMPOSITE_TYPE_MULTIPART: | ||
655 | mime_type = MAILMIME_MULTIPLE; | ||
656 | break; | ||
657 | |||
658 | case MAILMIME_COMPOSITE_TYPE_MESSAGE: | ||
659 | if (strcasecmp(content->subtype, "rfc822") == 0) | ||
660 | mime_type = MAILMIME_MESSAGE; | ||
661 | else | ||
662 | mime_type = MAILMIME_SINGLE; | ||
663 | break; | ||
664 | |||
665 | default: | ||
666 | res = MAILIMF_ERROR_INVAL; | ||
667 | goto free; | ||
668 | } | ||
669 | break; | ||
670 | |||
671 | default: | ||
672 | res = MAILIMF_ERROR_INVAL; | ||
673 | goto free; | ||
674 | } | ||
675 | #endif | ||
676 | |||
677 | build_info = mailmime_new_empty(content, mime_fields); | ||
678 | if (build_info == NULL) { | ||
679 | res = MAILIMF_ERROR_MEMORY; | ||
680 | goto free; | ||
681 | } | ||
682 | |||
683 | * result = build_info; | ||
684 | |||
685 | return MAILIMF_NO_ERROR; | ||
686 | |||
687 | free: | ||
688 | mailmime_content_free(content); | ||
689 | err: | ||
690 | return res; | ||
691 | } | ||
692 | |||
693 | int mailmime_set_preamble_file(struct mailmime * build_info, | ||
694 | char * filename) | ||
695 | { | ||
696 | struct mailmime_data * data; | ||
697 | |||
698 | data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, | ||
699 | 0, NULL, 0, filename); | ||
700 | if (data == NULL) | ||
701 | return MAILIMF_ERROR_MEMORY; | ||
702 | |||
703 | build_info->mm_data.mm_multipart.mm_preamble = data; | ||
704 | |||
705 | return MAILIMF_NO_ERROR; | ||
706 | } | ||
707 | |||
708 | int mailmime_set_epilogue_file(struct mailmime * build_info, | ||
709 | char * filename) | ||
710 | { | ||
711 | struct mailmime_data * data; | ||
712 | |||
713 | data = mailmime_data_new(MAILMIME_DATA_FILE, MAILMIME_MECHANISM_8BIT, | ||
714 | 0, NULL, 0, filename); | ||
715 | if (data == NULL) | ||
716 | return MAILIMF_ERROR_MEMORY; | ||
717 | |||
718 | build_info->mm_data.mm_multipart.mm_epilogue = data; | ||
719 | |||
720 | return MAILIMF_NO_ERROR; | ||
721 | } | ||
722 | |||
723 | int mailmime_set_preamble_text(struct mailmime * build_info, | ||
724 | char * data_str, size_t length) | ||
725 | { | ||
726 | struct mailmime_data * data; | ||
727 | |||
728 | data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, | ||
729 | 0, data_str, length, NULL); | ||
730 | if (data == NULL) | ||
731 | return MAILIMF_ERROR_MEMORY; | ||
732 | |||
733 | build_info->mm_data.mm_multipart.mm_preamble = data; | ||
734 | |||
735 | return MAILIMF_NO_ERROR; | ||
736 | } | ||
737 | |||
738 | int mailmime_set_epilogue_text(struct mailmime * build_info, | ||
739 | char * data_str, size_t length) | ||
740 | { | ||
741 | struct mailmime_data * data; | ||
742 | |||
743 | data = mailmime_data_new(MAILMIME_DATA_TEXT, MAILMIME_MECHANISM_8BIT, | ||
744 | 0, data_str, length, NULL); | ||
745 | if (data == NULL) | ||
746 | return MAILIMF_ERROR_MEMORY; | ||
747 | |||
748 | build_info->mm_data.mm_multipart.mm_epilogue = data; | ||
749 | |||
750 | return MAILIMF_NO_ERROR; | ||
751 | } | ||
752 | |||
753 | |||
754 | int mailmime_set_body_file(struct mailmime * build_info, | ||
755 | char * filename) | ||
756 | { | ||
757 | int encoding; | ||
758 | struct mailmime_data * data; | ||
759 | |||
760 | encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields); | ||
761 | |||
762 | data = mailmime_data_new(MAILMIME_DATA_FILE, encoding, | ||
763 | 0, NULL, 0, filename); | ||
764 | if (data == NULL) | ||
765 | return MAILIMF_ERROR_MEMORY; | ||
766 | |||
767 | build_info->mm_data.mm_single = data; | ||
768 | |||
769 | return MAILIMF_NO_ERROR; | ||
770 | } | ||
771 | |||
772 | int mailmime_set_body_text(struct mailmime * build_info, | ||
773 | char * data_str, size_t length) | ||
774 | { | ||
775 | int encoding; | ||
776 | struct mailmime_data * data; | ||
777 | |||
778 | encoding = mailmime_transfer_encoding_get(build_info->mm_mime_fields); | ||
779 | |||
780 | data = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, | ||
781 | 0, data_str, length, NULL); | ||
782 | if (data == NULL) | ||
783 | return MAILIMF_ERROR_MEMORY; | ||
784 | |||
785 | build_info->mm_data.mm_single = data; | ||
786 | |||
787 | return MAILIMF_NO_ERROR; | ||
788 | } | ||
789 | |||
790 | |||
791 | /* add a part as subpart of a mime part */ | ||
792 | |||
793 | int mailmime_add_part(struct mailmime * build_info, | ||
794 | struct mailmime * part) | ||
795 | { | ||
796 | int r; | ||
797 | |||
798 | if (build_info->mm_type == MAILMIME_MESSAGE) { | ||
799 | build_info->mm_data.mm_message.mm_msg_mime = part; | ||
800 | part->mm_parent_type = MAILMIME_MESSAGE; | ||
801 | part->mm_parent = build_info; | ||
802 | } | ||
803 | else if (build_info->mm_type == MAILMIME_MULTIPLE) { | ||
804 | r = clist_append(build_info->mm_data.mm_multipart.mm_mp_list, part); | ||
805 | if (r != 0) | ||
806 | return MAILIMF_ERROR_MEMORY; | ||
807 | |||
808 | part->mm_parent_type = MAILMIME_MULTIPLE; | ||
809 | part->mm_parent = build_info; | ||
810 | part->mm_multipart_pos = | ||
811 | clist_end(build_info->mm_data.mm_multipart.mm_mp_list); | ||
812 | } | ||
813 | else { | ||
814 | return MAILIMF_ERROR_INVAL; | ||
815 | } | ||
816 | return MAILIMF_NO_ERROR; | ||
817 | } | ||
818 | |||
819 | /* detach part from parent */ | ||
820 | |||
821 | void mailmime_remove_part(struct mailmime * mime) | ||
822 | { | ||
823 | struct mailmime * parent; | ||
824 | |||
825 | parent = mime->mm_parent; | ||
826 | if (parent == NULL) | ||
827 | return; | ||
828 | |||
829 | switch (mime->mm_parent_type) { | ||
830 | case MAILMIME_MESSAGE: | ||
831 | mime->mm_parent = NULL; | ||
832 | parent->mm_data.mm_message.mm_msg_mime = NULL; | ||
833 | break; | ||
834 | |||
835 | case MAILMIME_MULTIPLE: | ||
836 | mime->mm_parent = NULL; | ||
837 | clist_delete(parent->mm_data.mm_multipart.mm_mp_list, | ||
838 | mime->mm_multipart_pos); | ||
839 | break; | ||
840 | } | ||
841 | } | ||
842 | |||
843 | |||
844 | /* | ||
845 | attach a part to a mime part and create multipart/mixed | ||
846 | when needed, when the parent part has already some part | ||
847 | attached to it. | ||
848 | */ | ||
849 | |||
850 | int mailmime_smart_add_part(struct mailmime * mime, | ||
851 | struct mailmime * mime_sub) | ||
852 | { | ||
853 | struct mailmime * saved_sub; | ||
854 | struct mailmime * mp; | ||
855 | int res; | ||
856 | int r; | ||
857 | |||
858 | switch (mime->mm_type) { | ||
859 | case MAILMIME_SINGLE: | ||
860 | res = MAILIMF_ERROR_INVAL; | ||
861 | goto err; | ||
862 | |||
863 | case MAILMIME_MULTIPLE: | ||
864 | r = mailmime_add_part(mime, mime_sub); | ||
865 | if (r != MAILIMF_NO_ERROR) { | ||
866 | res = MAILIMF_ERROR_MEMORY; | ||
867 | goto err; | ||
868 | } | ||
869 | |||
870 | return MAILIMF_NO_ERROR; | ||
871 | } | ||
872 | |||
873 | /* MAILMIME_MESSAGE */ | ||
874 | |||
875 | if (mime->mm_data.mm_message.mm_msg_mime == NULL) { | ||
876 | /* there is no subpart, we can simply attach it */ | ||
877 | |||
878 | r = mailmime_add_part(mime, mime_sub); | ||
879 | if (r != MAILIMF_NO_ERROR) { | ||
880 | res = MAILIMF_ERROR_MEMORY; | ||
881 | goto err; | ||
882 | } | ||
883 | |||
884 | return MAILIMF_NO_ERROR; | ||
885 | } | ||
886 | |||
887 | if (mime->mm_data.mm_message.mm_msg_mime->mm_type == MAILMIME_MULTIPLE) { | ||
888 | /* in case the subpart is multipart, simply attach it to the subpart */ | ||
889 | |||
890 | return mailmime_add_part(mime->mm_data.mm_message.mm_msg_mime, mime_sub); | ||
891 | } | ||
892 | |||
893 | /* we save the current subpart, ... */ | ||
894 | |||
895 | saved_sub = mime->mm_data.mm_message.mm_msg_mime; | ||
896 | |||
897 | /* create a multipart */ | ||
898 | |||
899 | mp = mailmime_multiple_new("multipart/mixed"); | ||
900 | if (mp == NULL) { | ||
901 | res = MAILIMF_ERROR_MEMORY; | ||
902 | goto err; | ||
903 | } | ||
904 | |||
905 | /* detach the saved subpart from the parent */ | ||
906 | |||
907 | mailmime_remove_part(saved_sub); | ||
908 | |||
909 | /* the created multipart is the new child of the parent */ | ||
910 | |||
911 | r = mailmime_add_part(mime, mp); | ||
912 | if (r != MAILIMF_NO_ERROR) { | ||
913 | res = MAILIMF_ERROR_MEMORY; | ||
914 | goto free_mp; | ||
915 | } | ||
916 | |||
917 | /* then, attach the saved subpart and ... */ | ||
918 | |||
919 | r = mailmime_add_part(mp, saved_sub); | ||
920 | if (r != MAILIMF_NO_ERROR) { | ||
921 | res = MAILIMF_ERROR_MEMORY; | ||
922 | goto free_saved_sub; | ||
923 | } | ||
924 | |||
925 | /* the given part to the parent */ | ||
926 | |||
927 | r = mailmime_add_part(mp, mime_sub); | ||
928 | if (r != MAILIMF_NO_ERROR) { | ||
929 | res = MAILIMF_ERROR_MEMORY; | ||
930 | goto free_saved_sub; | ||
931 | } | ||
932 | |||
933 | return MAILIMF_NO_ERROR; | ||
934 | |||
935 | free_mp: | ||
936 | mailmime_free(mp); | ||
937 | free_saved_sub: | ||
938 | mailmime_free(saved_sub); | ||
939 | err: | ||
940 | return res; | ||
941 | } | ||
942 | |||
943 | |||
944 | |||
945 | /* detach part from parent and free it only if the part has no child */ | ||
946 | |||
947 | int mailmime_smart_remove_part(struct mailmime * mime) | ||
948 | { | ||
949 | struct mailmime * parent; | ||
950 | int res; | ||
951 | |||
952 | parent = mime->mm_parent; | ||
953 | if (parent == NULL) { | ||
954 | res = MAILIMF_ERROR_INVAL; | ||
955 | goto err; | ||
956 | } | ||
957 | |||
958 | switch (mime->mm_type) { | ||
959 | case MAILMIME_MESSAGE: | ||
960 | if (mime->mm_data.mm_message.mm_msg_mime != NULL) { | ||
961 | res = MAILIMF_ERROR_INVAL; | ||
962 | goto err; | ||
963 | } | ||
964 | |||
965 | mailmime_remove_part(mime); | ||
966 | |||
967 | mailmime_free(mime); | ||
968 | |||
969 | return MAILIMF_NO_ERROR; | ||
970 | |||
971 | case MAILMIME_MULTIPLE: | ||
972 | if (!clist_isempty(mime->mm_data.mm_multipart.mm_mp_list)) { | ||
973 | res = MAILIMF_ERROR_INVAL; | ||
974 | goto err; | ||
975 | } | ||
976 | |||
977 | mailmime_remove_part(mime); | ||
978 | |||
979 | mailmime_free(mime); | ||
980 | |||
981 | return MAILIMF_NO_ERROR; | ||
982 | |||
983 | case MAILMIME_SINGLE: | ||
984 | mailmime_remove_part(mime); | ||
985 | |||
986 | mailmime_free(mime); | ||
987 | |||
988 | return MAILIMF_NO_ERROR; | ||
989 | |||
990 | default: | ||
991 | return MAILIMF_ERROR_INVAL; | ||
992 | } | ||
993 | |||
994 | err: | ||
995 | return res; | ||
996 | } | ||
997 | |||
998 | |||
999 | /* create a mailmime_content structure (Content-Type field) */ | ||
1000 | |||
1001 | struct mailmime_content * mailmime_content_new_with_str(const char * str) | ||
1002 | { | ||
1003 | int r; | ||
1004 | size_t cur_token; | ||
1005 | struct mailmime_content * content; | ||
1006 | |||
1007 | cur_token = 0; | ||
1008 | r = mailmime_content_parse(str, strlen(str), &cur_token, &content); | ||
1009 | if (r != MAILIMF_NO_ERROR) | ||
1010 | return NULL; | ||
1011 | |||
1012 | return content; | ||
1013 | } | ||
1014 | |||
1015 | /* create MIME fields with only the field Content-Transfer-Encoding */ | ||
1016 | |||
1017 | struct mailmime_fields * mailmime_fields_new_encoding(int type) | ||
1018 | { | ||
1019 | struct mailmime_mechanism * encoding; | ||
1020 | struct mailmime_fields * mime_fields; | ||
1021 | |||
1022 | encoding = mailmime_mechanism_new(type, NULL); | ||
1023 | if (encoding == NULL) | ||
1024 | goto err; | ||
1025 | |||
1026 | mime_fields = mailmime_fields_new_with_data(encoding, | ||
1027 | NULL, NULL, NULL, NULL); | ||
1028 | if (mime_fields == NULL) | ||
1029 | goto free; | ||
1030 | |||
1031 | return mime_fields; | ||
1032 | |||
1033 | free: | ||
1034 | mailmime_mechanism_free(encoding); | ||
1035 | err: | ||
1036 | return NULL; | ||
1037 | } | ||
1038 | |||
1039 | |||
1040 | /* create a multipart MIME part */ | ||
1041 | |||
1042 | struct mailmime * mailmime_multiple_new(const char * type) | ||
1043 | { | ||
1044 | struct mailmime_fields * mime_fields; | ||
1045 | struct mailmime_content * content; | ||
1046 | struct mailmime * mp; | ||
1047 | |||
1048 | mime_fields = mailmime_fields_new_encoding(MAILMIME_MECHANISM_8BIT); | ||
1049 | if (mime_fields == NULL) | ||
1050 | goto err; | ||
1051 | |||
1052 | content = mailmime_content_new_with_str(type); | ||
1053 | if (content == NULL) | ||
1054 | goto free_fields; | ||
1055 | |||
1056 | mp = mailmime_new_empty(content, mime_fields); | ||
1057 | if (mp == NULL) | ||
1058 | goto free_content; | ||
1059 | |||
1060 | return mp; | ||
1061 | |||
1062 | free_content: | ||
1063 | mailmime_content_free(content); | ||
1064 | free_fields: | ||
1065 | mailmime_fields_free(mime_fields); | ||
1066 | err: | ||
1067 | return NULL; | ||
1068 | } | ||
1069 | |||
1070 | |||
1071 | |||
1072 | void mailmime_set_imf_fields(struct mailmime * build_info, | ||
1073 | struct mailimf_fields * mm_fields) | ||
1074 | { | ||
1075 | build_info->mm_data.mm_message.mm_fields = mm_fields; | ||
1076 | } | ||
1077 | |||
1078 | #if 0 | ||
1079 | struct mailmime_content * mailmime_get_content(char * mime_type) | ||
1080 | { | ||
1081 | struct mailmime_content *content; | ||
1082 | int r; | ||
1083 | size_t cur_token; | ||
1084 | |||
1085 | cur_token = 0; | ||
1086 | r = mailmime_content_parse(mime_type, strlen(mime_type), | ||
1087 | &cur_token, &content); | ||
1088 | if (r != MAILIMF_NO_ERROR) | ||
1089 | return NULL; | ||
1090 | |||
1091 | return content; | ||
1092 | } | ||
1093 | #endif | ||
1094 | |||
1095 | |||
1096 | |||
1097 | |||
1098 | struct mailmime_disposition * | ||
1099 | mailmime_disposition_new_with_data(int type, | ||
1100 | char * filename, char * creation_date, char * modification_date, | ||
1101 | char * read_date, size_t size) | ||
1102 | { | ||
1103 | struct mailmime_disposition_type * dsp_type; | ||
1104 | clist * list; | ||
1105 | int r; | ||
1106 | struct mailmime_disposition_parm * parm; | ||
1107 | struct mailmime_disposition * dsp; | ||
1108 | |||
1109 | dsp_type = mailmime_disposition_type_new(type, NULL); | ||
1110 | if (dsp_type == NULL) | ||
1111 | goto err; | ||
1112 | |||
1113 | list = clist_new(); | ||
1114 | if (list == NULL) | ||
1115 | goto free_dsp_type; | ||
1116 | |||
1117 | if (filename != NULL) { | ||
1118 | parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_FILENAME, | ||
1119 | filename, NULL, NULL, NULL, 0, NULL); | ||
1120 | if (parm == NULL) | ||
1121 | goto free_list; | ||
1122 | |||
1123 | r = clist_append(list, parm); | ||
1124 | if (r < 0) { | ||
1125 | mailmime_disposition_parm_free(parm); | ||
1126 | goto free_list; | ||
1127 | } | ||
1128 | } | ||
1129 | |||
1130 | if (creation_date != NULL) { | ||
1131 | parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_CREATION_DATE, | ||
1132 | NULL, creation_date, NULL, NULL, 0, NULL); | ||
1133 | if (parm == NULL) | ||
1134 | goto free_list; | ||
1135 | |||
1136 | r = clist_append(list, parm); | ||
1137 | if (r < 0) { | ||
1138 | mailmime_disposition_parm_free(parm); | ||
1139 | goto free_list; | ||
1140 | } | ||
1141 | } | ||
1142 | |||
1143 | if (modification_date != NULL) { | ||
1144 | parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE, | ||
1145 | NULL, NULL, modification_date, NULL, 0, NULL); | ||
1146 | if (parm == NULL) | ||
1147 | goto free_list; | ||
1148 | |||
1149 | r = clist_append(list, parm); | ||
1150 | if (r < 0) { | ||
1151 | mailmime_disposition_parm_free(parm); | ||
1152 | goto free_list; | ||
1153 | } | ||
1154 | } | ||
1155 | |||
1156 | if (read_date != NULL) { | ||
1157 | parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_READ_DATE, | ||
1158 | NULL, NULL, NULL, read_date, 0, NULL); | ||
1159 | if (parm == NULL) | ||
1160 | goto free_list; | ||
1161 | |||
1162 | r = clist_append(list, parm); | ||
1163 | if (r < 0) { | ||
1164 | mailmime_disposition_parm_free(parm); | ||
1165 | goto free_list; | ||
1166 | } | ||
1167 | } | ||
1168 | |||
1169 | if (size != (size_t) -1) { | ||
1170 | parm = mailmime_disposition_parm_new(MAILMIME_DISPOSITION_PARM_SIZE, | ||
1171 | NULL, NULL, NULL, NULL, size, NULL); | ||
1172 | if (parm == NULL) | ||
1173 | goto free_list; | ||
1174 | |||
1175 | r = clist_append(list, parm); | ||
1176 | if (r < 0) { | ||
1177 | mailmime_disposition_parm_free(parm); | ||
1178 | goto free_list; | ||
1179 | } | ||
1180 | } | ||
1181 | |||
1182 | dsp = mailmime_disposition_new(dsp_type, list); | ||
1183 | |||
1184 | return dsp; | ||
1185 | |||
1186 | free_list: | ||
1187 | clist_foreach(list, (clist_func) mailmime_disposition_parm_free, NULL); | ||
1188 | clist_free(list); | ||
1189 | free_dsp_type: | ||
1190 | mailmime_disposition_type_free(dsp_type); | ||
1191 | err: | ||
1192 | return NULL; | ||
1193 | } | ||
1194 | |||
1195 | |||
1196 | static void mailmime_disposition_single_fields_init(struct | ||
1197 | mailmime_single_fields * single_fields, | ||
1198 | struct mailmime_disposition * fld_disposition) | ||
1199 | { | ||
1200 | clistiter * cur; | ||
1201 | |||
1202 | single_fields->fld_disposition = fld_disposition; | ||
1203 | |||
1204 | for(cur = clist_begin(fld_disposition->dsp_parms) ; cur != NULL ; | ||
1205 | cur = clist_next(cur)) { | ||
1206 | struct mailmime_disposition_parm * param; | ||
1207 | |||
1208 | param = clist_content(cur); | ||
1209 | |||
1210 | switch (param->pa_type) { | ||
1211 | case MAILMIME_DISPOSITION_PARM_FILENAME: | ||
1212 | single_fields->fld_disposition_filename = param->pa_data.pa_filename; | ||
1213 | break; | ||
1214 | |||
1215 | case MAILMIME_DISPOSITION_PARM_CREATION_DATE: | ||
1216 | single_fields->fld_disposition_creation_date = | ||
1217 | param->pa_data.pa_creation_date; | ||
1218 | break; | ||
1219 | |||
1220 | case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: | ||
1221 | single_fields->fld_disposition_modification_date = | ||
1222 | param->pa_data.pa_modification_date; | ||
1223 | break; | ||
1224 | |||
1225 | case MAILMIME_DISPOSITION_PARM_READ_DATE: | ||
1226 | single_fields->fld_disposition_read_date = | ||
1227 | param->pa_data.pa_read_date; | ||
1228 | break; | ||
1229 | |||
1230 | case MAILMIME_DISPOSITION_PARM_SIZE: | ||
1231 | single_fields->fld_disposition_size = param->pa_data.pa_size; | ||
1232 | break; | ||
1233 | } | ||
1234 | } | ||
1235 | } | ||
1236 | |||
1237 | static void mailmime_content_single_fields_init(struct | ||
1238 | mailmime_single_fields * single_fields, | ||
1239 | struct mailmime_content * fld_content) | ||
1240 | { | ||
1241 | clistiter * cur; | ||
1242 | |||
1243 | single_fields->fld_content = fld_content; | ||
1244 | |||
1245 | for(cur = clist_begin(fld_content->ct_parameters) ; | ||
1246 | cur != NULL ; cur = clist_next(cur)) { | ||
1247 | struct mailmime_parameter * param; | ||
1248 | |||
1249 | param = clist_content(cur); | ||
1250 | |||
1251 | if (strcasecmp(param->pa_name, "boundary") == 0) | ||
1252 | single_fields->fld_content_boundary = param->pa_value; | ||
1253 | |||
1254 | if (strcasecmp(param->pa_name, "charset") == 0) | ||
1255 | single_fields->fld_content_charset = param->pa_value; | ||
1256 | |||
1257 | if (strcasecmp(param->pa_name, "name") == 0) | ||
1258 | single_fields->fld_content_name = param->pa_value; | ||
1259 | } | ||
1260 | } | ||
1261 | |||
1262 | void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, | ||
1263 | struct mailmime_fields * fld_fields, | ||
1264 | struct mailmime_content * fld_content) | ||
1265 | { | ||
1266 | clistiter * cur; | ||
1267 | |||
1268 | memset(single_fields, 0, sizeof(struct mailmime_single_fields)); | ||
1269 | |||
1270 | if (fld_content != NULL) | ||
1271 | mailmime_content_single_fields_init(single_fields, fld_content); | ||
1272 | |||
1273 | if (fld_fields == NULL) | ||
1274 | return; | ||
1275 | |||
1276 | for(cur = clist_begin(fld_fields->fld_list) ; cur != NULL ; | ||
1277 | cur = clist_next(cur)) { | ||
1278 | struct mailmime_field * field; | ||
1279 | |||
1280 | field = clist_content(cur); | ||
1281 | |||
1282 | switch (field->fld_type) { | ||
1283 | case MAILMIME_FIELD_TYPE: | ||
1284 | mailmime_content_single_fields_init(single_fields, | ||
1285 | field->fld_data.fld_content); | ||
1286 | break; | ||
1287 | |||
1288 | case MAILMIME_FIELD_TRANSFER_ENCODING: | ||
1289 | single_fields->fld_encoding = field->fld_data.fld_encoding; | ||
1290 | break; | ||
1291 | |||
1292 | case MAILMIME_FIELD_ID: | ||
1293 | single_fields->fld_id = field->fld_data.fld_id; | ||
1294 | break; | ||
1295 | |||
1296 | case MAILMIME_FIELD_DESCRIPTION: | ||
1297 | single_fields->fld_description = field->fld_data.fld_description; | ||
1298 | break; | ||
1299 | |||
1300 | case MAILMIME_FIELD_VERSION: | ||
1301 | single_fields->fld_version = field->fld_data.fld_version; | ||
1302 | break; | ||
1303 | |||
1304 | case MAILMIME_FIELD_DISPOSITION: | ||
1305 | mailmime_disposition_single_fields_init(single_fields, | ||
1306 | field->fld_data.fld_disposition); | ||
1307 | break; | ||
1308 | |||
1309 | case MAILMIME_FIELD_LANGUAGE: | ||
1310 | single_fields->fld_language = field->fld_data.fld_language; | ||
1311 | break; | ||
1312 | } | ||
1313 | } | ||
1314 | } | ||
1315 | |||
1316 | struct mailmime_single_fields * | ||
1317 | mailmime_single_fields_new(struct mailmime_fields * fld_fields, | ||
1318 | struct mailmime_content * fld_content) | ||
1319 | { | ||
1320 | struct mailmime_single_fields * single_fields; | ||
1321 | |||
1322 | single_fields = malloc(sizeof(struct mailmime_single_fields)); | ||
1323 | if (single_fields == NULL) | ||
1324 | goto err; | ||
1325 | |||
1326 | mailmime_single_fields_init(single_fields, fld_fields, fld_content); | ||
1327 | |||
1328 | return single_fields; | ||
1329 | |||
1330 | err: | ||
1331 | return NULL; | ||
1332 | } | ||
1333 | |||
1334 | |||
1335 | void mailmime_single_fields_free(struct mailmime_single_fields * | ||
1336 | single_fields) | ||
1337 | { | ||
1338 | free(single_fields); | ||
1339 | } | ||
1340 | |||
1341 | struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, | ||
1342 | char * filename, int encoding_type) | ||
1343 | { | ||
1344 | struct mailmime_disposition * dsp; | ||
1345 | struct mailmime_mechanism * encoding; | ||
1346 | struct mailmime_fields * mime_fields; | ||
1347 | |||
1348 | dsp = mailmime_disposition_new_with_data(dsp_type, | ||
1349 | filename, NULL, NULL, NULL, (size_t) -1); | ||
1350 | if (dsp == NULL) | ||
1351 | goto err; | ||
1352 | |||
1353 | encoding = mailmime_mechanism_new(encoding_type, NULL); | ||
1354 | if (encoding == NULL) | ||
1355 | goto free_dsp; | ||
1356 | |||
1357 | mime_fields = mailmime_fields_new_with_data(encoding, | ||
1358 | NULL, NULL, dsp, NULL); | ||
1359 | if (mime_fields == NULL) | ||
1360 | goto free_encoding; | ||
1361 | |||
1362 | return mime_fields; | ||
1363 | |||
1364 | free_encoding: | ||
1365 | mailmime_encoding_free(encoding); | ||
1366 | free_dsp: | ||
1367 | mailmime_disposition_free(dsp); | ||
1368 | err: | ||
1369 | return NULL; | ||
1370 | } | ||
1371 | |||
1372 | struct mailmime_data * | ||
1373 | mailmime_data_new_data(int encoding, int encoded, | ||
1374 | const char * data, size_t length) | ||
1375 | { | ||
1376 | return mailmime_data_new(MAILMIME_DATA_TEXT, encoding, encoded, data, length, NULL); | ||
1377 | } | ||
1378 | |||
1379 | struct mailmime_data * | ||
1380 | mailmime_data_new_file(int encoding, int encoded, | ||
1381 | char * filename) | ||
1382 | { | ||
1383 | return mailmime_data_new(MAILMIME_DATA_FILE, encoding, encoded, NULL, 0, filename); | ||
1384 | } | ||
1385 | |||
diff --git a/kmicromail/libetpan/mime/mailmime_types_helper.h b/kmicromail/libetpan/mime/mailmime_types_helper.h new file mode 100644 index 0000000..608acca --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_types_helper.h | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #ifndef MAILMIME_TYPES_HELPER_H | ||
37 | |||
38 | #define MAILMIME_TYPES_HELPER_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <libetpan/mailmime_types.h> | ||
45 | |||
46 | int mailmime_transfer_encoding_get(struct mailmime_fields * fields); | ||
47 | |||
48 | struct mailmime_disposition * | ||
49 | mailmime_disposition_new_filename(int type, char * filename); | ||
50 | |||
51 | struct mailmime_fields * mailmime_fields_new_empty(void); | ||
52 | |||
53 | int mailmime_fields_add(struct mailmime_fields * fields, | ||
54 | struct mailmime_field * field); | ||
55 | |||
56 | struct mailmime_fields * | ||
57 | mailmime_fields_new_with_data(struct mailmime_mechanism * encoding, | ||
58 | char * id, | ||
59 | char * description, | ||
60 | struct mailmime_disposition * disposition, | ||
61 | struct mailmime_language * language); | ||
62 | |||
63 | struct mailmime_fields * | ||
64 | mailmime_fields_new_with_version(struct mailmime_mechanism * encoding, | ||
65 | char * id, | ||
66 | char * description, | ||
67 | struct mailmime_disposition * disposition, | ||
68 | struct mailmime_language * language); | ||
69 | |||
70 | struct mailmime_content * mailmime_get_content_message(void); | ||
71 | struct mailmime_content * mailmime_get_content_text(void); | ||
72 | /* struct mailmime_content * mailmime_get_content(char * mime_type); */ | ||
73 | |||
74 | #define mailmime_get_content mailmime_content_new_with_str | ||
75 | |||
76 | struct mailmime_data * | ||
77 | mailmime_data_new_data(int encoding, int encoded, | ||
78 | const char * data, size_t length); | ||
79 | |||
80 | struct mailmime_data * | ||
81 | mailmime_data_new_file(int encoding, int encoded, | ||
82 | char * filename); | ||
83 | |||
84 | #if 0 | ||
85 | struct mailmime * | ||
86 | mailmime_new_message_file(char * filename); | ||
87 | |||
88 | struct mailmime * | ||
89 | mailmime_new_message_text(char * data_str, size_t length); | ||
90 | #endif | ||
91 | |||
92 | struct mailmime * | ||
93 | mailmime_new_message_data(struct mailmime * msg_mime); | ||
94 | |||
95 | struct mailmime * | ||
96 | mailmime_new_empty(struct mailmime_content * content, | ||
97 | struct mailmime_fields * mime_fields); | ||
98 | |||
99 | int | ||
100 | mailmime_new_with_content(const char * content_type, | ||
101 | struct mailmime_fields * mime_fields, | ||
102 | struct mailmime ** result); | ||
103 | |||
104 | int mailmime_set_preamble_file(struct mailmime * build_info, | ||
105 | char * filename); | ||
106 | |||
107 | int mailmime_set_epilogue_file(struct mailmime * build_info, | ||
108 | char * filename); | ||
109 | |||
110 | int mailmime_set_preamble_text(struct mailmime * build_info, | ||
111 | char * data_str, size_t length); | ||
112 | |||
113 | int mailmime_set_epilogue_text(struct mailmime * build_info, | ||
114 | char * data_str, size_t length); | ||
115 | |||
116 | int mailmime_set_body_file(struct mailmime * build_info, | ||
117 | char * filename); | ||
118 | |||
119 | int mailmime_set_body_text(struct mailmime * build_info, | ||
120 | char * data_str, size_t length); | ||
121 | |||
122 | int mailmime_add_part(struct mailmime * build_info, | ||
123 | struct mailmime * part); | ||
124 | |||
125 | void mailmime_remove_part(struct mailmime * mime); | ||
126 | |||
127 | void mailmime_set_imf_fields(struct mailmime * build_info, | ||
128 | struct mailimf_fields * fields); | ||
129 | |||
130 | |||
131 | struct mailmime_disposition * | ||
132 | mailmime_disposition_new_with_data(int type, | ||
133 | char * filename, char * creation_date, char * modification_date, | ||
134 | char * read_date, size_t size); | ||
135 | |||
136 | void mailmime_single_fields_init(struct mailmime_single_fields * single_fields, | ||
137 | struct mailmime_fields * fld_fields, | ||
138 | struct mailmime_content * fld_content); | ||
139 | |||
140 | struct mailmime_single_fields * | ||
141 | mailmime_single_fields_new(struct mailmime_fields * fld_fields, | ||
142 | struct mailmime_content * fld_content); | ||
143 | |||
144 | void mailmime_single_fields_free(struct mailmime_single_fields * | ||
145 | single_fields); | ||
146 | |||
147 | int mailmime_smart_add_part(struct mailmime * mime, | ||
148 | struct mailmime * mime_sub); | ||
149 | |||
150 | int mailmime_smart_remove_part(struct mailmime * mime); | ||
151 | |||
152 | struct mailmime_content * mailmime_content_new_with_str(const char * str); | ||
153 | |||
154 | struct mailmime_fields * mailmime_fields_new_encoding(int type); | ||
155 | |||
156 | struct mailmime * mailmime_multiple_new(const char * type); | ||
157 | |||
158 | struct mailmime_fields * mailmime_fields_new_filename(int dsp_type, | ||
159 | char * filename, int encoding_type); | ||
160 | |||
161 | #ifdef __cplusplus | ||
162 | } | ||
163 | #endif | ||
164 | |||
165 | #endif | ||
diff --git a/kmicromail/libetpan/mime/mailmime_write.c b/kmicromail/libetpan/mime/mailmime_write.c new file mode 100644 index 0000000..5c3b1f7 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_write.c | |||
@@ -0,0 +1,1416 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #include "mailmime_write.h" | ||
37 | |||
38 | #include <stdlib.h> | ||
39 | #include <string.h> | ||
40 | #include <time.h> | ||
41 | #include <unistd.h> | ||
42 | #include <sys/types.h> | ||
43 | #include <sys/stat.h> | ||
44 | #include <fcntl.h> | ||
45 | #include <sys/mman.h> | ||
46 | |||
47 | #include "mailimf_write.h" | ||
48 | #include "mailmime_content.h" | ||
49 | #include "mailmime_types_helper.h" | ||
50 | |||
51 | #define MAX_MAIL_COL 78 | ||
52 | |||
53 | #ifndef TRUE | ||
54 | #define TRUE 1 | ||
55 | #endif | ||
56 | |||
57 | #ifndef FALSE | ||
58 | #define FALSE 0 | ||
59 | #endif | ||
60 | |||
61 | static int mailmime_field_write(FILE * f, int * col, | ||
62 | struct mailmime_field * field); | ||
63 | |||
64 | static int mailmime_id_write(FILE * f, int * col, char * id); | ||
65 | |||
66 | static int mailmime_description_write(FILE * f, int * col, char * descr); | ||
67 | |||
68 | static int mailmime_version_write(FILE * f, int * col, uint32_t version); | ||
69 | |||
70 | static int mailmime_encoding_write(FILE * f, int * col, | ||
71 | struct mailmime_mechanism * encoding); | ||
72 | |||
73 | static int mailmime_language_write(FILE * f, int * col, | ||
74 | struct mailmime_language * language); | ||
75 | |||
76 | static int mailmime_disposition_write(FILE * f, int * col, | ||
77 | struct mailmime_disposition * | ||
78 | disposition); | ||
79 | |||
80 | static int | ||
81 | mailmime_disposition_param_write(FILE * f, int * col, | ||
82 | struct mailmime_disposition_parm * param); | ||
83 | |||
84 | static int mailmime_parameter_write(FILE * f, int * col, | ||
85 | struct mailmime_parameter * param); | ||
86 | |||
87 | /* | ||
88 | static int mailmime_content_write(FILE * f, int * col, | ||
89 | struct mailmime_content * content); | ||
90 | */ | ||
91 | |||
92 | static int mailmime_type_write(FILE * f, int * col, | ||
93 | struct mailmime_type * type); | ||
94 | |||
95 | static int | ||
96 | mailmime_discrete_type_write(FILE * f, int * col, | ||
97 | struct mailmime_discrete_type * discrete_type); | ||
98 | |||
99 | static int | ||
100 | mailmime_composite_type_write(FILE * f, int * col, | ||
101 | struct mailmime_composite_type * composite_type); | ||
102 | |||
103 | static int mailmime_sub_write(FILE * f, int * col, | ||
104 | struct mailmime * build_info); | ||
105 | |||
106 | |||
107 | /* ***** */ | ||
108 | |||
109 | int mailmime_fields_write(FILE * f, int * col, struct mailmime_fields * fields) | ||
110 | { | ||
111 | int r; | ||
112 | clistiter * cur; | ||
113 | |||
114 | for(cur = clist_begin(fields->fld_list) ; cur != NULL ; | ||
115 | cur = clist_next(cur)) { | ||
116 | struct mailmime_field * field; | ||
117 | |||
118 | field = cur->data; | ||
119 | r = mailmime_field_write(f, col, field); | ||
120 | if (r != MAILIMF_NO_ERROR) | ||
121 | return r; | ||
122 | } | ||
123 | |||
124 | return MAILIMF_NO_ERROR; | ||
125 | } | ||
126 | |||
127 | static int mailmime_field_write(FILE * f, int * col, | ||
128 | struct mailmime_field * field) | ||
129 | { | ||
130 | int r; | ||
131 | |||
132 | switch (field->fld_type) { | ||
133 | case MAILMIME_FIELD_TYPE: | ||
134 | r = mailmime_content_write(f, col, field->fld_data.fld_content); | ||
135 | break; | ||
136 | |||
137 | case MAILMIME_FIELD_TRANSFER_ENCODING: | ||
138 | r = mailmime_encoding_write(f, col, field->fld_data.fld_encoding); | ||
139 | break; | ||
140 | |||
141 | case MAILMIME_FIELD_ID: | ||
142 | r = mailmime_id_write(f, col, field->fld_data.fld_id); | ||
143 | break; | ||
144 | |||
145 | case MAILMIME_FIELD_DESCRIPTION: | ||
146 | r = mailmime_description_write(f, col, field->fld_data.fld_description); | ||
147 | break; | ||
148 | |||
149 | case MAILMIME_FIELD_VERSION: | ||
150 | r = mailmime_version_write(f, col, field->fld_data.fld_version); | ||
151 | break; | ||
152 | |||
153 | case MAILMIME_FIELD_DISPOSITION: | ||
154 | r = mailmime_disposition_write(f, col, field->fld_data.fld_disposition); | ||
155 | break; | ||
156 | |||
157 | case MAILMIME_FIELD_LANGUAGE: | ||
158 | r = mailmime_language_write(f, col, field->fld_data.fld_language); | ||
159 | break; | ||
160 | |||
161 | default: | ||
162 | r = MAILIMF_ERROR_INVAL; | ||
163 | break; | ||
164 | } | ||
165 | |||
166 | if (r != MAILIMF_NO_ERROR) | ||
167 | return r; | ||
168 | |||
169 | return MAILIMF_NO_ERROR; | ||
170 | } | ||
171 | |||
172 | static int mailmime_id_write(FILE * f, int * col, char * id) | ||
173 | { | ||
174 | int r; | ||
175 | |||
176 | r = mailimf_string_write(f, col, "Content-ID: ", 12); | ||
177 | if (r != MAILIMF_NO_ERROR) | ||
178 | return r; | ||
179 | |||
180 | r = mailimf_string_write(f, col, "<", 1); | ||
181 | if (r != MAILIMF_NO_ERROR) | ||
182 | return r; | ||
183 | |||
184 | r = mailimf_string_write(f, col, id, strlen(id)); | ||
185 | if (r != MAILIMF_NO_ERROR) | ||
186 | return r; | ||
187 | |||
188 | r = mailimf_string_write(f, col, ">", 1); | ||
189 | if (r != MAILIMF_NO_ERROR) | ||
190 | return r; | ||
191 | |||
192 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
193 | if (r != MAILIMF_NO_ERROR) | ||
194 | return r; | ||
195 | #if 0 | ||
196 | * col = 0; | ||
197 | #endif | ||
198 | |||
199 | return MAILIMF_NO_ERROR; | ||
200 | } | ||
201 | |||
202 | static int mailmime_description_write(FILE * f, int * col, char * descr) | ||
203 | { | ||
204 | int r; | ||
205 | |||
206 | r = mailimf_string_write(f, col, "Content-Description: ", 21); | ||
207 | if (r != MAILIMF_NO_ERROR) | ||
208 | return r; | ||
209 | |||
210 | r = mailimf_string_write(f, col, descr, strlen(descr)); | ||
211 | if (r != MAILIMF_NO_ERROR) | ||
212 | return r; | ||
213 | |||
214 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
215 | if (r != MAILIMF_NO_ERROR) | ||
216 | return r; | ||
217 | #if 0 | ||
218 | * col = 0; | ||
219 | #endif | ||
220 | |||
221 | return MAILIMF_NO_ERROR; | ||
222 | } | ||
223 | |||
224 | static int mailmime_version_write(FILE * f, int * col, uint32_t version) | ||
225 | { | ||
226 | int r; | ||
227 | char versionstr[40]; | ||
228 | |||
229 | r = mailimf_string_write(f, col, "MIME-Version: ", 14); | ||
230 | if (r != MAILIMF_NO_ERROR) | ||
231 | return r; | ||
232 | |||
233 | snprintf(versionstr, 40, "%i.%i", version >> 16, version & 0xFFFF); | ||
234 | |||
235 | r = mailimf_string_write(f, col, versionstr, strlen(versionstr)); | ||
236 | if (r != MAILIMF_NO_ERROR) | ||
237 | return r; | ||
238 | |||
239 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
240 | if (r != MAILIMF_NO_ERROR) | ||
241 | return r; | ||
242 | #if 0 | ||
243 | * col = 0; | ||
244 | #endif | ||
245 | |||
246 | return MAILIMF_NO_ERROR; | ||
247 | } | ||
248 | |||
249 | static int mailmime_encoding_write(FILE * f, int * col, | ||
250 | struct mailmime_mechanism * encoding) | ||
251 | { | ||
252 | int r; | ||
253 | |||
254 | r = mailimf_string_write(f, col, "Content-Transfer-Encoding: ", 27); | ||
255 | if (r != MAILIMF_NO_ERROR) | ||
256 | return r; | ||
257 | |||
258 | switch (encoding->enc_type) { | ||
259 | case MAILMIME_MECHANISM_7BIT: | ||
260 | r = mailimf_string_write(f, col, "7bit", 4); | ||
261 | break; | ||
262 | |||
263 | case MAILMIME_MECHANISM_8BIT: | ||
264 | r = mailimf_string_write(f, col, "8bit", 4); | ||
265 | break; | ||
266 | |||
267 | case MAILMIME_MECHANISM_BINARY: | ||
268 | r = mailimf_string_write(f, col, "binary", 6); | ||
269 | break; | ||
270 | |||
271 | case MAILMIME_MECHANISM_QUOTED_PRINTABLE: | ||
272 | r = mailimf_string_write(f, col, "quoted-printable", 16); | ||
273 | break; | ||
274 | |||
275 | case MAILMIME_MECHANISM_BASE64: | ||
276 | r = mailimf_string_write(f, col, "base64", 6); | ||
277 | break; | ||
278 | |||
279 | case MAILMIME_MECHANISM_TOKEN: | ||
280 | r = mailimf_string_write(f, col, encoding->enc_token, | ||
281 | strlen(encoding->enc_token)); | ||
282 | break; | ||
283 | |||
284 | default: | ||
285 | r = MAILIMF_ERROR_INVAL; | ||
286 | break; | ||
287 | } | ||
288 | |||
289 | if (r != MAILIMF_NO_ERROR) | ||
290 | return r; | ||
291 | |||
292 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
293 | if (r != MAILIMF_NO_ERROR) | ||
294 | return r; | ||
295 | #if 0 | ||
296 | * col = 0; | ||
297 | #endif | ||
298 | |||
299 | return MAILIMF_NO_ERROR; | ||
300 | } | ||
301 | |||
302 | static int mailmime_language_write(FILE * f, int * col, | ||
303 | struct mailmime_language * language) | ||
304 | { | ||
305 | int r; | ||
306 | clistiter * cur; | ||
307 | int first; | ||
308 | |||
309 | r = mailimf_string_write(f, col, "Content-Language: ", 18); | ||
310 | if (r != MAILIMF_NO_ERROR) | ||
311 | return r; | ||
312 | |||
313 | first = TRUE; | ||
314 | |||
315 | for(cur = clist_begin(language->lg_list) ; cur != NULL ; | ||
316 | cur = clist_next(cur)) { | ||
317 | char * lang; | ||
318 | size_t len; | ||
319 | |||
320 | lang = clist_content(cur); | ||
321 | len = strlen(lang); | ||
322 | |||
323 | if (!first) { | ||
324 | r = mailimf_string_write(f, col, ", ", 2); | ||
325 | if (r != MAILIMF_NO_ERROR) | ||
326 | return r; | ||
327 | } | ||
328 | else { | ||
329 | first = FALSE; | ||
330 | } | ||
331 | |||
332 | if (* col > 1) { | ||
333 | |||
334 | if (* col + len > MAX_MAIL_COL) { | ||
335 | r = mailimf_string_write(f, col, "\r\n ", 3); | ||
336 | if (r != MAILIMF_NO_ERROR) | ||
337 | return r; | ||
338 | #if 0 | ||
339 | * col = 1; | ||
340 | #endif | ||
341 | } | ||
342 | } | ||
343 | |||
344 | r = mailimf_string_write(f, col, lang, len); | ||
345 | if (r != MAILIMF_NO_ERROR) | ||
346 | return r; | ||
347 | } | ||
348 | |||
349 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
350 | if (r != MAILIMF_NO_ERROR) | ||
351 | return r; | ||
352 | #if 0 | ||
353 | * col = 0; | ||
354 | #endif | ||
355 | |||
356 | return MAILIMF_NO_ERROR; | ||
357 | } | ||
358 | |||
359 | static int mailmime_disposition_write(FILE * f, int * col, | ||
360 | struct mailmime_disposition * | ||
361 | disposition) | ||
362 | { | ||
363 | struct mailmime_disposition_type * dsp_type; | ||
364 | int r; | ||
365 | clistiter * cur; | ||
366 | |||
367 | dsp_type = disposition->dsp_type; | ||
368 | |||
369 | r = mailimf_string_write(f, col, "Content-Disposition: ", 21); | ||
370 | if (r != MAILIMF_NO_ERROR) | ||
371 | return r; | ||
372 | |||
373 | switch (dsp_type->dsp_type) { | ||
374 | case MAILMIME_DISPOSITION_TYPE_INLINE: | ||
375 | r = mailimf_string_write(f, col, "inline", 6); | ||
376 | break; | ||
377 | |||
378 | case MAILMIME_DISPOSITION_TYPE_ATTACHMENT: | ||
379 | r = mailimf_string_write(f, col, "attachment", 10); | ||
380 | break; | ||
381 | |||
382 | case MAILMIME_DISPOSITION_TYPE_EXTENSION: | ||
383 | r = mailimf_string_write(f, col, dsp_type->dsp_extension, | ||
384 | strlen(dsp_type->dsp_extension)); | ||
385 | break; | ||
386 | |||
387 | default: | ||
388 | r = MAILIMF_ERROR_INVAL; | ||
389 | break; | ||
390 | } | ||
391 | |||
392 | if (r != MAILIMF_NO_ERROR) | ||
393 | return r; | ||
394 | |||
395 | for(cur = clist_begin(disposition->dsp_parms) ; | ||
396 | cur != NULL ; cur = clist_next(cur)) { | ||
397 | struct mailmime_disposition_parm * param; | ||
398 | |||
399 | param = cur->data; | ||
400 | |||
401 | r = mailimf_string_write(f, col, "; ", 2); | ||
402 | if (r != MAILIMF_NO_ERROR) | ||
403 | return r; | ||
404 | |||
405 | r = mailmime_disposition_param_write(f, col, param); | ||
406 | if (r != MAILIMF_NO_ERROR) | ||
407 | return r; | ||
408 | } | ||
409 | |||
410 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
411 | if (r != MAILIMF_NO_ERROR) | ||
412 | return r; | ||
413 | |||
414 | return MAILIMF_NO_ERROR; | ||
415 | } | ||
416 | |||
417 | static int | ||
418 | mailmime_disposition_param_write(FILE * f, int * col, | ||
419 | struct mailmime_disposition_parm * param) | ||
420 | { | ||
421 | size_t len; | ||
422 | char sizestr[20]; | ||
423 | int r; | ||
424 | |||
425 | switch (param->pa_type) { | ||
426 | case MAILMIME_DISPOSITION_PARM_FILENAME: | ||
427 | len = strlen("filename=") + strlen(param->pa_data.pa_filename); | ||
428 | break; | ||
429 | |||
430 | case MAILMIME_DISPOSITION_PARM_CREATION_DATE: | ||
431 | len = strlen("creation-date=") + strlen(param->pa_data.pa_creation_date); | ||
432 | break; | ||
433 | |||
434 | case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: | ||
435 | len = strlen("modification-date=") + | ||
436 | strlen(param->pa_data.pa_modification_date); | ||
437 | break; | ||
438 | |||
439 | case MAILMIME_DISPOSITION_PARM_READ_DATE: | ||
440 | len = strlen("read-date=") + strlen(param->pa_data.pa_read_date); | ||
441 | break; | ||
442 | |||
443 | case MAILMIME_DISPOSITION_PARM_SIZE: | ||
444 | snprintf(sizestr, 20, "%u", param->pa_data.pa_size); | ||
445 | len = strlen("size=") + strlen(sizestr); | ||
446 | break; | ||
447 | |||
448 | case MAILMIME_DISPOSITION_PARM_PARAMETER: | ||
449 | len = strlen(param->pa_data.pa_parameter->pa_name) + 1 + | ||
450 | strlen(param->pa_data.pa_parameter->pa_value); | ||
451 | break; | ||
452 | |||
453 | default: | ||
454 | return MAILIMF_ERROR_INVAL; | ||
455 | } | ||
456 | |||
457 | if (* col > 1) { | ||
458 | |||
459 | if (* col + len > MAX_MAIL_COL) { | ||
460 | r = mailimf_string_write(f, col, "\r\n ", 3); | ||
461 | if (r != MAILIMF_NO_ERROR) | ||
462 | return r; | ||
463 | #if 0 | ||
464 | * col = 1; | ||
465 | #endif | ||
466 | } | ||
467 | } | ||
468 | |||
469 | switch (param->pa_type) { | ||
470 | case MAILMIME_DISPOSITION_PARM_FILENAME: | ||
471 | r = mailimf_string_write(f, col, "filename=", 9); | ||
472 | if (r != MAILIMF_NO_ERROR) | ||
473 | return r; | ||
474 | |||
475 | r = mailimf_quoted_string_write(f, col, | ||
476 | param->pa_data.pa_filename, strlen(param->pa_data.pa_filename)); | ||
477 | if (r != MAILIMF_NO_ERROR) | ||
478 | return r; | ||
479 | break; | ||
480 | |||
481 | case MAILMIME_DISPOSITION_PARM_CREATION_DATE: | ||
482 | r = mailimf_string_write(f, col, "creation-date=", 14); | ||
483 | if (r != MAILIMF_NO_ERROR) | ||
484 | return r; | ||
485 | |||
486 | r = mailimf_quoted_string_write(f, col, param->pa_data.pa_creation_date, | ||
487 | strlen(param->pa_data.pa_creation_date)); | ||
488 | if (r != MAILIMF_NO_ERROR) | ||
489 | return r; | ||
490 | break; | ||
491 | |||
492 | case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE: | ||
493 | r = mailimf_string_write(f, col, "modification-date=", 18); | ||
494 | if (r != MAILIMF_NO_ERROR) | ||
495 | return r; | ||
496 | |||
497 | r = mailimf_quoted_string_write(f, col, | ||
498 | param->pa_data.pa_modification_date, | ||
499 | strlen(param->pa_data.pa_modification_date)); | ||
500 | if (r != MAILIMF_NO_ERROR) | ||
501 | return r; | ||
502 | break; | ||
503 | |||
504 | case MAILMIME_DISPOSITION_PARM_READ_DATE: | ||
505 | r = mailimf_string_write(f, col, "read-date=", 10); | ||
506 | if (r != MAILIMF_NO_ERROR) | ||
507 | return r; | ||
508 | |||
509 | r = mailimf_quoted_string_write(f, col, param->pa_data.pa_read_date, | ||
510 | strlen(param->pa_data.pa_read_date)); | ||
511 | if (r != MAILIMF_NO_ERROR) | ||
512 | return r; | ||
513 | break; | ||
514 | |||
515 | case MAILMIME_DISPOSITION_PARM_SIZE: | ||
516 | r = mailimf_string_write(f, col, "size=", 5); | ||
517 | if (r != MAILIMF_NO_ERROR) | ||
518 | return r; | ||
519 | |||
520 | r = mailimf_string_write(f, col, sizestr, strlen(sizestr)); | ||
521 | if (r != MAILIMF_NO_ERROR) | ||
522 | return r; | ||
523 | break; | ||
524 | |||
525 | case MAILMIME_DISPOSITION_PARM_PARAMETER: | ||
526 | r = mailmime_parameter_write(f, col, param->pa_data.pa_parameter); | ||
527 | if (r != MAILIMF_NO_ERROR) | ||
528 | return r; | ||
529 | break; | ||
530 | } | ||
531 | |||
532 | return MAILIMF_NO_ERROR; | ||
533 | } | ||
534 | |||
535 | static int mailmime_parameter_write(FILE * f, int * col, | ||
536 | struct mailmime_parameter * param) | ||
537 | { | ||
538 | int r; | ||
539 | |||
540 | r = mailimf_string_write(f, col, param->pa_name, | ||
541 | strlen(param->pa_name)); | ||
542 | if (r != MAILIMF_NO_ERROR) | ||
543 | return r; | ||
544 | |||
545 | r = mailimf_string_write(f, col, "=", 1); | ||
546 | if (r != MAILIMF_NO_ERROR) | ||
547 | return r; | ||
548 | |||
549 | r = mailimf_quoted_string_write(f, col, param->pa_value, | ||
550 | strlen(param->pa_value)); | ||
551 | if (r != MAILIMF_NO_ERROR) | ||
552 | return r; | ||
553 | |||
554 | return MAILIMF_NO_ERROR; | ||
555 | } | ||
556 | |||
557 | int mailmime_content_type_write(FILE * f, int * col, | ||
558 | struct mailmime_content * content) | ||
559 | { | ||
560 | clistiter * cur; | ||
561 | size_t len; | ||
562 | int r; | ||
563 | |||
564 | r = mailmime_type_write(f, col, content->ct_type); | ||
565 | if (r != MAILIMF_NO_ERROR) | ||
566 | return r; | ||
567 | |||
568 | r = mailimf_string_write(f, col, "/", 1); | ||
569 | if (r != MAILIMF_NO_ERROR) | ||
570 | return r; | ||
571 | |||
572 | r = mailimf_string_write(f, col, content->ct_subtype, | ||
573 | strlen(content->ct_subtype)); | ||
574 | if (r != MAILIMF_NO_ERROR) | ||
575 | return r; | ||
576 | |||
577 | if (content->ct_parameters != NULL) { | ||
578 | for(cur = clist_begin(content->ct_parameters) ; | ||
579 | cur != NULL ; cur = clist_next(cur)) { | ||
580 | struct mailmime_parameter * param; | ||
581 | |||
582 | param = cur->data; | ||
583 | |||
584 | r = mailimf_string_write(f, col, "; ", 2); | ||
585 | if (r != MAILIMF_NO_ERROR) | ||
586 | return r; | ||
587 | |||
588 | len = strlen(param->pa_name) + 1 + strlen(param->pa_value); | ||
589 | |||
590 | if (* col > 1) { | ||
591 | |||
592 | if (* col + len > MAX_MAIL_COL) { | ||
593 | r = mailimf_string_write(f, col, "\r\n ", 3); | ||
594 | if (r != MAILIMF_NO_ERROR) | ||
595 | return r; | ||
596 | #if 0 | ||
597 | * col = 1; | ||
598 | #endif | ||
599 | } | ||
600 | } | ||
601 | |||
602 | r = mailmime_parameter_write(f, col, param); | ||
603 | if (r != MAILIMF_NO_ERROR) | ||
604 | return r; | ||
605 | } | ||
606 | } | ||
607 | |||
608 | return MAILIMF_NO_ERROR; | ||
609 | } | ||
610 | |||
611 | int mailmime_content_write(FILE * f, int * col, | ||
612 | struct mailmime_content * content) | ||
613 | { | ||
614 | int r; | ||
615 | |||
616 | r = mailimf_string_write(f, col, "Content-Type: ", 14); | ||
617 | if (r != MAILIMF_NO_ERROR) | ||
618 | return r; | ||
619 | |||
620 | r = mailmime_content_type_write(f, col, content); | ||
621 | if (r != MAILIMF_NO_ERROR) | ||
622 | return r; | ||
623 | |||
624 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
625 | if (r != MAILIMF_NO_ERROR) | ||
626 | return r; | ||
627 | |||
628 | return MAILIMF_NO_ERROR; | ||
629 | } | ||
630 | |||
631 | static int mailmime_type_write(FILE * f, int * col, | ||
632 | struct mailmime_type * type) | ||
633 | { | ||
634 | int r; | ||
635 | |||
636 | switch (type->tp_type) { | ||
637 | case MAILMIME_TYPE_DISCRETE_TYPE: | ||
638 | r = mailmime_discrete_type_write(f, col, type->tp_data.tp_discrete_type); | ||
639 | break; | ||
640 | |||
641 | case MAILMIME_TYPE_COMPOSITE_TYPE: | ||
642 | r = mailmime_composite_type_write(f, col, type->tp_data.tp_composite_type); | ||
643 | break; | ||
644 | |||
645 | default: | ||
646 | r = MAILIMF_ERROR_INVAL; | ||
647 | break; | ||
648 | } | ||
649 | |||
650 | if (r != MAILIMF_NO_ERROR) | ||
651 | return r; | ||
652 | |||
653 | return MAILIMF_NO_ERROR; | ||
654 | } | ||
655 | |||
656 | static int | ||
657 | mailmime_discrete_type_write(FILE * f, int * col, | ||
658 | struct mailmime_discrete_type * discrete_type) | ||
659 | { | ||
660 | int r; | ||
661 | |||
662 | switch (discrete_type->dt_type) { | ||
663 | case MAILMIME_DISCRETE_TYPE_TEXT: | ||
664 | r = mailimf_string_write(f, col, "text", 4); | ||
665 | break; | ||
666 | |||
667 | case MAILMIME_DISCRETE_TYPE_IMAGE: | ||
668 | r = mailimf_string_write(f, col, "image", 5); | ||
669 | break; | ||
670 | |||
671 | case MAILMIME_DISCRETE_TYPE_AUDIO: | ||
672 | r = mailimf_string_write(f, col, "audio", 5); | ||
673 | break; | ||
674 | |||
675 | case MAILMIME_DISCRETE_TYPE_VIDEO: | ||
676 | r = mailimf_string_write(f, col, "video", 5); | ||
677 | break; | ||
678 | |||
679 | case MAILMIME_DISCRETE_TYPE_APPLICATION: | ||
680 | r = mailimf_string_write(f, col, "application", 11); | ||
681 | break; | ||
682 | |||
683 | case MAILMIME_DISCRETE_TYPE_EXTENSION: | ||
684 | r = mailimf_string_write(f, col, discrete_type->dt_extension, | ||
685 | strlen(discrete_type->dt_extension)); | ||
686 | break; | ||
687 | |||
688 | default: | ||
689 | r = MAILIMF_ERROR_INVAL; | ||
690 | break; | ||
691 | } | ||
692 | |||
693 | if (r != MAILIMF_NO_ERROR) | ||
694 | return r; | ||
695 | |||
696 | return MAILIMF_NO_ERROR; | ||
697 | } | ||
698 | |||
699 | static int | ||
700 | mailmime_composite_type_write(FILE * f, int * col, | ||
701 | struct mailmime_composite_type * composite_type) | ||
702 | { | ||
703 | int r; | ||
704 | |||
705 | switch (composite_type->ct_type) { | ||
706 | case MAILMIME_COMPOSITE_TYPE_MESSAGE: | ||
707 | r = mailimf_string_write(f, col, "message", 7); | ||
708 | break; | ||
709 | |||
710 | case MAILMIME_COMPOSITE_TYPE_MULTIPART: | ||
711 | r = mailimf_string_write(f, col, "multipart", 9); | ||
712 | break; | ||
713 | |||
714 | case MAILMIME_COMPOSITE_TYPE_EXTENSION: | ||
715 | r = mailimf_string_write(f, col, composite_type->ct_token, | ||
716 | strlen(composite_type->ct_token)); | ||
717 | break; | ||
718 | |||
719 | default: | ||
720 | r = MAILIMF_ERROR_INVAL; | ||
721 | break; | ||
722 | } | ||
723 | |||
724 | if (r != MAILIMF_NO_ERROR) | ||
725 | return r; | ||
726 | |||
727 | return MAILIMF_NO_ERROR; | ||
728 | } | ||
729 | |||
730 | |||
731 | |||
732 | |||
733 | /* ****************************************************************** */ | ||
734 | /* message */ | ||
735 | |||
736 | /* | ||
737 | static int mailmime_data_write(FILE * f, int * col, | ||
738 | struct mailmime_data * data, | ||
739 | int is_text); | ||
740 | */ | ||
741 | |||
742 | static int mailmime_text_content_write(FILE * f, int * col, int encoding, | ||
743 | int istext, | ||
744 | const char * text, size_t size); | ||
745 | |||
746 | /* | ||
747 | static int mailmime_base64_write(FILE * f, int * col, | ||
748 | char * text, size_t size); | ||
749 | |||
750 | static int mailmime_quoted_printable_write(FILE * f, int * col, int istext, | ||
751 | char * text, size_t size); | ||
752 | */ | ||
753 | |||
754 | static int mailmime_part_write(FILE * f, int * col, | ||
755 | struct mailmime * build_info) | ||
756 | { | ||
757 | clistiter * cur; | ||
758 | int first; | ||
759 | int r; | ||
760 | char * boundary; | ||
761 | int istext; | ||
762 | |||
763 | istext = TRUE; | ||
764 | boundary = NULL; | ||
765 | |||
766 | if (build_info->mm_content_type != NULL) { | ||
767 | if (build_info->mm_type == MAILMIME_MULTIPLE) { | ||
768 | boundary = mailmime_extract_boundary(build_info->mm_content_type); | ||
769 | if (boundary == NULL) | ||
770 | return MAILIMF_ERROR_INVAL; | ||
771 | } | ||
772 | |||
773 | if (build_info->mm_content_type->ct_type->tp_type == | ||
774 | MAILMIME_TYPE_DISCRETE_TYPE) { | ||
775 | if (build_info->mm_content_type->ct_type->tp_data.tp_discrete_type->dt_type != | ||
776 | MAILMIME_DISCRETE_TYPE_TEXT) | ||
777 | istext = FALSE; | ||
778 | } | ||
779 | } | ||
780 | |||
781 | switch (build_info->mm_type) { | ||
782 | case MAILMIME_SINGLE: | ||
783 | |||
784 | /* 1-part body */ | ||
785 | |||
786 | if (build_info->mm_data.mm_single != NULL) { | ||
787 | r = mailmime_data_write(f, col, build_info->mm_data.mm_single, istext); | ||
788 | if (r != MAILIMF_NO_ERROR) | ||
789 | return r; | ||
790 | } | ||
791 | |||
792 | break; | ||
793 | |||
794 | case MAILMIME_MULTIPLE: | ||
795 | |||
796 | /* multi-part */ | ||
797 | |||
798 | |||
799 | /* preamble */ | ||
800 | |||
801 | if (build_info->mm_data.mm_multipart.mm_preamble != NULL) { | ||
802 | r = mailmime_data_write(f, col, | ||
803 | build_info->mm_data.mm_multipart.mm_preamble, TRUE); | ||
804 | if (r != MAILIMF_NO_ERROR) | ||
805 | return r; | ||
806 | |||
807 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
808 | if (r != MAILIMF_NO_ERROR) | ||
809 | return r; | ||
810 | #if 0 | ||
811 | * col = 0; | ||
812 | #endif | ||
813 | } | ||
814 | |||
815 | /* sub-parts */ | ||
816 | |||
817 | first = TRUE; | ||
818 | |||
819 | for(cur = clist_begin(build_info->mm_data.mm_multipart.mm_mp_list) ; | ||
820 | cur != NULL ; cur = clist_next(cur)) { | ||
821 | struct mailmime * subpart; | ||
822 | |||
823 | subpart = cur->data; | ||
824 | |||
825 | if (!first) { | ||
826 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
827 | if (r != MAILIMF_NO_ERROR) | ||
828 | return r; | ||
829 | #if 0 | ||
830 | * col = 0; | ||
831 | #endif | ||
832 | } | ||
833 | else { | ||
834 | first = FALSE; | ||
835 | } | ||
836 | |||
837 | r = mailimf_string_write(f, col, "--", 2); | ||
838 | if (r != MAILIMF_NO_ERROR) | ||
839 | return r; | ||
840 | |||
841 | r = mailimf_string_write(f, col, boundary, strlen(boundary)); | ||
842 | if (r != MAILIMF_NO_ERROR) | ||
843 | return r; | ||
844 | |||
845 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
846 | if (r != MAILIMF_NO_ERROR) | ||
847 | return r; | ||
848 | #if 0 | ||
849 | * col = 0; | ||
850 | #endif | ||
851 | |||
852 | r = mailmime_sub_write(f, col, subpart); | ||
853 | if (r != MAILIMF_NO_ERROR) | ||
854 | return r; | ||
855 | } | ||
856 | |||
857 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
858 | if (r != MAILIMF_NO_ERROR) | ||
859 | return r; | ||
860 | #if 0 | ||
861 | * col = 0; | ||
862 | #endif | ||
863 | |||
864 | r = mailimf_string_write(f, col, "--", 2); | ||
865 | if (r != MAILIMF_NO_ERROR) | ||
866 | return r; | ||
867 | |||
868 | r = mailimf_string_write(f, col, boundary, strlen(boundary)); | ||
869 | if (r != MAILIMF_NO_ERROR) | ||
870 | return r; | ||
871 | |||
872 | r = mailimf_string_write(f, col, "--", 2); | ||
873 | if (r != MAILIMF_NO_ERROR) | ||
874 | return r; | ||
875 | |||
876 | |||
877 | /* epilogue */ | ||
878 | |||
879 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
880 | if (r != MAILIMF_NO_ERROR) | ||
881 | return r; | ||
882 | #if 0 | ||
883 | * col = 0; | ||
884 | #endif | ||
885 | |||
886 | if (build_info->mm_data.mm_multipart.mm_epilogue != NULL) { | ||
887 | r = mailmime_data_write(f, col, | ||
888 | build_info->mm_data.mm_multipart.mm_epilogue, TRUE); | ||
889 | if (r != MAILIMF_NO_ERROR) | ||
890 | return r; | ||
891 | } | ||
892 | |||
893 | break; | ||
894 | |||
895 | case MAILMIME_MESSAGE: | ||
896 | |||
897 | if (build_info->mm_data.mm_message.mm_fields != NULL) { | ||
898 | r = mailimf_fields_write(f, col, | ||
899 | build_info->mm_data.mm_message.mm_fields); | ||
900 | if (r != MAILIMF_NO_ERROR) | ||
901 | return r; | ||
902 | } | ||
903 | |||
904 | if (build_info->mm_mime_fields != NULL) { | ||
905 | r = mailmime_fields_write(f, col, build_info->mm_mime_fields); | ||
906 | if (r != MAILIMF_NO_ERROR) | ||
907 | return r; | ||
908 | } | ||
909 | |||
910 | /* encapsuled message */ | ||
911 | |||
912 | if (build_info->mm_data.mm_message.mm_msg_mime != NULL) { | ||
913 | r = mailmime_sub_write(f, col, | ||
914 | build_info->mm_data.mm_message.mm_msg_mime); | ||
915 | if (r != MAILIMF_NO_ERROR) | ||
916 | return r; | ||
917 | } | ||
918 | break; | ||
919 | |||
920 | } | ||
921 | |||
922 | return MAILIMF_NO_ERROR; | ||
923 | } | ||
924 | |||
925 | |||
926 | static int mailmime_sub_write(FILE * f, int * col, | ||
927 | struct mailmime * build_info) | ||
928 | { | ||
929 | int r; | ||
930 | |||
931 | #if 0 | ||
932 | * col = 0; | ||
933 | #endif | ||
934 | /* MIME field - Content-Type */ | ||
935 | |||
936 | if (build_info->mm_content_type != NULL) { | ||
937 | r = mailmime_content_write(f, col, build_info->mm_content_type); | ||
938 | if (r != MAILIMF_NO_ERROR) | ||
939 | return r; | ||
940 | } | ||
941 | |||
942 | /* other MIME fields */ | ||
943 | |||
944 | if (build_info->mm_type != MAILMIME_MESSAGE) { | ||
945 | if (build_info->mm_mime_fields != NULL) { | ||
946 | r = mailmime_fields_write(f, col, build_info->mm_mime_fields); | ||
947 | if (r != MAILIMF_NO_ERROR) | ||
948 | return r; | ||
949 | } | ||
950 | } | ||
951 | |||
952 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
953 | if (r != MAILIMF_NO_ERROR) | ||
954 | return r; | ||
955 | #if 0 | ||
956 | * col = 0; | ||
957 | #endif | ||
958 | |||
959 | return mailmime_part_write(f, col, build_info); | ||
960 | } | ||
961 | |||
962 | int mailmime_write(FILE * f, int * col, | ||
963 | struct mailmime * build_info) | ||
964 | { | ||
965 | if (build_info->mm_parent != NULL) | ||
966 | return mailmime_sub_write(f, col, build_info); | ||
967 | else | ||
968 | return mailmime_part_write(f, col, build_info); | ||
969 | } | ||
970 | |||
971 | |||
972 | int mailmime_data_write(FILE * f, int * col, | ||
973 | struct mailmime_data * data, | ||
974 | int istext) | ||
975 | { | ||
976 | int fd; | ||
977 | int r; | ||
978 | char * text; | ||
979 | struct stat buf; | ||
980 | int res; | ||
981 | |||
982 | switch (data->dt_type) { | ||
983 | case MAILMIME_DATA_TEXT: | ||
984 | |||
985 | if (data->dt_encoded) { | ||
986 | r = mailimf_string_write(f, col, | ||
987 | data->dt_data.dt_text.dt_data, | ||
988 | data->dt_data.dt_text.dt_length); | ||
989 | if (r != MAILIMF_NO_ERROR) | ||
990 | return r; | ||
991 | } | ||
992 | else { | ||
993 | r = mailmime_text_content_write(f, col, data->dt_encoding, istext, | ||
994 | data->dt_data.dt_text.dt_data, | ||
995 | data->dt_data.dt_text.dt_length); | ||
996 | if (r != MAILIMF_NO_ERROR) | ||
997 | return r; | ||
998 | } | ||
999 | |||
1000 | break; | ||
1001 | |||
1002 | case MAILMIME_DATA_FILE: | ||
1003 | fd = open(data->dt_data.dt_filename, O_RDONLY); | ||
1004 | if (fd < 0) { | ||
1005 | res = MAILIMF_ERROR_FILE; | ||
1006 | goto err; | ||
1007 | } | ||
1008 | |||
1009 | r = fstat(fd, &buf); | ||
1010 | if (r < 0) { | ||
1011 | res = MAILIMF_ERROR_FILE; | ||
1012 | goto close; | ||
1013 | } | ||
1014 | |||
1015 | if (buf.st_size != 0) { | ||
1016 | text = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); | ||
1017 | if (text == NULL) { | ||
1018 | res = MAILIMF_ERROR_FILE; | ||
1019 | goto close; | ||
1020 | } | ||
1021 | |||
1022 | if (data->dt_encoded) { | ||
1023 | r = mailimf_string_write(f, col, text, buf.st_size); | ||
1024 | if (r != MAILIMF_NO_ERROR) { | ||
1025 | res = r; | ||
1026 | goto unmap; | ||
1027 | } | ||
1028 | } | ||
1029 | else { | ||
1030 | r = mailmime_text_content_write(f, col, data->dt_encoding, istext, | ||
1031 | text, buf.st_size); | ||
1032 | if (r != MAILIMF_NO_ERROR) { | ||
1033 | res = r; | ||
1034 | goto unmap; | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1038 | munmap(text, buf.st_size); | ||
1039 | } | ||
1040 | close(fd); | ||
1041 | |||
1042 | if (r != MAILIMF_NO_ERROR) | ||
1043 | return r; | ||
1044 | |||
1045 | break; | ||
1046 | |||
1047 | unmap: | ||
1048 | munmap(text, buf.st_size); | ||
1049 | close: | ||
1050 | close(fd); | ||
1051 | err: | ||
1052 | return res; | ||
1053 | } | ||
1054 | |||
1055 | return MAILIMF_NO_ERROR; | ||
1056 | } | ||
1057 | |||
1058 | static int mailmime_text_content_write(FILE * f, int * col, int encoding, | ||
1059 | int istext, | ||
1060 | const char * text, size_t size) | ||
1061 | { | ||
1062 | switch (encoding) { | ||
1063 | case MAILMIME_MECHANISM_QUOTED_PRINTABLE: | ||
1064 | return mailmime_quoted_printable_write(f, col, istext, text, size); | ||
1065 | break; | ||
1066 | |||
1067 | case MAILMIME_MECHANISM_BASE64: | ||
1068 | return mailmime_base64_write(f, col, text, size); | ||
1069 | break; | ||
1070 | |||
1071 | case MAILMIME_MECHANISM_7BIT: | ||
1072 | case MAILMIME_MECHANISM_8BIT: | ||
1073 | case MAILMIME_MECHANISM_BINARY: | ||
1074 | default: | ||
1075 | return mailimf_string_write(f, col, text, size); | ||
1076 | } | ||
1077 | } | ||
1078 | |||
1079 | |||
1080 | static const char base64_encoding[] = | ||
1081 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | ||
1082 | |||
1083 | #define BASE64_MAX_COL 76 | ||
1084 | |||
1085 | int mailmime_base64_write(FILE * f, int * col, | ||
1086 | const char * text, size_t size) | ||
1087 | { | ||
1088 | int a; | ||
1089 | int b; | ||
1090 | int c; | ||
1091 | size_t remains; | ||
1092 | const char * p; | ||
1093 | size_t count; | ||
1094 | char ogroup[4]; | ||
1095 | int r; | ||
1096 | |||
1097 | remains = size; | ||
1098 | p = text; | ||
1099 | |||
1100 | while (remains > 0) { | ||
1101 | switch (remains) { | ||
1102 | case 1: | ||
1103 | a = (unsigned char) p[0]; | ||
1104 | b = 0; | ||
1105 | c = 0; | ||
1106 | count = 1; | ||
1107 | break; | ||
1108 | case 2: | ||
1109 | a = (unsigned char) p[0]; | ||
1110 | b = (unsigned char) p[1]; | ||
1111 | c = 0; | ||
1112 | count = 2; | ||
1113 | break; | ||
1114 | default: | ||
1115 | a = (unsigned char) p[0]; | ||
1116 | b = (unsigned char) p[1]; | ||
1117 | c = (unsigned char) p[2]; | ||
1118 | count = 3; | ||
1119 | break; | ||
1120 | } | ||
1121 | |||
1122 | ogroup[0]= base64_encoding[a >> 2]; | ||
1123 | ogroup[1]= base64_encoding[((a & 3) << 4) | (b >> 4)]; | ||
1124 | ogroup[2]= base64_encoding[((b & 0xF) << 2) | (c >> 6)]; | ||
1125 | ogroup[3]= base64_encoding[c & 0x3F]; | ||
1126 | |||
1127 | switch (count) { | ||
1128 | case 1: | ||
1129 | ogroup[2]= '='; | ||
1130 | ogroup[3]= '='; | ||
1131 | break; | ||
1132 | case 2: | ||
1133 | ogroup[3]= '='; | ||
1134 | break; | ||
1135 | } | ||
1136 | |||
1137 | if (* col + 4 > BASE64_MAX_COL) { | ||
1138 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
1139 | if (r != MAILIMF_NO_ERROR) | ||
1140 | return r; | ||
1141 | #if 0 | ||
1142 | * col = 0; | ||
1143 | #endif | ||
1144 | } | ||
1145 | |||
1146 | r = mailimf_string_write(f, col, ogroup, 4); | ||
1147 | if (r != MAILIMF_NO_ERROR) | ||
1148 | return r; | ||
1149 | |||
1150 | remains -= count; | ||
1151 | p += count; | ||
1152 | } | ||
1153 | |||
1154 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
1155 | |||
1156 | return MAILIMF_NO_ERROR; | ||
1157 | } | ||
1158 | |||
1159 | #if 0 | ||
1160 | #define MAX_WRITE_SIZE 512 | ||
1161 | #endif | ||
1162 | |||
1163 | enum { | ||
1164 | STATE_INIT, | ||
1165 | STATE_CR, | ||
1166 | STATE_SPACE, | ||
1167 | STATE_SPACE_CR, | ||
1168 | }; | ||
1169 | |||
1170 | #if 0 | ||
1171 | static inline int write_try_buf(FILE * f, int * col, | ||
1172 | char ** pstart, size_t * plen) | ||
1173 | { | ||
1174 | int r; | ||
1175 | |||
1176 | if (* plen >= MAX_WRITE_SIZE) { | ||
1177 | r = mailimf_string_write(f, col, * pstart, * plen); | ||
1178 | if (r != MAILIMF_NO_ERROR) | ||
1179 | return r; | ||
1180 | * plen = 0; | ||
1181 | } | ||
1182 | |||
1183 | return MAILIMF_NO_ERROR; | ||
1184 | } | ||
1185 | #endif | ||
1186 | |||
1187 | static inline int write_remaining(FILE * f, int * col, | ||
1188 | const char ** pstart, size_t * plen) | ||
1189 | { | ||
1190 | int r; | ||
1191 | |||
1192 | if (* plen > 0) { | ||
1193 | r = mailimf_string_write(f, col, * pstart, * plen); | ||
1194 | if (r != MAILIMF_NO_ERROR) | ||
1195 | return r; | ||
1196 | * plen = 0; | ||
1197 | } | ||
1198 | |||
1199 | return MAILIMF_NO_ERROR; | ||
1200 | } | ||
1201 | |||
1202 | |||
1203 | |||
1204 | #define QP_MAX_COL 72 | ||
1205 | |||
1206 | int mailmime_quoted_printable_write(FILE * f, int * col, int istext, | ||
1207 | const char * text, size_t size) | ||
1208 | { | ||
1209 | size_t i; | ||
1210 | const char * start; | ||
1211 | size_t len; | ||
1212 | char hexstr[6]; | ||
1213 | int r; | ||
1214 | int state; | ||
1215 | |||
1216 | start = text; | ||
1217 | len = 0; | ||
1218 | state = STATE_INIT; | ||
1219 | |||
1220 | i = 0; | ||
1221 | while (i < size) { | ||
1222 | unsigned char ch; | ||
1223 | |||
1224 | if (* col + len > QP_MAX_COL) { | ||
1225 | r = write_remaining(f, col, &start, &len); | ||
1226 | if (r != MAILIMF_NO_ERROR) | ||
1227 | return r; | ||
1228 | start = text + i; | ||
1229 | |||
1230 | r = mailimf_string_write(f, col, "=\r\n", 3); | ||
1231 | if (r != MAILIMF_NO_ERROR) | ||
1232 | return r; | ||
1233 | } | ||
1234 | |||
1235 | ch = text[i]; | ||
1236 | |||
1237 | switch (state) { | ||
1238 | |||
1239 | case STATE_INIT: | ||
1240 | switch (ch) { | ||
1241 | case ' ': | ||
1242 | case '\t': | ||
1243 | state = STATE_SPACE; | ||
1244 | break; | ||
1245 | |||
1246 | case '\r': | ||
1247 | state = STATE_CR; | ||
1248 | break; | ||
1249 | |||
1250 | case '!': | ||
1251 | case '"': | ||
1252 | case '#': | ||
1253 | case '$': | ||
1254 | case '@': | ||
1255 | case '[': | ||
1256 | case '\\': | ||
1257 | case ']': | ||
1258 | case '^': | ||
1259 | case '`': | ||
1260 | case '{': | ||
1261 | case '|': | ||
1262 | case '}': | ||
1263 | case '~': | ||
1264 | case '=': | ||
1265 | case '?': | ||
1266 | case '_': | ||
1267 | case 'F': /* there is no more 'From' at the beginning of a line */ | ||
1268 | r = write_remaining(f, col, &start, &len); | ||
1269 | if (r != MAILIMF_NO_ERROR) | ||
1270 | return r; | ||
1271 | start = text + i + 1; | ||
1272 | |||
1273 | snprintf(hexstr, 6, "=%02X", ch); | ||
1274 | |||
1275 | r = mailimf_string_write(f, col, hexstr, 3); | ||
1276 | if (r != MAILIMF_NO_ERROR) | ||
1277 | return r; | ||
1278 | break; | ||
1279 | |||
1280 | default: | ||
1281 | if (istext && (ch == '\n')) { | ||
1282 | r = write_remaining(f, col, &start, &len); | ||
1283 | if (r != MAILIMF_NO_ERROR) | ||
1284 | return r; | ||
1285 | start = text + i + 1; | ||
1286 | |||
1287 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
1288 | if (r != MAILIMF_NO_ERROR) | ||
1289 | return r; | ||
1290 | break; | ||
1291 | } | ||
1292 | else { | ||
1293 | if (((ch >= 33) && (ch <= 60)) || ((ch >= 62) && (ch <= 126))) { | ||
1294 | len ++; | ||
1295 | } | ||
1296 | else { | ||
1297 | r = write_remaining(f, col, &start, &len); | ||
1298 | if (r != MAILIMF_NO_ERROR) | ||
1299 | return r; | ||
1300 | start = text + i + 1; | ||
1301 | |||
1302 | snprintf(hexstr, 6, "=%02X", ch); | ||
1303 | |||
1304 | r = mailimf_string_write(f, col, hexstr, 3); | ||
1305 | if (r != MAILIMF_NO_ERROR) | ||
1306 | return r; | ||
1307 | } | ||
1308 | } | ||
1309 | |||
1310 | break; | ||
1311 | } | ||
1312 | |||
1313 | i ++; | ||
1314 | break; | ||
1315 | |||
1316 | case STATE_CR: | ||
1317 | switch (ch) { | ||
1318 | case '\n': | ||
1319 | r = write_remaining(f, col, &start, &len); | ||
1320 | if (r != MAILIMF_NO_ERROR) | ||
1321 | return r; | ||
1322 | start = text + i + 1; | ||
1323 | r = mailimf_string_write(f, col, "\r\n", 2); | ||
1324 | if (r != MAILIMF_NO_ERROR) | ||
1325 | return r; | ||
1326 | i ++; | ||
1327 | state = STATE_INIT; | ||
1328 | break; | ||
1329 | |||
1330 | default: | ||
1331 | r = write_remaining(f, col, &start, &len); | ||
1332 | if (r != MAILIMF_NO_ERROR) | ||
1333 | return r; | ||
1334 | start = text + i; | ||
1335 | snprintf(hexstr, 6, "=%02X", '\r'); | ||
1336 | r = mailimf_string_write(f, col, hexstr, 3); | ||
1337 | if (r != MAILIMF_NO_ERROR) | ||
1338 | return r; | ||
1339 | state = STATE_INIT; | ||
1340 | break; | ||
1341 | } | ||
1342 | break; | ||
1343 | |||
1344 | case STATE_SPACE: | ||
1345 | switch (ch) { | ||
1346 | case '\r': | ||
1347 | state = STATE_SPACE_CR; | ||
1348 | i ++; | ||
1349 | break; | ||
1350 | |||
1351 | case '\n': | ||
1352 | r = write_remaining(f, col, &start, &len); | ||
1353 | if (r != MAILIMF_NO_ERROR) | ||
1354 | return r; | ||
1355 | start = text + i + 1; | ||
1356 | snprintf(hexstr, 6, "=%02X\r\n", text[i - 1]); | ||
1357 | r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); | ||
1358 | if (r != MAILIMF_NO_ERROR) | ||
1359 | return r; | ||
1360 | state = STATE_INIT; | ||
1361 | i ++; | ||
1362 | break; | ||
1363 | |||
1364 | case ' ': | ||
1365 | case '\t': | ||
1366 | len ++; | ||
1367 | i ++; | ||
1368 | break; | ||
1369 | |||
1370 | default: | ||
1371 | #if 0 | ||
1372 | len += 2; | ||
1373 | state = STATE_INIT; | ||
1374 | i ++; | ||
1375 | #endif | ||
1376 | len ++; | ||
1377 | state = STATE_INIT; | ||
1378 | break; | ||
1379 | } | ||
1380 | |||
1381 | break; | ||
1382 | |||
1383 | case STATE_SPACE_CR: | ||
1384 | switch (ch) { | ||
1385 | case '\n': | ||
1386 | r = write_remaining(f, col, &start, &len); | ||
1387 | if (r != MAILIMF_NO_ERROR) | ||
1388 | return r; | ||
1389 | start = text + i + 1; | ||
1390 | snprintf(hexstr, 6, "=%02X\r\n", text[i - 2]); | ||
1391 | r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); | ||
1392 | if (r != MAILIMF_NO_ERROR) | ||
1393 | return r; | ||
1394 | state = STATE_INIT; | ||
1395 | i ++; | ||
1396 | break; | ||
1397 | |||
1398 | default: | ||
1399 | r = write_remaining(f, col, &start, &len); | ||
1400 | if (r != MAILIMF_NO_ERROR) | ||
1401 | return r; | ||
1402 | start = text + i + 1; | ||
1403 | snprintf(hexstr, 6, "%c=%02X", text[i - 2], '\r'); | ||
1404 | r = mailimf_string_write(f, col, hexstr, strlen(hexstr)); | ||
1405 | if (r != MAILIMF_NO_ERROR) | ||
1406 | return r; | ||
1407 | state = STATE_INIT; | ||
1408 | break; | ||
1409 | } | ||
1410 | |||
1411 | break; | ||
1412 | } | ||
1413 | } | ||
1414 | |||
1415 | return MAILIMF_NO_ERROR; | ||
1416 | } | ||
diff --git a/kmicromail/libetpan/mime/mailmime_write.h b/kmicromail/libetpan/mime/mailmime_write.h new file mode 100644 index 0000000..96f8777 --- a/dev/null +++ b/kmicromail/libetpan/mime/mailmime_write.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * libEtPan! -- a mail stuff library | ||
3 | * | ||
4 | * Copyright (C) 2001, 2002 - DINH Viet Hoa | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. Neither the name of the libEtPan! project nor the names of its | ||
16 | * contributors may be used to endorse or promote products derived | ||
17 | * from this software without specific prior written permission. | ||
18 | * | ||
19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
29 | * SUCH DAMAGE. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * $Id$ | ||
34 | */ | ||
35 | |||
36 | #ifndef MAILMIME_WRITE_H | ||
37 | |||
38 | #define MAILMIME_WRITE_H | ||
39 | |||
40 | #ifdef __cplusplus | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | #include <libetpan/mailmime_types.h> | ||
45 | #include <stdio.h> | ||
46 | |||
47 | int mailmime_fields_write(FILE * f, int * col, | ||
48 | struct mailmime_fields * fields); | ||
49 | |||
50 | int mailmime_content_write(FILE * f, int * col, | ||
51 | struct mailmime_content * content); | ||
52 | |||
53 | int mailmime_content_type_write(FILE * f, int * col, | ||
54 | struct mailmime_content * content); | ||
55 | |||
56 | int mailmime_write(FILE * f, int * col, | ||
57 | struct mailmime * build_info); | ||
58 | |||
59 | int mailmime_quoted_printable_write(FILE * f, int * col, int istext, | ||
60 | const char * text, size_t size); | ||
61 | |||
62 | int mailmime_base64_write(FILE * f, int * col, | ||
63 | const char * text, size_t size); | ||
64 | |||
65 | int mailmime_data_write(FILE * f, int * col, | ||
66 | struct mailmime_data * data, | ||
67 | int istext); | ||
68 | |||
69 | #ifdef __cplusplus | ||
70 | } | ||
71 | #endif | ||
72 | |||
73 | #endif | ||