author | zautrix <zautrix> | 2004-07-03 16:33:12 (UTC) |
---|---|---|
committer | zautrix <zautrix> | 2004-07-03 16:33:12 (UTC) |
commit | e3b89230f065c48c84b48c88edb6eb088374c487 (patch) (unidiff) | |
tree | 162ea2ef909a6f82ccfcedf45d80d6c821174912 /kmicromail/libetpan/mime/mailmime_content.c | |
parent | 2dd6ac0b2d24c91d35ce674a6c26351352df2b15 (diff) | |
download | kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.zip kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.gz kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.bz2 |
Initial revision
Diffstat (limited to 'kmicromail/libetpan/mime/mailmime_content.c') (more/less context) (show whitespace changes)
-rw-r--r-- | kmicromail/libetpan/mime/mailmime_content.c | 2164 |
1 files changed, 2164 insertions, 0 deletions
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 | } | ||