summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/mime
authorzautrix <zautrix>2004-07-03 16:33:12 (UTC)
committer zautrix <zautrix>2004-07-03 16:33:12 (UTC)
commite3b89230f065c48c84b48c88edb6eb088374c487 (patch) (unidiff)
tree162ea2ef909a6f82ccfcedf45d80d6c821174912 /kmicromail/libetpan/mime
parent2dd6ac0b2d24c91d35ce674a6c26351352df2b15 (diff)
downloadkdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.zip
kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.gz
kdepimpi-e3b89230f065c48c84b48c88edb6eb088374c487.tar.bz2
Initial revision
Diffstat (limited to 'kmicromail/libetpan/mime') (more/less context) (show whitespace changes)
-rw-r--r--kmicromail/libetpan/mime/.libs/libmailmime.abin0 -> 192784 bytes
-rw-r--r--kmicromail/libetpan/mime/TODO10
-rw-r--r--kmicromail/libetpan/mime/mailmime.c1408
-rw-r--r--kmicromail/libetpan/mime/mailmime.h100
-rw-r--r--kmicromail/libetpan/mime/mailmime_content.c2164
-rw-r--r--kmicromail/libetpan/mime/mailmime_content.h89
-rw-r--r--kmicromail/libetpan/mime/mailmime_decode.c533
-rw-r--r--kmicromail/libetpan/mime/mailmime_decode.h55
-rw-r--r--kmicromail/libetpan/mime/mailmime_disposition.c595
-rw-r--r--kmicromail/libetpan/mime/mailmime_disposition.h62
-rw-r--r--kmicromail/libetpan/mime/mailmime_types.c750
-rw-r--r--kmicromail/libetpan/mime/mailmime_types.h440
-rw-r--r--kmicromail/libetpan/mime/mailmime_types_helper.c1385
-rw-r--r--kmicromail/libetpan/mime/mailmime_types_helper.h165
-rw-r--r--kmicromail/libetpan/mime/mailmime_write.c1416
-rw-r--r--kmicromail/libetpan/mime/mailmime_write.h73
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
70static int mailmime_attribute_parse(const char * message, size_t length,
71 size_t * index,
72 char ** result);
73static int
74mailmime_composite_type_parse(const char * message, size_t length,
75 size_t * index,
76 struct mailmime_composite_type ** result);
77
78static int is_text(char ch);
79
80static int
81mailmime_discrete_type_parse(const char * message, size_t length,
82 size_t * index,
83 struct mailmime_discrete_type ** result);
84
85static int mailmime_mechanism_parse(const char * message, size_t length,
86 size_t * index,
87 struct mailmime_mechanism ** result);
88
89static int mailmime_subtype_parse(const char * message, size_t length,
90 size_t * index, char ** result);
91
92static int is_token(char ch);
93
94static int mailmime_token_parse(const char * message, size_t length,
95 size_t * index,
96 char ** token);
97
98static int is_tspecials(char ch);
99
100static int mailmime_type_parse(const char * message, size_t length,
101 size_t * index,
102 struct mailmime_type ** result);
103
104/*
105int mailmime_version_parse(const char * message, guint32 length,
106 guint32 * index,
107 guint32 * result);
108*/
109
110/*
111static gboolean mailmime_x_token_parse(gconst char * message, guint32 length,
112 guint32 * index,
113 gchar ** result);
114*/
115
116/* ********************************************************************** */
117
118/*
119x attribute := token
120 ; Matching of attributes
121 ; is ALWAYS case-insensitive.
122*/
123
124static 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/*
132x composite-type := "message" / "multipart" / extension-token
133*/
134
135static int
136mailmime_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/*
189x content := "Content-Type" ":" type "/" subtype
190 *(";" parameter)
191 ; Matching of media type and subtype
192 ; is ALWAYS case-insensitive.
193*/
194
195int 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, &parameter);
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/*
309x description := "Content-Description" ":" *text
310*/
311
312static 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
325int 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/*
335x discrete-type := "text" / "image" / "audio" / "video" /
336 "application" / extension-token
337*/
338
339/* currently porting */
340
341static int
342mailmime_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/*
422x encoding := "Content-Transfer-Encoding" ":" mechanism
423*/
424
425int 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/*
433x entity-headers := [ content CRLF ]
434 [ encoding CRLF ]
435 [ id CRLF ]
436 [ description CRLF ]
437 *( MIME-extension-field CRLF )
438 */
439
440enum {
441 FIELD_STATE_START,
442 FIELD_STATE_T,
443 FIELD_STATE_D
444};
445
446static 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
507int
508mailmime_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/*
628x extension-token := ietf-token / x-token
629*/
630
631int
632mailmime_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/*
647x 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/*
653x ietf-token := <An extension token defined by a
654 standards-track RFC and registered
655 with IANA.>
656*/
657
658/*
659x id := "Content-ID" ":" msg-id
660*/
661
662int 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/*
669x mechanism := "7bit" / "8bit" / "binary" /
670 "quoted-printable" / "base64" /
671 ietf-token / x-token
672*/
673
674static 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/*
753x MIME-extension-field := <Any RFC 822 header field which
754 begins with the string
755 "Content-">
756*/
757
758/*
759in headers
760
761x 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/*
770in message
771
772x 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
783int
784mailmime_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
845int
846mailmime_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/*
914x parameter := attribute "=" value
915*/
916
917int 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/*
1008x subtype := extension-token / iana-token
1009*/
1010
1011static 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/*
1018x token := 1*<any (US-ASCII) CHAR except SPACE, CTLs,
1019 or tspecials>
1020*/
1021
1022static 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
1039static 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/*
1058enum {
1059 LWSP_1,
1060 LWSP_2,
1061 LWSP_3,
1062 LWSP_4,
1063 LWSP_OK
1064};
1065
1066gboolean 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/*
1137x tspecials := "(" / ")" / "<" / ">" / "@" /
1138 "," / ";" / ":" / "\" / <">
1139 "/" / "[" / "]" / "?" / "="
1140 ; Must be in quoted-string,
1141 ; to use within parameter values
1142*/
1143
1144static 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/*
1169x type := discrete-type / composite-type
1170*/
1171
1172static 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/*
1229x value := token / quoted-string
1230*/
1231
1232int 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/*
1249x version := "MIME-Version" ":" 1*DIGIT "." 1*DIGIT
1250*/
1251
1252int 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/*
1289x x-token := <The two characters "X-" or "x-" followed, with
1290 no intervening white space, by any token>
1291*/
1292
1293/*
1294static 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
1336int 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
41extern "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
52int mailmime_content_parse(const char * message, size_t length,
53 size_t * index,
54 struct mailmime_content ** result);
55
56int mailmime_description_parse(const char * message, size_t length,
57 size_t * index,
58 char ** result);
59
60int mailmime_encoding_parse(const char * message, size_t length,
61 size_t * index,
62 struct mailmime_mechanism ** result);
63
64int
65mailmime_field_parse(struct mailimf_optional_field * field,
66 struct mailmime_field ** result);
67
68int mailmime_id_parse(const char * message, size_t length,
69 size_t * index, char ** result);
70
71int
72mailmime_fields_parse(struct mailimf_fields *
73 fields,
74 struct mailmime_fields **
75 result);
76
77int mailmime_version_parse(const char * message, size_t length,
78 size_t * index,
79 uint32_t * result);
80
81int
82mailmime_extension_token_parse(const char * message, size_t length,
83 size_t * index, char ** result);
84
85int mailmime_parameter_parse(const char * message, size_t length,
86 size_t * index,
87 struct mailmime_parameter ** result);
88
89int mailmime_value_parse(const char * message, size_t length,
90 size_t * index, char ** result);
91
92int 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
62static 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
70char * 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
81char * 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/*
2005.2.3.3. The 'anon-ftp' Access-Type
201*/
202
203/*
2045.2.3.4. The 'local-file' Access-Type
205NAME
206SITE
207*/
208
209/*
2105.2.3.5. The 'mail-server' Access-Type
211SERVER
212SUBJECT
213*/
214
215
216enum {
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
226static 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
346static 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
369static int is_wsp(char ch)
370{
371 if ((ch == ' ') || (ch == '\t'))
372 return TRUE;
373
374 return FALSE;
375}
376
377static 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/*
402gboolean mailimf_crlf_parse(gchar * message, guint32 length, guint32 * index)
403*/
404
405enum {
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
415static int
416mailmime_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
542enum {
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
550static 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
639enum {
640 MULTIPART_NEXT_STATE_0,
641 MULTIPART_NEXT_STATE_1,
642 MULTIPART_NEXT_STATE_2
643};
644
645int 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
699static int
700mailmime_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
1062enum {
1063 MAILMIME_DEFAULT_TYPE_TEXT_PLAIN,
1064 MAILMIME_DEFAULT_TYPE_MESSAGE
1065};
1066
1067
1068int 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
1135char * 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
1163static 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
1211static 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
1470static 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
1527int 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
1552static 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
1572int 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
1675static 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
1686static inline char to_char(const char * hexa)
1687{
1688 return (hexa_to_char(hexa[0]) << 4) | hexa_to_char(hexa[1]);
1689}
1690
1691enum {
1692 STATE_NORMAL,
1693 STATE_CODED,
1694 STATE_OUT,
1695 STATE_CR,
1696};
1697
1698
1699static 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
1711int 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
2010int 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
2055int 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
2077int 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, &section_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
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46char * mailmime_content_charset_get(struct mailmime_content * content);
47
48char * mailmime_content_param_get(struct mailmime_content * content,
49 char * name);
50
51int mailmime_parse(const char * message, size_t length,
52 size_t * index, struct mailmime ** result);
53
54int mailmime_get_section(struct mailmime * mime,
55 struct mailmime_section * section,
56 struct mailmime ** result);
57
58
59char * mailmime_extract_boundary(struct mailmime_content * content_type);
60
61
62/* decode */
63
64int mailmime_base64_body_parse(const char * message, size_t length,
65 size_t * index, char ** result,
66 size_t * result_len);
67
68int 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
73int mailmime_binary_body_parse(const char * message, size_t length,
74 size_t * index, char ** result,
75 size_t * result_len);
76
77int mailmime_part_parse(const char * message, size_t length,
78 size_t * index,
79 int encoding, char ** result, size_t * result_len);
80
81
82int 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
63static int mailmime_charset_parse(const char * message, size_t length,
64 size_t * index, char ** charset);
65
66enum {
67 MAILMIME_ENCODING_B,
68 MAILMIME_ENCODING_Q
69};
70
71static int mailmime_encoding_parse(const char * message, size_t length,
72 size_t * index, int * result);
73
74static int mailmime_etoken_parse(const char * message, size_t length,
75 size_t * index, char ** result);
76
77static int
78mailmime_non_encoded_word_parse(const char * message, size_t length,
79 size_t * index,
80 char ** result);
81
82static int
83mailmime_encoded_word_parse(const char * message, size_t length,
84 size_t * index,
85 struct mailmime_encoded_word ** result);
86
87
88enum {
89 TYPE_ERROR,
90 TYPE_WORD,
91 TYPE_ENCODED_WORD,
92};
93
94int 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
236static int
237mailmime_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
301static 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
461static 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
467static 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
497int 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
527static 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
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46int 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
42static int
43mailmime_disposition_parm_parse(const char * message, size_t length,
44 size_t * index,
45 struct mailmime_disposition_parm **
46 result);
47
48static int
49mailmime_creation_date_parm_parse(const char * message, size_t length,
50 size_t * index, char ** result);
51
52static int
53mailmime_filename_parm_parse(const char * message, size_t length,
54 size_t * index, char ** result);
55
56static int
57mailmime_modification_date_parm_parse(const char * message, size_t length,
58 size_t * index, char ** result);
59
60static int
61mailmime_read_date_parm_parse(const char * message, size_t length,
62 size_t * index, char ** result);
63
64static int
65mailmime_size_parm_parse(const char * message, size_t length,
66 size_t * index, size_t * result);
67
68static int
69mailmime_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
80int 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, &param);
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
173int
174mailmime_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
248int 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
270static int
271mailmime_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 &parameter);
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
423static int
424mailmime_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
456static int
457mailmime_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
489static int
490mailmime_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
522static int
523mailmime_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
555static int
556mailmime_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
590static int
591mailmime_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
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46int mailmime_disposition_parse(const char * message, size_t length,
47 size_t * index,
48 struct mailmime_disposition ** result);
49
50int
51mailmime_disposition_type_parse(const char * message, size_t length,
52 size_t * index,
53 struct mailmime_disposition_type ** result);
54
55int 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
42void mailmime_attribute_free(char * attribute)
43{
44 mailmime_token_free(attribute);
45}
46
47
48
49struct mailmime_composite_type *
50mailmime_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
64void 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
72struct mailmime_content *
73mailmime_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
90void 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
104void mailmime_description_free(char * description)
105{
106 free(description);
107}
108
109struct mailmime_discrete_type *
110mailmime_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
124void 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
131void mailmime_encoding_free(struct mailmime_mechanism * encoding)
132{
133 mailmime_mechanism_free(encoding);
134}
135
136void mailmime_extension_token_free(char * extension)
137{
138 mailmime_token_free(extension);
139}
140
141void mailmime_id_free(char * id)
142{
143 mailimf_msg_id_free(id);
144}
145
146struct 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
160void 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
167struct mailmime_parameter *
168mailmime_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
182void 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
190void mailmime_subtype_free(char * subtype)
191{
192 mailmime_extension_token_free(subtype);
193}
194
195
196void mailmime_token_free(char * token)
197{
198 free(token);
199}
200
201
202struct mailmime_type *
203mailmime_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
226void 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
239void mailmime_value_free(char * value)
240{
241 free(value);
242}
243
244
245/*
246void mailmime_x_token_free(gchar * x_token)
247{
248 g_free(x_token);
249}
250*/
251
252struct mailmime_field *
253mailmime_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
295void 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
327struct 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
340void 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/*
349struct mailmime_body_part *
350mailmime_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
364void mailmime_body_part_free(struct mailmime_body_part * body_part)
365{
366 g_free(body_part);
367}
368*/
369
370struct mailmime_multipart_body *
371mailmime_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
384void 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
394struct 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
459void 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
495struct mailmime_encoded_word *
496mailmime_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
509void mailmime_charset_free(char * charset)
510{
511 free(charset);
512}
513
514void mailmime_encoded_text_free(char * text)
515{
516 free(text);
517}
518
519void 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
531struct mailmime_disposition *
532mailmime_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
546void 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
557struct mailmime_disposition_type *
558mailmime_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
572void 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
580struct mailmime_disposition_parm *
581mailmime_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
620void 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
645void mailmime_filename_parm_free(char * filename)
646{
647 mailmime_value_free(filename);
648}
649
650void mailmime_creation_date_parm_free(char * date)
651{
652 mailmime_quoted_date_time_free(date);
653}
654
655void mailmime_modification_date_parm_free(char * date)
656{
657 mailmime_quoted_date_time_free(date);
658}
659
660void mailmime_read_date_parm_free(char * date)
661{
662 mailmime_quoted_date_time_free(date);
663}
664
665void mailmime_quoted_date_time_free(char * date)
666{
667 mailimf_quoted_string_free(date);
668}
669
670struct 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
683void 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
692struct 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
705void 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
712void mailmime_decoded_part_free(char * part)
713{
714 mmap_string_unref(part);
715}
716
717struct 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
742void 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
41extern "C" {
42#endif
43
44#include <inttypes.h>
45#include <libetpan/mailimf.h>
46#include <libetpan/clist.h>
47
48enum {
49 MAILMIME_COMPOSITE_TYPE_ERROR,
50 MAILMIME_COMPOSITE_TYPE_MESSAGE,
51 MAILMIME_COMPOSITE_TYPE_MULTIPART,
52 MAILMIME_COMPOSITE_TYPE_EXTENSION
53};
54
55struct mailmime_composite_type {
56 int ct_type;
57 char * ct_token;
58};
59
60
61struct mailmime_content {
62 struct mailmime_type * ct_type;
63 char * ct_subtype;
64 clist * ct_parameters; /* elements are (struct mailmime_parameter *) */
65};
66
67
68enum {
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
78struct mailmime_discrete_type {
79 int dt_type;
80 char * dt_extension;
81};
82
83enum {
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
94struct 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
107enum {
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
117struct mailmime_mechanism {
118 int enc_type;
119 char * enc_token;
120};
121
122
123struct mailmime_fields {
124 clist * fld_list; /* list of (struct mailmime_field *) */
125};
126
127
128struct mailmime_parameter {
129 char * pa_name;
130 char * pa_value;
131};
132
133enum {
134 MAILMIME_TYPE_ERROR,
135 MAILMIME_TYPE_DISCRETE_TYPE,
136 MAILMIME_TYPE_COMPOSITE_TYPE
137};
138
139struct 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
147void mailmime_attribute_free(char * attribute);
148
149struct mailmime_composite_type *
150mailmime_composite_type_new(int ct_type, char * ct_token);
151
152void mailmime_composite_type_free(struct mailmime_composite_type * ct);
153
154struct mailmime_content *
155mailmime_content_new(struct mailmime_type * ct_type,
156 char * ct_subtype,
157 clist * ct_parameters);
158
159void mailmime_content_free(struct mailmime_content * content);
160
161void mailmime_description_free(char * description);
162
163struct mailmime_discrete_type *
164mailmime_discrete_type_new(int dt_type, char * dt_extension);
165
166void mailmime_discrete_type_free(struct mailmime_discrete_type *
167 discrete_type);
168
169void mailmime_encoding_free(struct mailmime_mechanism * encoding);
170
171void mailmime_extension_token_free(char * extension);
172
173void mailmime_id_free(char * id);
174
175struct mailmime_mechanism * mailmime_mechanism_new(int enc_type, char * enc_token);
176
177void mailmime_mechanism_free(struct mailmime_mechanism * mechanism);
178
179struct mailmime_parameter *
180mailmime_parameter_new(char * pa_name, char * pa_value);
181
182void mailmime_parameter_free(struct mailmime_parameter * parameter);
183
184void mailmime_subtype_free(char * subtype);
185
186void mailmime_token_free(char * token);
187
188struct mailmime_type *
189mailmime_type_new(int tp_type,
190 struct mailmime_discrete_type * tp_discrete_type,
191 struct mailmime_composite_type * tp_composite_type);
192
193void mailmime_type_free(struct mailmime_type * type);
194
195void mailmime_value_free(char * value);
196
197
198
199struct mailmime_language {
200 clist * lg_list; /* atom (char *) */
201};
202
203struct mailmime_language * mailmime_language_new(clist * lg_list);
204
205void mailmime_language_free(struct mailmime_language * lang);
206
207
208/*
209void mailmime_x_token_free(gchar * x_token);
210*/
211
212struct mailmime_field *
213mailmime_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
222void mailmime_field_free(struct mailmime_field * field);
223
224struct mailmime_fields * mailmime_fields_new(clist * fld_list);
225
226void mailmime_fields_free(struct mailmime_fields * fields);
227
228
229struct mailmime_multipart_body {
230 clist * bd_list;
231};
232
233struct mailmime_multipart_body *
234mailmime_multipart_body_new(clist * bd_list);
235
236void mailmime_multipart_body_free(struct mailmime_multipart_body * mp_body);
237
238
239enum {
240 MAILMIME_DATA_TEXT,
241 MAILMIME_DATA_FILE,
242};
243
244struct 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
257struct 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
261void mailmime_data_free(struct mailmime_data * mime_data);
262
263
264enum {
265 MAILMIME_NONE,
266 MAILMIME_SINGLE,
267 MAILMIME_MULTIPLE,
268 MAILMIME_MESSAGE,
269};
270
271struct 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
305struct 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
316void mailmime_free(struct mailmime * mime);
317
318struct mailmime_encoded_word {
319 char * wd_charset;
320 char * wd_text;
321};
322
323struct mailmime_encoded_word *
324mailmime_encoded_word_new(char * wd_charset, char * wd_text);
325
326void mailmime_encoded_word_free(struct mailmime_encoded_word * ew);
327
328void mailmime_charset_free(char * charset);
329
330void mailmime_encoded_text_free(char * text);
331
332
333struct mailmime_disposition {
334 struct mailmime_disposition_type * dsp_type;
335 clist * dsp_parms; /* struct mailmime_disposition_parm */
336};
337
338
339enum {
340 MAILMIME_DISPOSITION_TYPE_ERROR,
341 MAILMIME_DISPOSITION_TYPE_INLINE,
342 MAILMIME_DISPOSITION_TYPE_ATTACHMENT,
343 MAILMIME_DISPOSITION_TYPE_EXTENSION
344};
345
346struct mailmime_disposition_type {
347 int dsp_type;
348 char * dsp_extension;
349};
350
351
352enum {
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
361struct 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
373struct mailmime_disposition *
374mailmime_disposition_new(struct mailmime_disposition_type * dsp_type,
375 clist * dsp_parms);
376
377void mailmime_disposition_free(struct mailmime_disposition * dsp);
378
379struct mailmime_disposition_type *
380mailmime_disposition_type_new(int dt_type, char * dt_extension);
381
382void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type);
383
384struct mailmime_disposition_parm *
385mailmime_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
393void mailmime_disposition_parm_free(struct mailmime_disposition_parm *
394 dsp_parm);
395
396void mailmime_filename_parm_free(char * filename);
397
398void mailmime_creation_date_parm_free(char * date);
399
400void mailmime_modification_date_parm_free(char * date);
401
402void mailmime_read_date_parm_free(char * date);
403
404void mailmime_quoted_date_time_free(char * date);
405
406struct mailmime_section {
407 clist * sec_list; /* list of (uint32 *) */
408};
409
410struct mailmime_section * mailmime_section_new(clist * list);
411
412void mailmime_section_free(struct mailmime_section * section);
413
414
415void mailmime_decoded_part_free(char * part);
416
417struct 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
49int 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
65struct mailmime_disposition *
66mailmime_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
73struct 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
94int 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
106static 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
130struct mailmime_fields *
131mailmime_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
240struct mailmime_fields *
241mailmime_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
278struct 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
325struct 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
382struct mailmime *
383mailmime_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
423struct mailmime *
424mailmime_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
466struct mailmime *
467mailmime_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
501static 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
517struct mailmime *
518mailmime_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
623int
624mailmime_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
693int 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
708int 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
723int 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
738int 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
754int 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
772int 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
793int 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
821void 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
850int 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
947int 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
1001struct 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
1017struct 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
1042struct 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
1072void 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
1079struct 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
1098struct mailmime_disposition *
1099mailmime_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
1196static 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
1237static 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
1262void 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
1316struct mailmime_single_fields *
1317mailmime_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
1335void mailmime_single_fields_free(struct mailmime_single_fields *
1336 single_fields)
1337{
1338 free(single_fields);
1339}
1340
1341struct 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
1372struct mailmime_data *
1373mailmime_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
1379struct mailmime_data *
1380mailmime_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
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45
46int mailmime_transfer_encoding_get(struct mailmime_fields * fields);
47
48struct mailmime_disposition *
49mailmime_disposition_new_filename(int type, char * filename);
50
51struct mailmime_fields * mailmime_fields_new_empty(void);
52
53int mailmime_fields_add(struct mailmime_fields * fields,
54 struct mailmime_field * field);
55
56struct mailmime_fields *
57mailmime_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
63struct mailmime_fields *
64mailmime_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
70struct mailmime_content * mailmime_get_content_message(void);
71struct 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
76struct mailmime_data *
77mailmime_data_new_data(int encoding, int encoded,
78 const char * data, size_t length);
79
80struct mailmime_data *
81mailmime_data_new_file(int encoding, int encoded,
82 char * filename);
83
84#if 0
85struct mailmime *
86mailmime_new_message_file(char * filename);
87
88struct mailmime *
89mailmime_new_message_text(char * data_str, size_t length);
90#endif
91
92struct mailmime *
93mailmime_new_message_data(struct mailmime * msg_mime);
94
95struct mailmime *
96mailmime_new_empty(struct mailmime_content * content,
97 struct mailmime_fields * mime_fields);
98
99int
100mailmime_new_with_content(const char * content_type,
101 struct mailmime_fields * mime_fields,
102 struct mailmime ** result);
103
104int mailmime_set_preamble_file(struct mailmime * build_info,
105 char * filename);
106
107int mailmime_set_epilogue_file(struct mailmime * build_info,
108 char * filename);
109
110int mailmime_set_preamble_text(struct mailmime * build_info,
111 char * data_str, size_t length);
112
113int mailmime_set_epilogue_text(struct mailmime * build_info,
114 char * data_str, size_t length);
115
116int mailmime_set_body_file(struct mailmime * build_info,
117 char * filename);
118
119int mailmime_set_body_text(struct mailmime * build_info,
120 char * data_str, size_t length);
121
122int mailmime_add_part(struct mailmime * build_info,
123 struct mailmime * part);
124
125void mailmime_remove_part(struct mailmime * mime);
126
127void mailmime_set_imf_fields(struct mailmime * build_info,
128 struct mailimf_fields * fields);
129
130
131struct mailmime_disposition *
132mailmime_disposition_new_with_data(int type,
133 char * filename, char * creation_date, char * modification_date,
134 char * read_date, size_t size);
135
136void mailmime_single_fields_init(struct mailmime_single_fields * single_fields,
137 struct mailmime_fields * fld_fields,
138 struct mailmime_content * fld_content);
139
140struct mailmime_single_fields *
141mailmime_single_fields_new(struct mailmime_fields * fld_fields,
142 struct mailmime_content * fld_content);
143
144void mailmime_single_fields_free(struct mailmime_single_fields *
145 single_fields);
146
147int mailmime_smart_add_part(struct mailmime * mime,
148 struct mailmime * mime_sub);
149
150int mailmime_smart_remove_part(struct mailmime * mime);
151
152struct mailmime_content * mailmime_content_new_with_str(const char * str);
153
154struct mailmime_fields * mailmime_fields_new_encoding(int type);
155
156struct mailmime * mailmime_multiple_new(const char * type);
157
158struct 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
61static int mailmime_field_write(FILE * f, int * col,
62 struct mailmime_field * field);
63
64static int mailmime_id_write(FILE * f, int * col, char * id);
65
66static int mailmime_description_write(FILE * f, int * col, char * descr);
67
68static int mailmime_version_write(FILE * f, int * col, uint32_t version);
69
70static int mailmime_encoding_write(FILE * f, int * col,
71 struct mailmime_mechanism * encoding);
72
73static int mailmime_language_write(FILE * f, int * col,
74 struct mailmime_language * language);
75
76static int mailmime_disposition_write(FILE * f, int * col,
77 struct mailmime_disposition *
78 disposition);
79
80static int
81mailmime_disposition_param_write(FILE * f, int * col,
82 struct mailmime_disposition_parm * param);
83
84static int mailmime_parameter_write(FILE * f, int * col,
85 struct mailmime_parameter * param);
86
87/*
88static int mailmime_content_write(FILE * f, int * col,
89 struct mailmime_content * content);
90*/
91
92static int mailmime_type_write(FILE * f, int * col,
93 struct mailmime_type * type);
94
95static int
96mailmime_discrete_type_write(FILE * f, int * col,
97 struct mailmime_discrete_type * discrete_type);
98
99static int
100mailmime_composite_type_write(FILE * f, int * col,
101 struct mailmime_composite_type * composite_type);
102
103static int mailmime_sub_write(FILE * f, int * col,
104 struct mailmime * build_info);
105
106
107/* ***** */
108
109int 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
127static 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
172static 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
202static 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
224static 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
249static 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
302static 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
359static 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
417static int
418mailmime_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
535static 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
557int 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
611int 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
631static 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
656static int
657mailmime_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
699static int
700mailmime_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/*
737static int mailmime_data_write(FILE * f, int * col,
738 struct mailmime_data * data,
739 int is_text);
740*/
741
742static int mailmime_text_content_write(FILE * f, int * col, int encoding,
743 int istext,
744 const char * text, size_t size);
745
746/*
747static int mailmime_base64_write(FILE * f, int * col,
748 char * text, size_t size);
749
750static int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
751 char * text, size_t size);
752*/
753
754static 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
926static 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
962int 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
972int 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
1058static 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
1080static const char base64_encoding[] =
1081"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1082
1083#define BASE64_MAX_COL 76
1084
1085int 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
1163enum {
1164 STATE_INIT,
1165 STATE_CR,
1166 STATE_SPACE,
1167 STATE_SPACE_CR,
1168};
1169
1170#if 0
1171static 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
1187static 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
1206int 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
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45#include <stdio.h>
46
47int mailmime_fields_write(FILE * f, int * col,
48 struct mailmime_fields * fields);
49
50int mailmime_content_write(FILE * f, int * col,
51 struct mailmime_content * content);
52
53int mailmime_content_type_write(FILE * f, int * col,
54 struct mailmime_content * content);
55
56int mailmime_write(FILE * f, int * col,
57 struct mailmime * build_info);
58
59int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
60 const char * text, size_t size);
61
62int mailmime_base64_write(FILE * f, int * col,
63 const char * text, size_t size);
64
65int 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