summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/mime
Unidiff
Diffstat (limited to 'libetpan/src/low-level/mime') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/mime/TODO10
-rw-r--r--libetpan/src/low-level/mime/mailmime.c1408
-rw-r--r--libetpan/src/low-level/mime/mailmime.h102
-rw-r--r--libetpan/src/low-level/mime/mailmime_content.c2381
-rw-r--r--libetpan/src/low-level/mime/mailmime_content.h89
-rw-r--r--libetpan/src/low-level/mime/mailmime_decode.c544
-rw-r--r--libetpan/src/low-level/mime/mailmime_decode.h55
-rw-r--r--libetpan/src/low-level/mime/mailmime_disposition.c595
-rw-r--r--libetpan/src/low-level/mime/mailmime_disposition.h62
-rw-r--r--libetpan/src/low-level/mime/mailmime_types.c753
-rw-r--r--libetpan/src/low-level/mime/mailmime_types.h440
-rw-r--r--libetpan/src/low-level/mime/mailmime_types_helper.c1385
-rw-r--r--libetpan/src/low-level/mime/mailmime_types_helper.h165
-rw-r--r--libetpan/src/low-level/mime/mailmime_write.c1416
-rw-r--r--libetpan/src/low-level/mime/mailmime_write.h73
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_file.c156
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_file.h105
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_generic.c1416
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_generic.h73
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_mem.c106
-rw-r--r--libetpan/src/low-level/mime/mailmime_write_mem.h73
21 files changed, 11407 insertions, 0 deletions
diff --git a/libetpan/src/low-level/mime/TODO b/libetpan/src/low-level/mime/TODO
new file mode 100644
index 0000000..df02810
--- a/dev/null
+++ b/libetpan/src/low-level/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/libetpan/src/low-level/mime/mailmime.c b/libetpan/src/low-level/mime/mailmime.c
new file mode 100644
index 0000000..4bade55
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime.c
@@ -0,0 +1,1408 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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/libetpan/src/low-level/mime/mailmime.h b/libetpan/src/low-level/mime/mailmime.h
new file mode 100644
index 0000000..83cba25
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime.h
@@ -0,0 +1,102 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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_file.h>
51#include <libetpan/mailmime_write_mem.h>
52#include <libetpan/mailmime_write_generic.h>
53
54int mailmime_content_parse(const char * message, size_t length,
55 size_t * index,
56 struct mailmime_content ** result);
57
58int mailmime_description_parse(const char * message, size_t length,
59 size_t * index,
60 char ** result);
61
62int mailmime_encoding_parse(const char * message, size_t length,
63 size_t * index,
64 struct mailmime_mechanism ** result);
65
66int
67mailmime_field_parse(struct mailimf_optional_field * field,
68 struct mailmime_field ** result);
69
70int mailmime_id_parse(const char * message, size_t length,
71 size_t * index, char ** result);
72
73int
74mailmime_fields_parse(struct mailimf_fields *
75 fields,
76 struct mailmime_fields **
77 result);
78
79int mailmime_version_parse(const char * message, size_t length,
80 size_t * index,
81 uint32_t * result);
82
83int
84mailmime_extension_token_parse(const char * message, size_t length,
85 size_t * index, char ** result);
86
87int mailmime_parameter_parse(const char * message, size_t length,
88 size_t * index,
89 struct mailmime_parameter ** result);
90
91int mailmime_value_parse(const char * message, size_t length,
92 size_t * index, char ** result);
93
94int mailmime_language_parse(const char * message, size_t length,
95 size_t * index,
96 struct mailmime_language ** result);
97
98#ifdef __cplusplus
99}
100#endif
101
102#endif
diff --git a/libetpan/src/low-level/mime/mailmime_content.c b/libetpan/src/low-level/mime/mailmime_content.c
new file mode 100644
index 0000000..6a10dfb
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_content.c
@@ -0,0 +1,2381 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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 size = end_text - begin_text;
519
520#if 0
521 if (size > 0) {
522 end_text --;
523 size --;
524 }
525#endif
526
527 if (size >= 1) {
528 if (message[end_text - 1] == '\r') {
529 end_text --;
530 size --;
531 }
532 else if (size >= 1) {
533 if (message[end_text - 1] == '\n') {
534 end_text --;
535 size --;
536 if (size >= 1) {
537 if (message[end_text - 1] == '\r') {
538 end_text --;
539 size --;
540 }
541 }
542 }
543 }
544 }
545
546 size = end_text - begin_text;
547 if (size == 0)
548 return MAILIMF_ERROR_PARSE;
549
550#if 0
551 body_part = mailimf_body_new(message + begin_text, size);
552 if (body_part == NULL)
553 goto err;
554#endif
555
556 * result = message + begin_text;
557 * result_size = size;
558 * index = cur_token;
559
560 return MAILIMF_NO_ERROR;
561#if 0
562 err:
563 return MAILIMF_ERROR_PARSE;
564#endif
565}
566
567static int
568mailmime_body_part_dash2_transport_crlf_parse(const char * message,
569 size_t length,
570 size_t * index, char * boundary,
571 const char ** result, size_t * result_size)
572{
573 size_t cur_token;
574 int r;
575 size_t after_boundary;
576 const char * data_str;
577 size_t data_size;
578 const char * begin_text;
579 const char * end_text;
580
581 cur_token = * index;
582
583 begin_text = message + cur_token;
584 end_text = message + cur_token;
585
586 while (1) {
587 r = mailmime_body_part_dash2_parse(message, length, &cur_token,
588 boundary, &data_str, &data_size);
589 if (r == MAILIMF_NO_ERROR) {
590 end_text = data_str + data_size;
591 }
592 else {
593 return r;
594 }
595
596 /* parse transport-padding */
597 while (1) {
598 r = mailmime_lwsp_parse(message, length, &cur_token);
599 if (r == MAILIMF_NO_ERROR) {
600 /* do nothing */
601 }
602 else if (r == MAILIMF_ERROR_PARSE) {
603 break;
604 }
605 else {
606 return r;
607 }
608 }
609
610 r = mailimf_crlf_parse(message, length, &cur_token);
611 if (r == MAILIMF_NO_ERROR) {
612 break;
613 }
614 else if (r == MAILIMF_ERROR_PARSE) {
615 /* do nothing */
616 }
617 else {
618 return r;
619 }
620 }
621
622 * index = cur_token;
623 * result = begin_text;
624 * result_size = end_text - begin_text;
625
626 return MAILIMF_NO_ERROR;
627}
628
629static int mailmime_multipart_close_parse(const char * message, size_t length,
630 size_t * index);
631
632static int
633mailmime_body_part_dash2_close_parse(const char * message,
634 size_t length,
635 size_t * index, char * boundary,
636 const char ** result, size_t * result_size)
637{
638 size_t cur_token;
639 int r;
640 size_t after_boundary;
641 const char * data_str;
642 size_t data_size;
643 const char * begin_text;
644 const char * end_text;
645
646 cur_token = * index;
647
648 begin_text = message + cur_token;
649 end_text = message + cur_token;
650
651 while (1) {
652 r = mailmime_body_part_dash2_parse(message, length,
653 &cur_token, boundary, &data_str, &data_size);
654 if (r == MAILIMF_NO_ERROR) {
655 end_text = data_str + data_size;
656 }
657 else {
658 return r;
659 }
660
661 r = mailmime_multipart_close_parse(message, length, &cur_token);
662 if (r == MAILIMF_NO_ERROR) {
663 break;
664 }
665 else if (r == MAILIMF_ERROR_PARSE) {
666 /* do nothing */
667 }
668 else {
669 return r;
670 }
671 }
672
673 * index = cur_token;
674 * result = data_str;
675 * result_size = data_size;
676
677 return MAILIMF_NO_ERROR;
678}
679
680enum {
681 MULTIPART_CLOSE_STATE_0,
682 MULTIPART_CLOSE_STATE_1,
683 MULTIPART_CLOSE_STATE_2,
684 MULTIPART_CLOSE_STATE_3,
685 MULTIPART_CLOSE_STATE_4
686};
687
688static int mailmime_multipart_close_parse(const char * message, size_t length,
689 size_t * index)
690{
691 int state;
692 size_t cur_token;
693
694 cur_token = * index;
695 state = MULTIPART_CLOSE_STATE_0;
696
697 while (state != MULTIPART_CLOSE_STATE_4) {
698
699 switch(state) {
700
701 case MULTIPART_CLOSE_STATE_0:
702 if (cur_token >= length)
703 return MAILIMF_ERROR_PARSE;
704
705 switch (message[cur_token]) {
706 case '-':
707 state = MULTIPART_CLOSE_STATE_1;
708 break;
709 default:
710 return MAILIMF_ERROR_PARSE;
711 }
712 break;
713
714 case MULTIPART_CLOSE_STATE_1:
715 if (cur_token >= length)
716 return MAILIMF_ERROR_PARSE;
717
718 switch (message[cur_token]) {
719 case '-':
720 state = MULTIPART_CLOSE_STATE_2;
721 break;
722 default:
723 return MAILIMF_ERROR_PARSE;
724 }
725 break;
726
727 case MULTIPART_CLOSE_STATE_2:
728 if (cur_token >= length) {
729 state = MULTIPART_CLOSE_STATE_4;
730 break;
731 }
732
733 switch (message[cur_token]) {
734 case ' ':
735 state = MULTIPART_CLOSE_STATE_2;
736 break;
737 case '\t':
738 state = MULTIPART_CLOSE_STATE_2;
739 break;
740 case '\r':
741 state = MULTIPART_CLOSE_STATE_3;
742 break;
743 case '\n':
744 state = MULTIPART_CLOSE_STATE_4;
745 break;
746 default:
747 state = MULTIPART_CLOSE_STATE_4;
748 break;
749 }
750 break;
751
752 case MULTIPART_CLOSE_STATE_3:
753 if (cur_token >= length) {
754 state = MULTIPART_CLOSE_STATE_4;
755 break;
756 }
757
758 switch (message[cur_token]) {
759 case '\n':
760 state = MULTIPART_CLOSE_STATE_4;
761 break;
762 default:
763 state = MULTIPART_CLOSE_STATE_4;
764 break;
765 }
766 break;
767 }
768
769 cur_token ++;
770 }
771
772 * index = cur_token;
773
774 return MAILIMF_NO_ERROR;
775}
776
777enum {
778 MULTIPART_NEXT_STATE_0,
779 MULTIPART_NEXT_STATE_1,
780 MULTIPART_NEXT_STATE_2
781};
782
783int mailmime_multipart_next_parse(const char * message, size_t length,
784 size_t * index)
785{
786 int state;
787 size_t cur_token;
788
789 cur_token = * index;
790 state = MULTIPART_NEXT_STATE_0;
791
792 while (state != MULTIPART_NEXT_STATE_2) {
793
794 if (cur_token >= length)
795 return MAILIMF_ERROR_PARSE;
796
797 switch(state) {
798
799 case MULTIPART_NEXT_STATE_0:
800 switch (message[cur_token]) {
801 case ' ':
802 state = MULTIPART_NEXT_STATE_0;
803 break;
804 case '\t':
805 state = MULTIPART_NEXT_STATE_0;
806 break;
807 case '\r':
808 state = MULTIPART_NEXT_STATE_1;
809 break;
810 case '\n':
811 state = MULTIPART_NEXT_STATE_2;
812 break;
813 default:
814 return MAILIMF_ERROR_PARSE;
815 }
816 break;
817
818 case MULTIPART_NEXT_STATE_1:
819 switch (message[cur_token]) {
820 case '\n':
821 state = MULTIPART_NEXT_STATE_2;
822 break;
823 default:
824 return MAILIMF_ERROR_PARSE;
825 }
826 break;
827 }
828
829 cur_token ++;
830 }
831
832 * index = cur_token;
833
834 return MAILIMF_NO_ERROR;
835}
836
837static int
838mailmime_multipart_body_parse(const char * message, size_t length,
839 size_t * index, char * boundary,
840 int default_subtype,
841 clist ** result,
842 struct mailmime_data ** p_preamble,
843 struct mailmime_data ** p_epilogue)
844{
845 size_t cur_token;
846 clist * list;
847 int r;
848 int res;
849#if 0
850 size_t begin;
851#endif
852 size_t preamble_begin;
853 size_t preamble_length;
854 size_t preamble_end;
855#if 0
856 int no_preamble;
857 size_t before_crlf;
858#endif
859 size_t epilogue_begin;
860 size_t epilogue_length;
861 struct mailmime_data * preamble;
862 struct mailmime_data * epilogue;
863 size_t part_begin;
864 int final_part;
865
866 preamble = NULL;
867 epilogue = NULL;
868
869 cur_token = * index;
870 preamble_begin = cur_token;
871
872#if 0
873 no_preamble = FALSE;
874#endif
875 preamble_end = preamble_begin;
876
877#if 0
878 r = mailmime_preamble_parse(message, length, &cur_token);
879 if (r == MAILIMF_NO_ERROR) {
880 /* do nothing */
881#if 0
882 preamble_end = cur_token - 2;
883#endif
884 }
885 else if (r == MAILIMF_ERROR_PARSE) {
886 /* do nothing */
887 no_preamble = TRUE;
888 }
889 else {
890 res = r;
891 goto err;
892 }
893
894 while (1) {
895
896 preamble_end = cur_token;
897 r = mailmime_boundary_parse(message, length, &cur_token, boundary);
898 if (r == MAILIMF_NO_ERROR) {
899 break;
900 }
901 else if (r == MAILIMF_ERROR_PARSE) {
902 /* do nothing */
903 }
904 else {
905 res = r;
906 goto err;
907 }
908
909 r = mailmime_preamble_parse(message, length, &cur_token);
910 if (r == MAILIMF_NO_ERROR) {
911#if 0
912 preamble_end = cur_token - 2;
913#endif
914 }
915 else if (r == MAILIMF_ERROR_PARSE) {
916 no_preamble = TRUE;
917 break;
918 }
919 else {
920 res = r;
921 goto err;
922 }
923 }
924
925 if (no_preamble) {
926#if 0
927 preamble_end = cur_token;
928#endif
929 }
930 else {
931
932 r = mailmime_lwsp_parse(message, length, &cur_token);
933 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
934 res = r;
935 goto err;
936 }
937
938 before_crlf = cur_token;
939 r = mailimf_crlf_parse(message, length, &cur_token);
940 if (r == MAILIMF_NO_ERROR) {
941#if 0
942 preamble_end = before_crlf;
943#endif
944 /* remove the CR LF at the end of preamble if any */
945 }
946 else if (r == MAILIMF_ERROR_PARSE) {
947 /* do nothing */
948 }
949 else {
950 res = r;
951 goto err;
952 }
953 }
954 preamble_length = preamble_end - begin;
955#endif
956
957 r = mailmime_preamble_parse(message, length, &cur_token, 1);
958 if (r == MAILIMF_NO_ERROR) {
959 while (1) {
960
961 preamble_end = cur_token;
962 r = mailmime_boundary_parse(message, length, &cur_token, boundary);
963 if (r == MAILIMF_NO_ERROR) {
964 break;
965 }
966 else if (r == MAILIMF_ERROR_PARSE) {
967 /* do nothing */
968 }
969 else {
970 res = r;
971 goto err;
972 }
973
974 r = mailmime_preamble_parse(message, length, &cur_token, 0);
975 if (r == MAILIMF_NO_ERROR) {
976 }
977 else if (r == MAILIMF_ERROR_PARSE) {
978 break;
979 }
980 else {
981 res = r;
982 goto err;
983 }
984 }
985 }
986
987 preamble_end -= 2;
988 if (preamble_end != preamble_begin) {
989 /* try to find the real end of the preamble (strip CR LF) */
990 if (message[preamble_end - 1] == '\n') {
991 preamble_end --;
992 if (preamble_end - 1 >= preamble_begin) {
993 if (message[preamble_end - 1] == '\r')
994 preamble_end --;
995 }
996 }
997 else if (message[preamble_end - 1] == '\r') {
998 preamble_end --;
999 }
1000 }
1001 preamble_length = preamble_end - preamble_begin;
1002
1003 part_begin = cur_token;
1004 while (1) {
1005 r = mailmime_lwsp_parse(message, length, &cur_token);
1006 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1007 res = r;
1008 goto err;
1009 }
1010#if 0
1011 if (r == MAILIMF_ERROR_PARSE)
1012 break;
1013#endif
1014
1015 r = mailimf_crlf_parse(message, length, &cur_token);
1016 if (r == MAILIMF_NO_ERROR) {
1017 part_begin = cur_token;
1018 }
1019 else if (r == MAILIMF_ERROR_PARSE) {
1020 /* do nothing */
1021 break;
1022 }
1023 else {
1024 res = r;
1025 goto err;
1026 }
1027 }
1028
1029 cur_token = part_begin;
1030
1031 list = clist_new();
1032 if (list == NULL) {
1033 res = MAILIMF_ERROR_MEMORY;
1034 goto err;
1035 }
1036
1037 final_part = 0;
1038
1039 while (!final_part) {
1040 size_t bp_token;
1041 struct mailmime * mime_bp;
1042 const char * data_str;
1043 size_t data_size;
1044 struct mailimf_fields * fields;
1045 struct mailmime_fields * mime_fields;
1046 int got_crlf;
1047 size_t after_boundary;
1048
1049#if 0
1050 /* XXX - begin */
1051 r = mailmime_body_part_dash2_parse(message, length, &cur_token,
1052 boundary, &data_str, &data_size);
1053 if (r == MAILIMF_NO_ERROR) {
1054 /* do nothing */
1055 }
1056 else if (r == MAILIMF_ERROR_PARSE) {
1057 break;
1058 }
1059 else {
1060 res = r;
1061 goto free;
1062 }
1063
1064 after_boundary = cur_token;
1065 got_crlf = 0;
1066 /* parse transport-padding */
1067 while (1) {
1068 r = mailmime_lwsp_parse(message, length, &cur_token);
1069 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1070 res = r;
1071 goto free;
1072 }
1073
1074 r = mailimf_crlf_parse(message, length, &cur_token);
1075 if (r == MAILIMF_NO_ERROR) {
1076 got_crlf = 1;
1077 break;
1078 }
1079 else if (r == MAILIMF_ERROR_PARSE) {
1080 /* do nothing */
1081 break;
1082 }
1083 else {
1084 res = r;
1085 goto free;
1086 }
1087 }
1088 if (after_boundary != cur_token) {
1089 if (!got_crlf) {
1090 r = mailimf_crlf_parse(message, length, &cur_token);
1091 if (r == MAILIMF_NO_ERROR) {
1092 got_crlf = 1;
1093 break;
1094 }
1095 }
1096 }
1097 /* XXX - end */
1098#endif
1099
1100 r = mailmime_body_part_dash2_transport_crlf_parse(message, length,
1101 &cur_token, boundary, &data_str, &data_size);
1102 if (r == MAILIMF_ERROR_PARSE) {
1103 r = mailmime_body_part_dash2_close_parse(message, length,
1104 &cur_token, boundary, &data_str, &data_size);
1105 if (r == MAILIMF_NO_ERROR) {
1106 final_part = 1;
1107 }
1108 }
1109
1110 if (r == MAILIMF_NO_ERROR) {
1111 bp_token = 0;
1112
1113 r = mailimf_optional_fields_parse(data_str, data_size,
1114 &bp_token, &fields);
1115 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1116 res = r;
1117 goto free;
1118 }
1119
1120 r = mailimf_crlf_parse(data_str, data_size, &bp_token);
1121 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1122 mailimf_fields_free(fields);
1123 res = r;
1124 goto free;
1125 }
1126
1127 mime_fields = NULL;
1128 r = mailmime_fields_parse(fields, &mime_fields);
1129 mailimf_fields_free(fields);
1130 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1131 res = r;
1132 goto free;
1133 }
1134
1135 r = mailmime_parse_with_default(data_str, data_size,
1136 &bp_token, default_subtype, NULL,
1137 mime_fields, &mime_bp);
1138 if (r == MAILIMF_NO_ERROR) {
1139 r = clist_append(list, mime_bp);
1140 if (r < 0) {
1141 mailmime_free(mime_bp);
1142 res = MAILIMF_ERROR_MEMORY;
1143 goto free;
1144 }
1145 }
1146 else if (r == MAILIMF_ERROR_PARSE) {
1147 mailmime_fields_free(mime_fields);
1148 break;
1149 }
1150 else {
1151 mailmime_fields_free(mime_fields);
1152 res = r;
1153 goto free;
1154 }
1155
1156 r = mailmime_multipart_next_parse(message, length, &cur_token);
1157 if (r == MAILIMF_NO_ERROR) {
1158 /* do nothing */
1159 }
1160 }
1161 else {
1162 res = r;
1163 goto free;
1164 }
1165
1166#if 0
1167 else if (r == MAILIMF_ERROR_PARSE) {
1168 r = mailmime_body_part_dash2_parse(message, length,
1169 &cur_token, boundary, &data_str, &data_size);
1170 if (r != MAILIMF_NO_ERROR) {
1171 res = r;
1172 goto free;
1173 }
1174
1175 r = mailmime_multipart_close_parse(message, length, &cur_token);
1176 if (r == MAILIMF_NO_ERROR) {
1177 break;
1178 }
1179 else if (r == MAILIMF_ERROR_PARSE) {
1180 res = r;
1181 goto free;
1182#if 0
1183 fprintf(stderr, "close not found, reparse %s\n", boundary);
1184 /* reparse */
1185 continue;
1186#endif
1187 }
1188 else {
1189 res = r;
1190 goto free;
1191 }
1192 }
1193 else {
1194 res = r;
1195 goto free;
1196 }
1197#endif
1198 }
1199
1200 epilogue_begin = length;
1201 /* parse transport-padding */
1202 while (1) {
1203 r = mailmime_lwsp_parse(message, length, &cur_token);
1204 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1205 res = r;
1206 goto free;
1207 }
1208
1209 if (r == MAILIMF_ERROR_PARSE)
1210 break;
1211
1212#if 0
1213 if (r == MAILIMF_ERROR_PARSE)
1214 break;
1215#endif
1216
1217#if 0
1218 before_crlf = cur_token;
1219#endif
1220 }
1221
1222 r = mailimf_crlf_parse(message, length, &cur_token);
1223 if (r == MAILIMF_NO_ERROR) {
1224 epilogue_begin = cur_token;
1225 }
1226 else if (r != MAILIMF_ERROR_PARSE) {
1227 res = r;
1228 goto free;
1229 }
1230
1231 /* add preamble and epilogue */
1232
1233 epilogue_length = length - epilogue_begin;
1234
1235 if (preamble_length != 0) {
1236 preamble = mailmime_data_new(MAILMIME_DATA_TEXT,
1237 MAILMIME_MECHANISM_8BIT, 1,
1238 message + preamble_begin, preamble_length,
1239 NULL);
1240 if (preamble == NULL) {
1241 res = MAILIMF_ERROR_MEMORY;
1242 goto free;
1243 }
1244 }
1245
1246 if (epilogue_length != 0) {
1247 epilogue = mailmime_data_new(MAILMIME_DATA_TEXT,
1248 MAILMIME_MECHANISM_8BIT, 1,
1249 message + epilogue_begin, epilogue_length,
1250 NULL);
1251 if (epilogue == NULL) {
1252 res = MAILIMF_ERROR_MEMORY;
1253 goto free;
1254 }
1255 }
1256
1257 /* end of preamble and epilogue */
1258
1259 cur_token = length;
1260
1261 * result = list;
1262 * p_preamble = preamble;
1263 * p_epilogue = epilogue;
1264 * index = cur_token;
1265
1266 return MAILIMF_NO_ERROR;
1267
1268 free:
1269 if (epilogue != NULL)
1270 mailmime_data_free(epilogue);
1271 if (preamble != NULL)
1272 mailmime_data_free(preamble);
1273 clist_foreach(list, (clist_func) mailmime_free, NULL);
1274 clist_free(list);
1275 err:
1276 return res;
1277}
1278
1279enum {
1280 MAILMIME_DEFAULT_TYPE_TEXT_PLAIN,
1281 MAILMIME_DEFAULT_TYPE_MESSAGE
1282};
1283
1284
1285int mailmime_parse(const char * message, size_t length,
1286 size_t * index, struct mailmime ** result)
1287{
1288 struct mailmime * mime;
1289 int r;
1290 int res;
1291 struct mailmime_content * content_message;
1292 size_t cur_token;
1293 struct mailmime_fields * mime_fields;
1294 const char * data_str;
1295 size_t data_size;
1296 size_t bp_token;
1297
1298 cur_token = * index;
1299
1300 content_message = mailmime_get_content_message();
1301 if (content_message == NULL) {
1302 res = MAILIMF_ERROR_MEMORY;
1303 goto err;
1304 }
1305
1306#if 0
1307 mime_fields = mailmime_fields_new_with_data(content_message,
1308 NULL,
1309 NULL,
1310 NULL,
1311 NULL,
1312 NULL);
1313 if (mime_fields == NULL) {
1314 mailmime_content_free(content_message);
1315 res = MAILIMF_ERROR_MEMORY;
1316 goto err;
1317 }
1318#endif
1319 mime_fields = mailmime_fields_new_empty();
1320 if (mime_fields == NULL) {
1321 mailmime_content_free(content_message);
1322 res = MAILIMF_ERROR_MEMORY;
1323 goto err;
1324 }
1325
1326 data_str = message + cur_token;
1327 data_size = length - cur_token;
1328
1329 bp_token = 0;
1330 r = mailmime_parse_with_default(data_str, data_size,
1331 &bp_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN,
1332 content_message, mime_fields, &mime);
1333 cur_token += bp_token;
1334 if (r != MAILIMF_NO_ERROR) {
1335 mailmime_fields_free(mime_fields);
1336 res = r;
1337 goto free;
1338 }
1339
1340 * index = cur_token;
1341 * result = mime;
1342
1343 return MAILIMF_NO_ERROR;
1344
1345 free:
1346 mailmime_fields_free(mime_fields);
1347 err:
1348 return res;
1349}
1350
1351
1352char * mailmime_extract_boundary(struct mailmime_content * content_type)
1353{
1354 char * boundary;
1355
1356 boundary = mailmime_content_param_get(content_type, "boundary");
1357
1358 if (boundary != NULL) {
1359 int len;
1360 char * new_boundary;
1361
1362 len = strlen(boundary);
1363 new_boundary = malloc(len + 1);
1364 if (new_boundary == NULL)
1365 return NULL;
1366
1367 if (boundary[0] == '"') {
1368 strncpy(new_boundary, boundary + 1, len - 2);
1369 new_boundary[len - 2] = 0;
1370 }
1371 else
1372 strcpy(new_boundary, boundary);
1373
1374 boundary = new_boundary;
1375 }
1376
1377 return boundary;
1378}
1379
1380static void remove_unparsed_mime_headers(struct mailimf_fields * fields)
1381{
1382 clistiter * cur;
1383
1384 cur = clist_begin(fields->fld_list);
1385 while (cur != NULL) {
1386 struct mailimf_field * field;
1387 int delete;
1388
1389 field = clist_content(cur);
1390
1391 switch (field->fld_type) {
1392 case MAILIMF_FIELD_OPTIONAL_FIELD:
1393 delete = 0;
1394 if (strncasecmp(field->fld_data.fld_optional_field->fld_name,
1395 "Content-", 8) == 0) {
1396 char * name;
1397
1398 name = field->fld_data.fld_optional_field->fld_name + 8;
1399 if ((strcasecmp(name, "Type") == 0)
1400 || (strcasecmp(name, "Transfer-Encoding") == 0)
1401 || (strcasecmp(name, "ID") == 0)
1402 || (strcasecmp(name, "Description") == 0)
1403 || (strcasecmp(name, "Disposition") == 0)
1404 || (strcasecmp(name, "Language") == 0)) {
1405 delete = 1;
1406 }
1407 }
1408 else if (strcasecmp(field->fld_data.fld_optional_field->fld_name,
1409 "MIME-Version") == 0) {
1410 delete = 1;
1411 }
1412
1413 if (delete) {
1414 cur = clist_delete(fields->fld_list, cur);
1415 mailimf_field_free(field);
1416 }
1417 else {
1418 cur = clist_next(cur);
1419 }
1420 break;
1421
1422 default:
1423 cur = clist_next(cur);
1424 }
1425 }
1426}
1427
1428static int mailmime_parse_with_default(const char * message, size_t length,
1429 size_t * index, int default_type,
1430 struct mailmime_content * content_type,
1431 struct mailmime_fields * mime_fields,
1432 struct mailmime ** result)
1433{
1434 size_t cur_token;
1435
1436 int body_type;
1437
1438 int encoding;
1439 struct mailmime_data * body;
1440 char * boundary;
1441 struct mailimf_fields * fields;
1442 clist * list;
1443 struct mailmime * msg_mime;
1444
1445 struct mailmime * mime;
1446
1447 int r;
1448 int res;
1449 struct mailmime_data * preamble;
1450 struct mailmime_data * epilogue;
1451
1452 /*
1453 note that when this function is called, content type is always detached,
1454 even if the function fails
1455 */
1456
1457 preamble = NULL;
1458 epilogue = NULL;
1459
1460 cur_token = * index;
1461
1462 /* get content type */
1463
1464 if (content_type == NULL) {
1465 if (mime_fields != NULL) {
1466 clistiter * cur;
1467
1468 for(cur = clist_begin(mime_fields->fld_list) ; cur != NULL ;
1469 cur = clist_next(cur)) {
1470 struct mailmime_field * field;
1471
1472 field = clist_content(cur);
1473 if (field->fld_type == MAILMIME_FIELD_TYPE) {
1474 content_type = field->fld_data.fld_content;
1475
1476 /* detach content type from list */
1477 field->fld_data.fld_content = NULL;
1478 clist_delete(mime_fields->fld_list, cur);
1479 mailmime_field_free(field);
1480 /*
1481 there may be a leak due to the detached content type
1482 in case the function fails
1483 */
1484 break;
1485 }
1486 }
1487 }
1488 }
1489
1490 /* set default type if no content type */
1491
1492 if (content_type == NULL) {
1493 /* content_type is detached, in any case, we will have to free it */
1494 if (default_type == MAILMIME_DEFAULT_TYPE_TEXT_PLAIN) {
1495 content_type = mailmime_get_content_text();
1496 if (content_type == NULL) {
1497 res = MAILIMF_ERROR_MEMORY;
1498 goto err;
1499 }
1500 }
1501 else /* message */ {
1502 body_type = MAILMIME_MESSAGE;
1503
1504 content_type = mailmime_get_content_message();
1505 if (content_type == NULL) {
1506 res = MAILIMF_ERROR_MEMORY;
1507 goto err;
1508 }
1509 }
1510 }
1511
1512 /* get the body type */
1513
1514 boundary = NULL; /* XXX - removes a gcc warning */
1515
1516 switch (content_type->ct_type->tp_type) {
1517 case MAILMIME_TYPE_COMPOSITE_TYPE:
1518 switch (content_type->ct_type->tp_data.tp_composite_type->ct_type) {
1519 case MAILMIME_COMPOSITE_TYPE_MULTIPART:
1520 boundary = mailmime_extract_boundary(content_type);
1521
1522 if (boundary == NULL)
1523 body_type = MAILMIME_SINGLE;
1524 else
1525 body_type = MAILMIME_MULTIPLE;
1526 break;
1527
1528 case MAILMIME_COMPOSITE_TYPE_MESSAGE:
1529
1530 if (strcasecmp(content_type->ct_subtype, "rfc822") == 0)
1531 body_type = MAILMIME_MESSAGE;
1532 else
1533 body_type = MAILMIME_SINGLE;
1534 break;
1535
1536 default:
1537 res = MAILIMF_ERROR_INVAL;
1538 goto free_content;
1539 }
1540 break;
1541
1542 default: /* MAILMIME_TYPE_DISCRETE_TYPE */
1543 body_type = MAILMIME_SINGLE;
1544 break;
1545 }
1546
1547 /* set body */
1548
1549 if (mime_fields != NULL)
1550 encoding = mailmime_transfer_encoding_get(mime_fields);
1551 else
1552 encoding = MAILMIME_MECHANISM_8BIT;
1553
1554 cur_token = * index;
1555 body = mailmime_data_new(MAILMIME_DATA_TEXT, encoding, 1,
1556 message + cur_token, length - cur_token,
1557 NULL);
1558 if (body == NULL) {
1559 res = MAILIMF_ERROR_MEMORY;
1560 goto free_content;
1561 }
1562
1563 /* in case of composite, parse the sub-part(s) */
1564
1565 list = NULL;
1566 msg_mime = NULL;
1567 fields = NULL;
1568
1569 switch (body_type) {
1570 case MAILMIME_MESSAGE:
1571 {
1572 struct mailmime_fields * submime_fields;
1573
1574 r = mailimf_envelope_and_optional_fields_parse(message, length,
1575 &cur_token, &fields);
1576 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1577 res = r;
1578 goto free_content;
1579 }
1580
1581 r = mailimf_crlf_parse(message, length, &cur_token);
1582 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1583 mailimf_fields_free(fields);
1584 res = r;
1585 goto free_content;
1586 }
1587
1588 submime_fields = NULL;
1589 r = mailmime_fields_parse(fields, &submime_fields);
1590 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
1591 mailimf_fields_free(fields);
1592 res = r;
1593 goto free_content;
1594 }
1595
1596 remove_unparsed_mime_headers(fields);
1597
1598 r = mailmime_parse_with_default(message, length,
1599 &cur_token, MAILMIME_DEFAULT_TYPE_TEXT_PLAIN,
1600 NULL, submime_fields, &msg_mime);
1601 if (r == MAILIMF_NO_ERROR) {
1602 /* do nothing */
1603 }
1604 else if (r == MAILIMF_ERROR_PARSE) {
1605 mailmime_fields_free(mime_fields);
1606 msg_mime = NULL;
1607 }
1608 else {
1609 mailmime_fields_free(mime_fields);
1610 res = r;
1611 goto free_content;
1612 }
1613 }
1614
1615 break;
1616
1617 case MAILMIME_MULTIPLE:
1618 {
1619 int default_subtype;
1620
1621 default_subtype = MAILMIME_DEFAULT_TYPE_TEXT_PLAIN;
1622 if (content_type != NULL)
1623 if (strcasecmp(content_type->ct_subtype, "digest") == 0)
1624 default_subtype = MAILMIME_DEFAULT_TYPE_MESSAGE;
1625
1626 cur_token = * index;
1627 r = mailmime_multipart_body_parse(message, length,
1628 &cur_token, boundary,
1629 default_subtype,
1630 &list, &preamble, &epilogue);
1631 if (r == MAILIMF_NO_ERROR) {
1632 /* do nothing */
1633 }
1634 else if (r == MAILIMF_ERROR_PARSE) {
1635 list = clist_new();
1636 if (list == NULL) {
1637 res = MAILIMF_ERROR_MEMORY;
1638 goto free_content;
1639 }
1640 }
1641 else {
1642 res = r;
1643 goto free_content;
1644 }
1645
1646 free(boundary);
1647 }
1648 break;
1649
1650 default: /* MAILMIME_SINGLE */
1651 /* do nothing */
1652 break;
1653 }
1654
1655 mime = mailmime_new(body_type, message, length,
1656 mime_fields, content_type,
1657 body, preamble, /* preamble */
1658 epilogue, /* epilogue */
1659 list, fields, msg_mime);
1660 if (mime == NULL) {
1661 res = MAILIMF_ERROR_MEMORY;
1662 goto free;
1663 }
1664
1665 * result = mime;
1666 * index = length;
1667
1668 return MAILIMF_NO_ERROR;
1669
1670 free:
1671 if (epilogue != NULL)
1672 mailmime_data_free(epilogue);
1673 if (preamble != NULL)
1674 mailmime_data_free(preamble);
1675 if (msg_mime != NULL)
1676 mailmime_free(msg_mime);
1677 if (list != NULL) {
1678 clist_foreach(list, (clist_func) mailmime_free, NULL);
1679 clist_free(list);
1680 }
1681 free_content:
1682 mailmime_content_free(content_type);
1683 err:
1684 return res;
1685}
1686
1687static int mailmime_get_section_list(struct mailmime * mime,
1688 clistiter * list, struct mailmime ** result)
1689{
1690 uint32_t id;
1691 struct mailmime * data;
1692 struct mailmime * submime;
1693
1694 if (list == NULL) {
1695 * result = mime;
1696 return MAILIMF_NO_ERROR;
1697 }
1698
1699 id = * ((uint32_t *) clist_content(list));
1700
1701 data = NULL;
1702 switch (mime->mm_type) {
1703 case MAILMIME_SINGLE:
1704 return MAILIMF_ERROR_INVAL;
1705
1706 case MAILMIME_MULTIPLE:
1707 data = clist_nth_data(mime->mm_data.mm_multipart.mm_mp_list, id - 1);
1708 if (data == NULL)
1709 return MAILIMF_ERROR_INVAL;
1710
1711 if (clist_next(list) != NULL)
1712 return mailmime_get_section_list(data, clist_next(list), result);
1713 else {
1714 * result = data;
1715 return MAILIMF_NO_ERROR;
1716 }
1717
1718 case MAILMIME_MESSAGE:
1719 submime = mime->mm_data.mm_message.mm_msg_mime;
1720 switch (submime->mm_type) {
1721 case MAILMIME_MULTIPLE:
1722 data = clist_nth_data(submime->mm_data.mm_multipart.mm_mp_list, id - 1);
1723 if (data == NULL)
1724 return MAILIMF_ERROR_INVAL;
1725 return mailmime_get_section_list(data, clist_next(list), result);
1726
1727 default:
1728 if (id != 1)
1729 return MAILIMF_ERROR_INVAL;
1730
1731 data = submime;
1732 if (data == NULL)
1733 return MAILIMF_ERROR_INVAL;
1734
1735 return mailmime_get_section_list(data, clist_next(list), result);
1736 }
1737 break;
1738
1739 default:
1740 return MAILIMF_ERROR_INVAL;
1741 }
1742}
1743
1744int mailmime_get_section(struct mailmime * mime,
1745 struct mailmime_section * section,
1746 struct mailmime ** result)
1747{
1748 return mailmime_get_section_list(mime,
1749 clist_begin(section->sec_list), result);
1750}
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766/* ************************************************************************* */
1767/* MIME part decoding */
1768
1769static inline signed char get_base64_value(char ch)
1770{
1771 if ((ch >= 'A') && (ch <= 'Z'))
1772 return ch - 'A';
1773 if ((ch >= 'a') && (ch <= 'z'))
1774 return ch - 'a' + 26;
1775 if ((ch >= '0') && (ch <= '9'))
1776 return ch - '0' + 52;
1777 switch (ch) {
1778 case '+':
1779 return 62;
1780 case '/':
1781 return 63;
1782 case '=': /* base64 padding */
1783 return -1;
1784 default:
1785 return -1;
1786 }
1787}
1788
1789int mailmime_base64_body_parse(const char * message, size_t length,
1790 size_t * index, char ** result,
1791 size_t * result_len)
1792{
1793 size_t cur_token;
1794 size_t i;
1795 char chunk[4];
1796 int chunk_index;
1797 char out[3];
1798 MMAPString * mmapstr;
1799 int res;
1800 int r;
1801 size_t written;
1802
1803 cur_token = * index;
1804 chunk_index = 0;
1805 written = 0;
1806
1807 mmapstr = mmap_string_sized_new((length - cur_token) * 3 / 4);
1808 if (mmapstr == NULL) {
1809 res = MAILIMF_ERROR_MEMORY;
1810 goto err;
1811 }
1812
1813 i = 0;
1814 while (1) {
1815 signed char value;
1816
1817 value = -1;
1818 while (value == -1) {
1819
1820 if (cur_token >= length)
1821 break;
1822
1823 value = get_base64_value(message[cur_token]);
1824 cur_token ++;
1825 }
1826
1827 if (value == -1)
1828 break;
1829
1830 chunk[chunk_index] = value;
1831 chunk_index ++;
1832
1833 if (chunk_index == 4) {
1834 out[0] = (chunk[0] << 2) | (chunk[1] >> 4);
1835 out[1] = (chunk[1] << 4) | (chunk[2] >> 2);
1836 out[2] = (chunk[2] << 6) | (chunk[3]);
1837
1838 chunk[0] = 0;
1839 chunk[1] = 0;
1840 chunk[2] = 0;
1841 chunk[3] = 0;
1842
1843 chunk_index = 0;
1844
1845 if (mmap_string_append_len(mmapstr, out, 3) == NULL) {
1846 res = MAILIMF_ERROR_MEMORY;
1847 goto free;
1848 }
1849 written += 3;
1850 }
1851 }
1852
1853 if (chunk_index != 0) {
1854 size_t len;
1855
1856 len = 0;
1857 out[0] = (chunk[0] << 2) | (chunk[1] >> 4);
1858 len ++;
1859
1860 if (chunk_index >= 3) {
1861 out[1] = (chunk[1] << 4) | (chunk[2] >> 2);
1862 len ++;
1863 }
1864
1865 if (mmap_string_append_len(mmapstr, out, len) == NULL) {
1866 res = MAILIMF_ERROR_MEMORY;
1867 goto free;
1868 }
1869 written += len;
1870 }
1871
1872 r = mmap_string_ref(mmapstr);
1873 if (r < 0) {
1874 res = MAILIMF_ERROR_MEMORY;
1875 goto free;
1876 }
1877
1878 * index = cur_token;
1879 * result = mmapstr->str;
1880 * result_len = written;
1881
1882 return MAILIMF_NO_ERROR;
1883
1884 free:
1885 mmap_string_free(mmapstr);
1886 err:
1887 return res;
1888}
1889
1890
1891
1892static inline int hexa_to_char(char hexdigit)
1893{
1894 if ((hexdigit >= '0') && (hexdigit <= '9'))
1895 return hexdigit - '0';
1896 if ((hexdigit >= 'a') && (hexdigit <= 'f'))
1897 return hexdigit - 'a' + 10;
1898 if ((hexdigit >= 'A') && (hexdigit <= 'F'))
1899 return hexdigit - 'A' + 10;
1900 return 0;
1901}
1902
1903static inline char to_char(const char * hexa)
1904{
1905 return (hexa_to_char(hexa[0]) << 4) | hexa_to_char(hexa[1]);
1906}
1907
1908enum {
1909 STATE_NORMAL,
1910 STATE_CODED,
1911 STATE_OUT,
1912 STATE_CR,
1913};
1914
1915
1916static int write_decoded_qp(MMAPString * mmapstr,
1917 const char * start, size_t count)
1918{
1919 if (mmap_string_append_len(mmapstr, start, count) == NULL)
1920 return MAILIMF_ERROR_MEMORY;
1921
1922 return MAILIMF_NO_ERROR;
1923}
1924
1925
1926#define WRITE_MAX_QP 512
1927
1928int mailmime_quoted_printable_body_parse(const char * message, size_t length,
1929 size_t * index, char ** result,
1930 size_t * result_len, int in_header)
1931{
1932 size_t cur_token;
1933 int state;
1934 int r;
1935 char ch;
1936 size_t count;
1937 const char * start;
1938 MMAPString * mmapstr;
1939 int res;
1940 size_t written;
1941
1942 state = STATE_NORMAL;
1943 cur_token = * index;
1944
1945 count = 0;
1946 start = message + cur_token;
1947 written = 0;
1948
1949 mmapstr = mmap_string_sized_new(length - cur_token);
1950 if (mmapstr == NULL) {
1951 res = MAILIMF_ERROR_MEMORY;
1952 goto err;
1953 }
1954
1955#if 0
1956 if (length >= 1) {
1957 if (message[length - 1] == '\n') {
1958 length --;
1959 if (length >= 1)
1960 if (message[length - 1] == '\r') {
1961 length --;
1962 }
1963 }
1964 }
1965#endif
1966
1967 while (state != STATE_OUT) {
1968
1969 if (cur_token >= length) {
1970 state = STATE_OUT;
1971 break;
1972 }
1973
1974 switch (state) {
1975
1976 case STATE_CODED:
1977
1978 if (count > 0) {
1979 r = write_decoded_qp(mmapstr, start, count);
1980 if (r != MAILIMF_NO_ERROR) {
1981 res = r;
1982 goto free;
1983 }
1984 written += count;
1985 count = 0;
1986 }
1987
1988 switch (message[cur_token]) {
1989 case '=':
1990 if (cur_token + 1 >= length) {
1991 /* error but ignore it */
1992 state = STATE_NORMAL;
1993 start = message + cur_token;
1994 cur_token ++;
1995 count ++;
1996 break;
1997 }
1998
1999 switch (message[cur_token + 1]) {
2000
2001 case '\n':
2002 cur_token += 2;
2003
2004 start = message + cur_token;
2005
2006 state = STATE_NORMAL;
2007 break;
2008
2009 case '\r':
2010 if (cur_token + 2 >= length) {
2011 state = STATE_OUT;
2012 break;
2013 }
2014
2015 if (message[cur_token + 2] == '\n')
2016 cur_token += 3;
2017 else
2018 cur_token += 2;
2019
2020 start = message + cur_token;
2021
2022 state = STATE_NORMAL;
2023
2024 break;
2025
2026 default:
2027 if (cur_token + 2 >= length) {
2028 /* error but ignore it */
2029 cur_token ++;
2030
2031 start = message + cur_token;
2032
2033 count ++;
2034 state = STATE_NORMAL;
2035 break;
2036 }
2037
2038#if 0
2039 /* flush before writing additionnal information */
2040 r = write_decoded_qp(mmapstr, start, count);
2041 if (r != MAILIMF_NO_ERROR) {
2042 res = r;
2043 goto free;
2044 }
2045 written += count;
2046 count = 0;
2047#endif
2048
2049 ch = to_char(message + cur_token + 1);
2050
2051 if (mmap_string_append_c(mmapstr, ch) == NULL) {
2052 res = MAILIMF_ERROR_MEMORY;
2053 goto free;
2054 }
2055
2056 cur_token += 3;
2057 written ++;
2058
2059 start = message + cur_token;
2060
2061 state = STATE_NORMAL;
2062 break;
2063 }
2064 break;
2065 }
2066 break; /* end of STATE_ENCODED */
2067
2068 case STATE_NORMAL:
2069
2070 switch (message[cur_token]) {
2071
2072 case '=':
2073 state = STATE_CODED;
2074 break;
2075
2076 case '\n':
2077 /* flush before writing additionnal information */
2078 if (count > 0) {
2079 r = write_decoded_qp(mmapstr, start, count);
2080 if (r != MAILIMF_NO_ERROR) {
2081 res = r;
2082 goto free;
2083 }
2084 written += count;
2085
2086 count = 0;
2087 }
2088
2089 r = write_decoded_qp(mmapstr, "\r\n", 2);
2090 if (r != MAILIMF_NO_ERROR) {
2091 res = r;
2092 goto free;
2093 }
2094 written += 2;
2095 cur_token ++;
2096 start = message + cur_token;
2097 break;
2098
2099 case '\r':
2100 state = STATE_CR;
2101 cur_token ++;
2102 break;
2103
2104 case '_':
2105 if (in_header) {
2106 if (count > 0) {
2107 r = write_decoded_qp(mmapstr, start, count);
2108 if (r != MAILIMF_NO_ERROR) {
2109 res = r;
2110 goto free;
2111 }
2112 written += count;
2113 count = 0;
2114 }
2115
2116 if (mmap_string_append_c(mmapstr, ' ') == NULL) {
2117 res = MAILIMF_ERROR_MEMORY;
2118 goto free;
2119 }
2120
2121 written ++;
2122 cur_token ++;
2123 start = message + cur_token;
2124
2125 break;
2126 }
2127 /* WARINING : must be followed by switch default action */
2128
2129 default:
2130 if (count >= WRITE_MAX_QP) {
2131 r = write_decoded_qp(mmapstr, start, count);
2132 if (r != MAILIMF_NO_ERROR) {
2133 res = r;
2134 goto free;
2135 }
2136 written += count;
2137 count = 0;
2138 start = message + cur_token;
2139 }
2140
2141 count ++;
2142 cur_token ++;
2143 break;
2144 }
2145 break; /* end of STATE_NORMAL */
2146
2147 case STATE_CR:
2148 switch (message[cur_token]) {
2149
2150 case '\n':
2151 /* flush before writing additionnal information */
2152 if (count > 0) {
2153 r = write_decoded_qp(mmapstr, start, count);
2154 if (r != MAILIMF_NO_ERROR) {
2155 res = r;
2156 goto free;
2157 }
2158 written += count;
2159 count = 0;
2160 }
2161
2162 r = write_decoded_qp(mmapstr, "\r\n", 2);
2163 if (r != MAILIMF_NO_ERROR) {
2164 res = r;
2165 goto free;
2166 }
2167 written += 2;
2168 cur_token ++;
2169 start = message + cur_token;
2170 state = STATE_NORMAL;
2171 break;
2172
2173 default:
2174 /* flush before writing additionnal information */
2175 if (count > 0) {
2176 r = write_decoded_qp(mmapstr, start, count);
2177 if (r != MAILIMF_NO_ERROR) {
2178 res = r;
2179 goto free;
2180 }
2181 written += count;
2182 count = 0;
2183 }
2184
2185 start = message + cur_token;
2186
2187 r = write_decoded_qp(mmapstr, "\r\n", 2);
2188 if (r != MAILIMF_NO_ERROR) {
2189 res = r;
2190 goto free;
2191 }
2192 written += 2;
2193 state = STATE_NORMAL;
2194 }
2195 break; /* end of STATE_CR */
2196 }
2197 }
2198
2199 if (count > 0) {
2200 r = write_decoded_qp(mmapstr, start, count);
2201 if (r != MAILIMF_NO_ERROR) {
2202 res = r;
2203 goto free;
2204 }
2205 written += count;
2206 count = 0;
2207 }
2208
2209 r = mmap_string_ref(mmapstr);
2210 if (r < 0) {
2211 res = MAILIMF_ERROR_MEMORY;
2212 goto free;
2213 }
2214
2215 * index = cur_token;
2216 * result = mmapstr->str;
2217 * result_len = written;
2218
2219 return MAILIMF_NO_ERROR;
2220
2221 free:
2222 mmap_string_free(mmapstr);
2223 err:
2224 return res;
2225}
2226
2227int mailmime_binary_body_parse(const char * message, size_t length,
2228 size_t * index, char ** result,
2229 size_t * result_len)
2230{
2231 MMAPString * mmapstr;
2232 size_t cur_token;
2233 int r;
2234 int res;
2235
2236 cur_token = * index;
2237
2238 if (length >= 1) {
2239 if (message[length - 1] == '\n') {
2240 length --;
2241 if (length >= 1)
2242 if (message[length - 1] == '\r')
2243 length --;
2244 }
2245 }
2246
2247 mmapstr = mmap_string_new_len(message + cur_token, length - cur_token);
2248 if (mmapstr == NULL) {
2249 res = MAILIMF_ERROR_MEMORY;
2250 goto err;
2251 }
2252
2253 r = mmap_string_ref(mmapstr);
2254 if (r < 0) {
2255 res = MAILIMF_ERROR_MEMORY;
2256 goto free;
2257 }
2258
2259 * index = length;
2260 * result = mmapstr->str;
2261 * result_len = length - cur_token;
2262
2263 return MAILIMF_NO_ERROR;
2264
2265 free:
2266 mmap_string_free(mmapstr);
2267 err:
2268 return res;
2269}
2270
2271
2272int mailmime_part_parse(const char * message, size_t length,
2273 size_t * index,
2274 int encoding, char ** result, size_t * result_len)
2275{
2276 switch (encoding) {
2277 case MAILMIME_MECHANISM_BASE64:
2278 return mailmime_base64_body_parse(message, length, index,
2279 result, result_len);
2280
2281 case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
2282 return mailmime_quoted_printable_body_parse(message, length, index,
2283 result, result_len, FALSE);
2284
2285 case MAILMIME_MECHANISM_7BIT:
2286 case MAILMIME_MECHANISM_8BIT:
2287 case MAILMIME_MECHANISM_BINARY:
2288 default:
2289 return mailmime_binary_body_parse(message, length, index,
2290 result, result_len);
2291 }
2292}
2293
2294int mailmime_get_section_id(struct mailmime * mime,
2295 struct mailmime_section ** result)
2296{
2297 clist * list;
2298 int res;
2299 struct mailmime_section * section_id;
2300 int r;
2301
2302 if (mime->mm_parent == NULL) {
2303 list = clist_new();
2304 if (list == NULL) {
2305 res = MAILIMF_ERROR_MEMORY;
2306 goto err;
2307 }
2308
2309 section_id = mailmime_section_new(list);
2310 if (section_id == NULL) {
2311 res = MAILIMF_ERROR_MEMORY;
2312 goto err;
2313 }
2314 }
2315 else {
2316 uint32_t id;
2317 uint32_t * p_id;
2318 clistiter * cur;
2319 struct mailmime * parent;
2320
2321 r = mailmime_get_section_id(mime->mm_parent, &section_id);
2322 if (r != MAILIMF_NO_ERROR) {
2323 res = r;
2324 goto err;
2325 }
2326
2327 parent = mime->mm_parent;
2328 switch (parent->mm_type) {
2329 case MAILMIME_MULTIPLE:
2330 id = 1;
2331 for(cur = clist_begin(parent->mm_data.mm_multipart.mm_mp_list) ;
2332 cur != NULL ; cur = clist_next(cur)) {
2333 if (clist_content(cur) == mime)
2334 break;
2335 id ++;
2336 }
2337
2338 p_id = malloc(sizeof(* p_id));
2339 if (p_id == NULL) {
2340 res = MAILIMF_ERROR_MEMORY;
2341 goto free;
2342 }
2343 * p_id = id;
2344
2345 r = clist_append(section_id->sec_list, p_id);
2346 if (r < 0) {
2347 free(p_id);
2348 res = MAILIMF_ERROR_MEMORY;
2349 goto free;
2350 }
2351 break;
2352
2353 case MAILMIME_MESSAGE:
2354 if ((mime->mm_type == MAILMIME_SINGLE) ||
2355 (mime->mm_type == MAILMIME_MESSAGE)) {
2356 p_id = malloc(sizeof(* p_id));
2357 if (p_id == NULL) {
2358 res = MAILIMF_ERROR_MEMORY;
2359 goto free;
2360 }
2361 * p_id = 1;
2362
2363 r = clist_append(section_id->sec_list, p_id);
2364 if (r < 0) {
2365 free(p_id);
2366 res = MAILIMF_ERROR_MEMORY;
2367 goto free;
2368 }
2369 }
2370 }
2371 }
2372
2373 * result = section_id;
2374
2375 return MAILIMF_NO_ERROR;
2376
2377 free:
2378 mailmime_section_free(section_id);
2379 err:
2380 return res;
2381}
diff --git a/libetpan/src/low-level/mime/mailmime_content.h b/libetpan/src/low-level/mime/mailmime_content.h
new file mode 100644
index 0000000..989e515
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_content.h
@@ -0,0 +1,89 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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/libetpan/src/low-level/mime/mailmime_decode.c b/libetpan/src/low-level/mime/mailmime_decode.c
new file mode 100644
index 0000000..715ddad
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_decode.c
@@ -0,0 +1,544 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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 switch (r) {
191 case MAIL_CHARCONV_ERROR_MEMORY:
192 free(raw_word);
193 res = MAILIMF_ERROR_MEMORY;
194 goto free;
195
196 case MAIL_CHARCONV_ERROR_UNKNOWN_CHARSET:
197 case MAIL_CHARCONV_ERROR_CONV:
198 free(raw_word);
199 res = MAILIMF_ERROR_PARSE;
200 goto free;
201 }
202
203 if (mmap_string_append(gphrase, wordutf8) == NULL) {
204 free(wordutf8);
205 free(raw_word);
206 res = MAILIMF_ERROR_MEMORY;
207 goto free;
208 }
209
210 free(wordutf8);
211 free(raw_word);
212 first = FALSE;
213 }
214 else if (r == MAILIMF_ERROR_PARSE) {
215 break;
216 }
217 else {
218 res = r;
219 goto free;
220 }
221 }
222 }
223
224 if (first) {
225 res = MAILIMF_ERROR_PARSE;
226 goto free;
227 }
228
229 str = strdup(gphrase->str);
230 if (str == NULL) {
231 res = MAILIMF_ERROR_MEMORY;
232 goto free;
233 }
234 mmap_string_free(gphrase);
235
236 * result = str;
237 * index = cur_token;
238
239 return MAILIMF_NO_ERROR;
240
241 free:
242 mmap_string_free(gphrase);
243 err:
244 return res;
245}
246
247static int
248mailmime_non_encoded_word_parse(const char * message, size_t length,
249 size_t * index,
250 char ** result)
251{
252 int end;
253 size_t cur_token;
254 int res;
255 char * text;
256 int r;
257 size_t begin;
258
259 cur_token = * index;
260
261 r = mailimf_fws_parse(message, length, &cur_token);
262 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
263 res = r;
264 goto err;
265 }
266
267 begin = cur_token;
268
269 end = FALSE;
270 while (1) {
271 if (cur_token >= length)
272 break;
273
274 switch (message[cur_token]) {
275 case ' ':
276 case '\t':
277 case '\r':
278 case '\n':
279 end = TRUE;
280 break;
281 }
282
283 if (end)
284 break;
285
286 cur_token ++;
287 }
288
289 if (cur_token - begin == 0) {
290 res = MAILIMF_ERROR_PARSE;
291 goto err;
292 }
293
294 text = malloc(cur_token - begin + 1);
295 if (text == NULL) {
296 res = MAILIMF_ERROR_MEMORY;
297 goto err;
298 }
299
300 memcpy(text, message + begin, cur_token - begin);
301 text[cur_token - begin] = '\0';
302
303 * index = cur_token;
304 * result = text;
305
306 return MAILIMF_NO_ERROR;
307
308 err:
309 return res;
310}
311
312static int mailmime_encoded_word_parse(const char * message, size_t length,
313 size_t * index,
314 struct mailmime_encoded_word ** result)
315{
316 size_t cur_token;
317 char * charset;
318 int encoding;
319 char * text;
320 size_t end_encoding;
321 char * decoded;
322 size_t decoded_len;
323 struct mailmime_encoded_word * ew;
324 int r;
325 int res;
326 int opening_quote;
327 int end;
328
329 cur_token = * index;
330
331 r = mailimf_fws_parse(message, length, &cur_token);
332 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
333 res = r;
334 goto err;
335 }
336
337 opening_quote = FALSE;
338 r = mailimf_char_parse(message, length, &cur_token, '\"');
339 if (r == MAILIMF_NO_ERROR) {
340 opening_quote = TRUE;
341 }
342 else if (r == MAILIMF_ERROR_PARSE) {
343 /* do nothing */
344 }
345 else {
346 res = r;
347 goto err;
348 }
349
350 r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "=?");
351 if (r != MAILIMF_NO_ERROR) {
352 res = r;
353 goto err;
354 }
355
356 r = mailmime_charset_parse(message, length, &cur_token, &charset);
357 if (r != MAILIMF_NO_ERROR) {
358 res = r;
359 goto err;
360 }
361
362 r = mailimf_char_parse(message, length, &cur_token, '?');
363 if (r != MAILIMF_NO_ERROR) {
364 res = r;
365 goto free_charset;
366 }
367
368 r = mailmime_encoding_parse(message, length, &cur_token, &encoding);
369 if (r != MAILIMF_NO_ERROR) {
370 res = r;
371 goto free_charset;
372 }
373
374 r = mailimf_char_parse(message, length, &cur_token, '?');
375 if (r != MAILIMF_NO_ERROR) {
376 res = r;
377 goto free_charset;
378 }
379
380 end = FALSE;
381 end_encoding = cur_token;
382 while (1) {
383 if (end_encoding >= length)
384 break;
385
386 switch (message[end_encoding]) {
387 case '?':
388#if 0
389 case ' ':
390#endif
391 end = TRUE;
392 break;
393 }
394
395 if (end)
396 break;
397
398 end_encoding ++;
399 }
400
401 decoded_len = 0;
402 decoded = NULL;
403 switch (encoding) {
404 case MAILMIME_ENCODING_B:
405 r = mailmime_base64_body_parse(message, end_encoding,
406 &cur_token, &decoded,
407 &decoded_len);
408
409 if (r != MAILIMF_NO_ERROR) {
410 res = r;
411 goto free_charset;
412 }
413 break;
414 case MAILMIME_ENCODING_Q:
415 r = mailmime_quoted_printable_body_parse(message, end_encoding,
416 &cur_token, &decoded,
417 &decoded_len, TRUE);
418
419 if (r != MAILIMF_NO_ERROR) {
420 res = r;
421 goto free_charset;
422 }
423
424 break;
425 }
426
427 text = malloc(decoded_len + 1);
428 if (text == NULL) {
429 res = MAILIMF_ERROR_MEMORY;
430 goto free_charset;
431 }
432
433 if (decoded_len > 0)
434 memcpy(text, decoded, decoded_len);
435 text[decoded_len] = '\0';
436
437 mailmime_decoded_part_free(decoded);
438
439 r = mailimf_token_case_insensitive_parse(message, length, &cur_token, "?=");
440 if (r != MAILIMF_NO_ERROR) {
441 res = r;
442 goto free_encoded_text;
443 }
444
445 if (opening_quote) {
446 r = mailimf_char_parse(message, length, &cur_token, '\"');
447 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
448 res = r;
449 goto free_encoded_text;
450 }
451 }
452
453 ew = mailmime_encoded_word_new(charset, text);
454 if (ew == NULL) {
455 res = MAILIMF_ERROR_MEMORY;
456 goto free_encoded_text;
457 }
458
459 * result = ew;
460 * index = cur_token;
461
462 return MAILIMF_NO_ERROR;
463
464 free_encoded_text:
465 mailmime_encoded_text_free(text);
466 free_charset:
467 mailmime_charset_free(charset);
468 err:
469 return res;
470}
471
472static int mailmime_charset_parse(const char * message, size_t length,
473 size_t * index, char ** charset)
474{
475 return mailmime_etoken_parse(message, length, index, charset);
476}
477
478static int mailmime_encoding_parse(const char * message, size_t length,
479 size_t * index, int * result)
480{
481 size_t cur_token;
482 int encoding;
483
484 cur_token = * index;
485
486 if (cur_token >= length)
487 return MAILIMF_ERROR_PARSE;
488
489 switch ((char) toupper((unsigned char) message[cur_token])) {
490 case 'Q':
491 encoding = MAILMIME_ENCODING_Q;
492 break;
493 case 'B':
494 encoding = MAILMIME_ENCODING_B;
495 break;
496 default:
497 return MAILIMF_ERROR_INVAL;
498 }
499
500 cur_token ++;
501
502 * result = encoding;
503 * index = cur_token;
504
505 return MAILIMF_NO_ERROR;
506}
507
508int is_etoken_char(char ch)
509{
510 unsigned char uch = ch;
511
512 if (uch < 31)
513 return FALSE;
514
515 switch (uch) {
516 case ' ':
517 case '(':
518 case ')':
519 case '<':
520 case '>':
521 case '@':
522 case ',':
523 case ';':
524 case ':':
525 case '"':
526 case '/':
527 case '[':
528 case ']':
529 case '?':
530 case '.':
531 case '=':
532 return FALSE;
533 }
534
535 return TRUE;
536}
537
538static int mailmime_etoken_parse(const char * message, size_t length,
539 size_t * index, char ** result)
540{
541 return mailimf_custom_string_parse(message, length,
542 index, result,
543 is_etoken_char);
544}
diff --git a/libetpan/src/low-level/mime/mailmime_decode.h b/libetpan/src/low-level/mime/mailmime_decode.h
new file mode 100644
index 0000000..7b9d693
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_decode.h
@@ -0,0 +1,55 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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/libetpan/src/low-level/mime/mailmime_disposition.c b/libetpan/src/low-level/mime/mailmime_disposition.c
new file mode 100644
index 0000000..eb1d846
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_disposition.c
@@ -0,0 +1,595 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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/libetpan/src/low-level/mime/mailmime_disposition.h b/libetpan/src/low-level/mime/mailmime_disposition.h
new file mode 100644
index 0000000..e992d7c
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_disposition.h
@@ -0,0 +1,62 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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/libetpan/src/low-level/mime/mailmime_types.c b/libetpan/src/low-level/mime/mailmime_types.c
new file mode 100644
index 0000000..115d17f
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_types.c
@@ -0,0 +1,753 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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 switch (mime->mm_type) {
462 case MAILMIME_SINGLE:
463 if ((mime->mm_body == NULL) && (mime->mm_data.mm_single != NULL))
464 mailmime_data_free(mime->mm_data.mm_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_body != NULL)
487 mailmime_data_free(mime->mm_body);
488
489 if (mime->mm_mime_fields != NULL)
490 mailmime_fields_free(mime->mm_mime_fields);
491 if (mime->mm_content_type != NULL)
492 mailmime_content_free(mime->mm_content_type);
493 free(mime);
494}
495
496
497
498struct mailmime_encoded_word *
499mailmime_encoded_word_new(char * wd_charset, char * wd_text)
500{
501 struct mailmime_encoded_word * ew;
502
503 ew = malloc(sizeof(* ew));
504 if (ew == NULL)
505 return NULL;
506 ew->wd_charset = wd_charset;
507 ew->wd_text = wd_text;
508
509 return ew;
510}
511
512void mailmime_charset_free(char * charset)
513{
514 free(charset);
515}
516
517void mailmime_encoded_text_free(char * text)
518{
519 free(text);
520}
521
522void mailmime_encoded_word_free(struct mailmime_encoded_word * ew)
523{
524 mailmime_charset_free(ew->wd_charset);
525 mailmime_encoded_text_free(ew->wd_text);
526 free(ew);
527}
528
529
530
531/* mailmime_disposition */
532
533
534struct mailmime_disposition *
535mailmime_disposition_new(struct mailmime_disposition_type * dsp_type,
536 clist * dsp_parms)
537{
538 struct mailmime_disposition * dsp;
539
540 dsp = malloc(sizeof(* dsp));
541 if (dsp == NULL)
542 return NULL;
543 dsp->dsp_type = dsp_type;
544 dsp->dsp_parms = dsp_parms;
545
546 return dsp;
547}
548
549void mailmime_disposition_free(struct mailmime_disposition * dsp)
550{
551 mailmime_disposition_type_free(dsp->dsp_type);
552 clist_foreach(dsp->dsp_parms,
553 (clist_func) mailmime_disposition_parm_free, NULL);
554 clist_free(dsp->dsp_parms);
555 free(dsp);
556}
557
558
559
560struct mailmime_disposition_type *
561mailmime_disposition_type_new(int dsp_type, char * dsp_extension)
562{
563 struct mailmime_disposition_type * m_dsp_type;
564
565 m_dsp_type = malloc(sizeof(* m_dsp_type));
566 if (m_dsp_type == NULL)
567 return NULL;
568
569 m_dsp_type->dsp_type = dsp_type;
570 m_dsp_type->dsp_extension = dsp_extension;
571
572 return m_dsp_type;
573}
574
575void mailmime_disposition_type_free(struct mailmime_disposition_type * dsp_type)
576{
577 if (dsp_type->dsp_extension != NULL)
578 free(dsp_type->dsp_extension);
579 free(dsp_type);
580}
581
582
583struct mailmime_disposition_parm *
584mailmime_disposition_parm_new(int pa_type,
585 char * pa_filename,
586 char * pa_creation_date,
587 char * pa_modification_date,
588 char * pa_read_date,
589 size_t pa_size,
590 struct mailmime_parameter * pa_parameter)
591{
592 struct mailmime_disposition_parm * dsp_parm;
593
594 dsp_parm = malloc(sizeof(* dsp_parm));
595 if (dsp_parm == NULL)
596 return NULL;
597
598 dsp_parm->pa_type = pa_type;
599 switch (pa_type) {
600 case MAILMIME_DISPOSITION_PARM_FILENAME:
601 dsp_parm->pa_data.pa_filename = pa_filename;
602 break;
603 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
604 dsp_parm->pa_data.pa_creation_date = pa_creation_date;
605 break;
606 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
607 dsp_parm->pa_data.pa_modification_date = pa_modification_date;
608 break;
609 case MAILMIME_DISPOSITION_PARM_READ_DATE:
610 dsp_parm->pa_data.pa_read_date = pa_read_date;
611 break;
612 case MAILMIME_DISPOSITION_PARM_SIZE:
613 dsp_parm->pa_data.pa_size = pa_size;
614 break;
615 case MAILMIME_DISPOSITION_PARM_PARAMETER:
616 dsp_parm->pa_data.pa_parameter = pa_parameter;
617 break;
618 }
619
620 return dsp_parm;
621}
622
623void mailmime_disposition_parm_free(struct mailmime_disposition_parm *
624 dsp_parm)
625{
626 switch (dsp_parm->pa_type) {
627 case MAILMIME_DISPOSITION_PARM_FILENAME:
628 mailmime_filename_parm_free(dsp_parm->pa_data.pa_filename);
629 break;
630 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
631 mailmime_creation_date_parm_free(dsp_parm->pa_data.pa_creation_date);
632 break;
633 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
634 mailmime_modification_date_parm_free(dsp_parm->pa_data.pa_modification_date);
635 break;
636 case MAILMIME_DISPOSITION_PARM_READ_DATE:
637 mailmime_read_date_parm_free(dsp_parm->pa_data.pa_read_date);
638 break;
639 case MAILMIME_DISPOSITION_PARM_PARAMETER:
640 mailmime_parameter_free(dsp_parm->pa_data.pa_parameter);
641 break;
642 }
643
644 free(dsp_parm);
645}
646
647
648void mailmime_filename_parm_free(char * filename)
649{
650 mailmime_value_free(filename);
651}
652
653void mailmime_creation_date_parm_free(char * date)
654{
655 mailmime_quoted_date_time_free(date);
656}
657
658void mailmime_modification_date_parm_free(char * date)
659{
660 mailmime_quoted_date_time_free(date);
661}
662
663void mailmime_read_date_parm_free(char * date)
664{
665 mailmime_quoted_date_time_free(date);
666}
667
668void mailmime_quoted_date_time_free(char * date)
669{
670 mailimf_quoted_string_free(date);
671}
672
673struct mailmime_section * mailmime_section_new(clist * sec_list)
674{
675 struct mailmime_section * section;
676
677 section = malloc(sizeof(* section));
678 if (section == NULL)
679 return NULL;
680
681 section->sec_list = sec_list;
682
683 return section;
684}
685
686void mailmime_section_free(struct mailmime_section * section)
687{
688 clist_foreach(section->sec_list, (clist_func) free, NULL);
689 clist_free(section->sec_list);
690 free(section);
691}
692
693
694
695struct mailmime_language * mailmime_language_new(clist * lg_list)
696{
697 struct mailmime_language * lang;
698
699 lang = malloc(sizeof(* lang));
700 if (lang == NULL)
701 return NULL;
702
703 lang->lg_list = lg_list;
704
705 return lang;
706}
707
708void mailmime_language_free(struct mailmime_language * lang)
709{
710 clist_foreach(lang->lg_list, (clist_func) mailimf_atom_free, NULL);
711 clist_free(lang->lg_list);
712 free(lang);
713}
714
715void mailmime_decoded_part_free(char * part)
716{
717 mmap_string_unref(part);
718}
719
720struct mailmime_data * mailmime_data_new(int dt_type, int dt_encoding,
721 int dt_encoded, const char * dt_data, size_t dt_length, char * dt_filename)
722{
723 struct mailmime_data * mime_data;
724
725 mime_data = malloc(sizeof(* mime_data));
726 if (mime_data == NULL)
727 return NULL;
728
729 mime_data->dt_type = dt_type;
730 mime_data->dt_encoding = dt_encoding;
731 mime_data->dt_encoded = dt_encoded;
732 switch (dt_type) {
733 case MAILMIME_DATA_TEXT:
734 mime_data->dt_data.dt_text.dt_data = dt_data;
735 mime_data->dt_data.dt_text.dt_length = dt_length;
736 break;
737 case MAILMIME_DATA_FILE:
738 mime_data->dt_data.dt_filename = dt_filename;
739 break;
740 }
741
742 return mime_data;
743}
744
745void mailmime_data_free(struct mailmime_data * mime_data)
746{
747 switch (mime_data->dt_type) {
748 case MAILMIME_DATA_FILE:
749 free(mime_data->dt_data.dt_filename);
750 break;
751 }
752 free(mime_data);
753}
diff --git a/libetpan/src/low-level/mime/mailmime_types.h b/libetpan/src/low-level/mime/mailmime_types.h
new file mode 100644
index 0000000..21f0d96
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_types.h
@@ -0,0 +1,440 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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/libetpan/src/low-level/mime/mailmime_types_helper.c b/libetpan/src/low-level/mime/mailmime_types_helper.c
new file mode 100644
index 0000000..e45330c
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_types_helper.c
@@ -0,0 +1,1385 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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/libetpan/src/low-level/mime/mailmime_types_helper.h b/libetpan/src/low-level/mime/mailmime_types_helper.h
new file mode 100644
index 0000000..cdbbff9
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_types_helper.h
@@ -0,0 +1,165 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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/libetpan/src/low-level/mime/mailmime_write.c b/libetpan/src/low-level/mime/mailmime_write.c
new file mode 100644
index 0000000..4bce0d5
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write.c
@@ -0,0 +1,1416 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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, "%lu", (unsigned long) 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 == MAP_FAILED) {
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/libetpan/src/low-level/mime/mailmime_write.h b/libetpan/src/low-level/mime/mailmime_write.h
new file mode 100644
index 0000000..adca123
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write.h
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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
diff --git a/libetpan/src/low-level/mime/mailmime_write_file.c b/libetpan/src/low-level/mime/mailmime_write_file.c
new file mode 100644
index 0000000..3beeff8
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_file.c
@@ -0,0 +1,156 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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_file.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 "mailmime_content.h"
48#include "mailmime_types_helper.h"
49#include "mailmime_write_generic.h"
50
51static int do_write(void * data, const char * str, size_t length)
52{
53 FILE * f;
54
55 f = data;
56
57 return fwrite(str, 1, length, f);
58}
59
60
61int mailmime_fields_write_file(FILE * f, int * col,
62 struct mailmime_fields * fields)
63{
64 return mailmime_fields_write_driver(do_write, f, col, fields);
65}
66
67int mailmime_content_write_file(FILE * f, int * col,
68 struct mailmime_content * content)
69{
70 return mailmime_content_write_driver(do_write, f, col, content);
71}
72
73int mailmime_content_type_write_file(FILE * f, int * col,
74 struct mailmime_content * content)
75{
76 return mailmime_content_type_write_driver(do_write, f, col, content);
77}
78
79int mailmime_write_file(FILE * f, int * col,
80 struct mailmime * build_info)
81{
82 return mailmime_write_driver(do_write, f, col, build_info);
83}
84
85int mailmime_quoted_printable_write_file(FILE * f, int * col, int istext,
86 const char * text, size_t size)
87{
88 return mailmime_quoted_printable_write_driver(do_write, f, col,
89 istext, text, size);
90}
91
92int mailmime_base64_write_file(FILE * f, int * col,
93 const char * text, size_t size)
94{
95 return mailmime_base64_write_driver(do_write, f, col, text, size);
96}
97
98int mailmime_data_write_file(FILE * f, int * col,
99 struct mailmime_data * data,
100 int istext)
101{
102 return mailmime_data_write_driver(do_write, f, col, data, istext);
103}
104
105
106
107
108/* binary compatibility with 0.34 - begin */
109
110#ifdef MAILMIME_WRITE_COMPATIBILITY
111int mailmime_fields_write(FILE * f, int * col,
112 struct mailmime_fields * fields)
113{
114 return mailmime_fields_write_file(f, col, fields);
115}
116
117int mailmime_content_write(FILE * f, int * col,
118 struct mailmime_content * content)
119{
120 return mailmime_content_write_file(f, col, content);
121}
122
123int mailmime_content_type_write(FILE * f, int * col,
124 struct mailmime_content * content)
125{
126 return mailmime_content_type_write_file(f, col, content);
127}
128
129int mailmime_write(FILE * f, int * col,
130 struct mailmime * build_info)
131{
132 return mailmime_write_file(f, col, build_info);
133}
134
135int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
136 const char * text, size_t size)
137{
138 return mailmime_quoted_printable_write_file(f, col,
139 istext, text, size);
140}
141
142int mailmime_base64_write(FILE * f, int * col,
143 const char * text, size_t size)
144{
145 return mailmime_base64_write_file(f, col, text, size);
146}
147
148int mailmime_data_write(FILE * f, int * col,
149 struct mailmime_data * data,
150 int istext)
151{
152 return mailmime_data_write_file(f, col, data, istext);
153}
154#endif
155
156/* binary compatibility with 0.34 - end */
diff --git a/libetpan/src/low-level/mime/mailmime_write_file.h b/libetpan/src/low-level/mime/mailmime_write_file.h
new file mode 100644
index 0000000..4cfa484
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_file.h
@@ -0,0 +1,105 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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_FILE_H
37
38#define MAILMIME_WRITE_FILE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45#include <stdio.h>
46
47 //#define MAILMIME_WRITE_COMPATIBILITY
48
49
50int mailmime_fields_write_file(FILE * f, int * col,
51 struct mailmime_fields * fields);
52
53int mailmime_content_write_file(FILE * f, int * col,
54 struct mailmime_content * content);
55
56int mailmime_content_type_write_file(FILE * f, int * col,
57 struct mailmime_content * content);
58
59int mailmime_write_file(FILE * f, int * col,
60 struct mailmime * build_info);
61
62int mailmime_quoted_printable_write_file(FILE * f, int * col, int istext,
63 const char * text, size_t size);
64
65int mailmime_base64_write_file(FILE * f, int * col,
66 const char * text, size_t size);
67
68int mailmime_data_write_file(FILE * f, int * col,
69 struct mailmime_data * data,
70 int istext);
71
72
73/* binary compatibility with 0.34 - begin */
74
75#ifdef MAILMIME_WRITE_COMPATIBILITY
76int mailmime_fields_write(FILE * f, int * col,
77 struct mailmime_fields * fields);
78
79int mailmime_content_write(FILE * f, int * col,
80 struct mailmime_content * content);
81
82int mailmime_content_type_write(FILE * f, int * col,
83 struct mailmime_content * content);
84
85int mailmime_write(FILE * f, int * col,
86 struct mailmime * build_info);
87
88int mailmime_quoted_printable_write(FILE * f, int * col, int istext,
89 const char * text, size_t size);
90
91int mailmime_base64_write(FILE * f, int * col,
92 const char * text, size_t size);
93
94int mailmime_data_write(FILE * f, int * col,
95 struct mailmime_data * data,
96 int istext);
97#endif
98
99/* binary compatibility with 0.34 - end */
100
101#ifdef __cplusplus
102}
103#endif
104
105#endif
diff --git a/libetpan/src/low-level/mime/mailmime_write_generic.c b/libetpan/src/low-level/mime/mailmime_write_generic.c
new file mode 100644
index 0000000..4a55881
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_generic.c
@@ -0,0 +1,1416 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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_generic.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_generic.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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
62 struct mailmime_field * field);
63
64static int mailmime_id_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * id);
65
66static int mailmime_description_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * descr);
67
68static int mailmime_version_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, uint32_t version);
69
70static int mailmime_encoding_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
71 struct mailmime_mechanism * encoding);
72
73static int mailmime_language_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
74 struct mailmime_language * language);
75
76static int mailmime_disposition_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
77 struct mailmime_disposition *
78 disposition);
79
80static int
81mailmime_disposition_param_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
82 struct mailmime_disposition_parm * param);
83
84static int mailmime_parameter_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
85 struct mailmime_parameter * param);
86
87/*
88static int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
89 struct mailmime_content * content);
90*/
91
92static int mailmime_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
93 struct mailmime_type * type);
94
95static int
96mailmime_discrete_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
97 struct mailmime_discrete_type * discrete_type);
98
99static int
100mailmime_composite_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
101 struct mailmime_composite_type * composite_type);
102
103static int mailmime_sub_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
104 struct mailmime * build_info);
105
106
107/* ***** */
108
109int mailmime_fields_write_driver(int (* do_write)(void *, const char *, size_t), void * data, 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_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, 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_driver(do_write, data, col, field->fld_data.fld_content);
135 break;
136
137 case MAILMIME_FIELD_TRANSFER_ENCODING:
138 r = mailmime_encoding_write_driver(do_write, data, col, field->fld_data.fld_encoding);
139 break;
140
141 case MAILMIME_FIELD_ID:
142 r = mailmime_id_write_driver(do_write, data, col, field->fld_data.fld_id);
143 break;
144
145 case MAILMIME_FIELD_DESCRIPTION:
146 r = mailmime_description_write_driver(do_write, data, col, field->fld_data.fld_description);
147 break;
148
149 case MAILMIME_FIELD_VERSION:
150 r = mailmime_version_write_driver(do_write, data, col, field->fld_data.fld_version);
151 break;
152
153 case MAILMIME_FIELD_DISPOSITION:
154 r = mailmime_disposition_write_driver(do_write, data, col, field->fld_data.fld_disposition);
155 break;
156
157 case MAILMIME_FIELD_LANGUAGE:
158 r = mailmime_language_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * id)
173{
174 int r;
175
176 r = mailimf_string_write_driver(do_write, data, col, "Content-ID: ", 12);
177 if (r != MAILIMF_NO_ERROR)
178 return r;
179
180 r = mailimf_string_write_driver(do_write, data, col, "<", 1);
181 if (r != MAILIMF_NO_ERROR)
182 return r;
183
184 r = mailimf_string_write_driver(do_write, data, col, id, strlen(id));
185 if (r != MAILIMF_NO_ERROR)
186 return r;
187
188 r = mailimf_string_write_driver(do_write, data, col, ">", 1);
189 if (r != MAILIMF_NO_ERROR)
190 return r;
191
192 r = mailimf_string_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, char * descr)
203{
204 int r;
205
206 r = mailimf_string_write_driver(do_write, data, col, "Content-Description: ", 21);
207 if (r != MAILIMF_NO_ERROR)
208 return r;
209
210 r = mailimf_string_write_driver(do_write, data, col, descr, strlen(descr));
211 if (r != MAILIMF_NO_ERROR)
212 return r;
213
214 r = mailimf_string_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, uint32_t version)
225{
226 int r;
227 char versionstr[40];
228
229 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, col, versionstr, strlen(versionstr));
236 if (r != MAILIMF_NO_ERROR)
237 return r;
238
239 r = mailimf_string_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
250 struct mailmime_mechanism * encoding)
251{
252 int r;
253
254 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, col, "7bit", 4);
261 break;
262
263 case MAILMIME_MECHANISM_8BIT:
264 r = mailimf_string_write_driver(do_write, data, col, "8bit", 4);
265 break;
266
267 case MAILMIME_MECHANISM_BINARY:
268 r = mailimf_string_write_driver(do_write, data, col, "binary", 6);
269 break;
270
271 case MAILMIME_MECHANISM_QUOTED_PRINTABLE:
272 r = mailimf_string_write_driver(do_write, data, col, "quoted-printable", 16);
273 break;
274
275 case MAILMIME_MECHANISM_BASE64:
276 r = mailimf_string_write_driver(do_write, data, col, "base64", 6);
277 break;
278
279 case MAILMIME_MECHANISM_TOKEN:
280 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
303 struct mailmime_language * language)
304{
305 int r;
306 clistiter * cur;
307 int first;
308
309 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, col, lang, len);
345 if (r != MAILIMF_NO_ERROR)
346 return r;
347 }
348
349 r = mailimf_string_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, 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_driver(do_write, data, 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_driver(do_write, data, col, "inline", 6);
376 break;
377
378 case MAILMIME_DISPOSITION_TYPE_ATTACHMENT:
379 r = mailimf_string_write_driver(do_write, data, col, "attachment", 10);
380 break;
381
382 case MAILMIME_DISPOSITION_TYPE_EXTENSION:
383 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, col, "; ", 2);
402 if (r != MAILIMF_NO_ERROR)
403 return r;
404
405 r = mailmime_disposition_param_write_driver(do_write, data, col, param);
406 if (r != MAILIMF_NO_ERROR)
407 return r;
408 }
409
410 r = mailimf_string_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, 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, "%lu", (unsigned long) 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_driver(do_write, data, 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_driver(do_write, data, col, "filename=", 9);
472 if (r != MAILIMF_NO_ERROR)
473 return r;
474
475 r = mailimf_quoted_string_write_driver(do_write, data, 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_driver(do_write, data, col, "creation-date=", 14);
483 if (r != MAILIMF_NO_ERROR)
484 return r;
485
486 r = mailimf_quoted_string_write_driver(do_write, data, 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_driver(do_write, data, col, "modification-date=", 18);
494 if (r != MAILIMF_NO_ERROR)
495 return r;
496
497 r = mailimf_quoted_string_write_driver(do_write, data, 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_driver(do_write, data, col, "read-date=", 10);
506 if (r != MAILIMF_NO_ERROR)
507 return r;
508
509 r = mailimf_quoted_string_write_driver(do_write, data, 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_driver(do_write, data, col, "size=", 5);
517 if (r != MAILIMF_NO_ERROR)
518 return r;
519
520 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
536 struct mailmime_parameter * param)
537{
538 int r;
539
540 r = mailimf_string_write_driver(do_write, data, col, param->pa_name,
541 strlen(param->pa_name));
542 if (r != MAILIMF_NO_ERROR)
543 return r;
544
545 r = mailimf_string_write_driver(do_write, data, col, "=", 1);
546 if (r != MAILIMF_NO_ERROR)
547 return r;
548
549 r = mailimf_quoted_string_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
558 struct mailmime_content * content)
559{
560 clistiter * cur;
561 size_t len;
562 int r;
563
564 r = mailmime_type_write_driver(do_write, data, col, content->ct_type);
565 if (r != MAILIMF_NO_ERROR)
566 return r;
567
568 r = mailimf_string_write_driver(do_write, data, col, "/", 1);
569 if (r != MAILIMF_NO_ERROR)
570 return r;
571
572 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
612 struct mailmime_content * content)
613{
614 int r;
615
616 r = mailimf_string_write_driver(do_write, data, col, "Content-Type: ", 14);
617 if (r != MAILIMF_NO_ERROR)
618 return r;
619
620 r = mailmime_content_type_write_driver(do_write, data, col, content);
621 if (r != MAILIMF_NO_ERROR)
622 return r;
623
624 r = mailimf_string_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, 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_driver(do_write, data, col, type->tp_data.tp_discrete_type);
639 break;
640
641 case MAILMIME_TYPE_COMPOSITE_TYPE:
642 r = mailmime_composite_type_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, 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_driver(do_write, data, col, "text", 4);
665 break;
666
667 case MAILMIME_DISCRETE_TYPE_IMAGE:
668 r = mailimf_string_write_driver(do_write, data, col, "image", 5);
669 break;
670
671 case MAILMIME_DISCRETE_TYPE_AUDIO:
672 r = mailimf_string_write_driver(do_write, data, col, "audio", 5);
673 break;
674
675 case MAILMIME_DISCRETE_TYPE_VIDEO:
676 r = mailimf_string_write_driver(do_write, data, col, "video", 5);
677 break;
678
679 case MAILMIME_DISCRETE_TYPE_APPLICATION:
680 r = mailimf_string_write_driver(do_write, data, col, "application", 11);
681 break;
682
683 case MAILMIME_DISCRETE_TYPE_EXTENSION:
684 r = mailimf_string_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, 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_driver(do_write, data, col, "message", 7);
708 break;
709
710 case MAILMIME_COMPOSITE_TYPE_MULTIPART:
711 r = mailimf_string_write_driver(do_write, data, col, "multipart", 9);
712 break;
713
714 case MAILMIME_COMPOSITE_TYPE_EXTENSION:
715 r = mailimf_string_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
738 struct mailmime_data * data,
739 int is_text);
740*/
741
742static int mailmime_text_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int encoding,
743 int istext,
744 const char * text, size_t size);
745
746/*
747static int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
748 char * text, size_t size);
749
750static int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext,
751 char * text, size_t size);
752*/
753
754static int mailmime_part_write_driver(int (* do_write)(void *, const char *, size_t), void * data, 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_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, col, "--", 2);
838 if (r != MAILIMF_NO_ERROR)
839 return r;
840
841 r = mailimf_string_write_driver(do_write, data, col, boundary, strlen(boundary));
842 if (r != MAILIMF_NO_ERROR)
843 return r;
844
845 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, col, subpart);
853 if (r != MAILIMF_NO_ERROR)
854 return r;
855 }
856
857 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, col, "--", 2);
865 if (r != MAILIMF_NO_ERROR)
866 return r;
867
868 r = mailimf_string_write_driver(do_write, data, col, boundary, strlen(boundary));
869 if (r != MAILIMF_NO_ERROR)
870 return r;
871
872 r = mailimf_string_write_driver(do_write, data, col, "--", 2);
873 if (r != MAILIMF_NO_ERROR)
874 return r;
875
876
877 /* epilogue */
878
879 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, 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_driver(do_write, data, 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_driver(do_write, data, col, build_info->mm_mime_fields);
947 if (r != MAILIMF_NO_ERROR)
948 return r;
949 }
950 }
951
952 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, col, build_info);
960}
961
962int mailmime_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
963 struct mailmime * build_info)
964{
965 if (build_info->mm_parent != NULL)
966 return mailmime_sub_write_driver(do_write, data, col, build_info);
967 else
968 return mailmime_part_write_driver(do_write, data, col, build_info);
969}
970
971
972int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
973 struct mailmime_data * mime_data,
974 int istext)
975{
976 int fd;
977 int r;
978 char * text;
979 struct stat buf;
980 int res;
981
982 switch (mime_data->dt_type) {
983 case MAILMIME_DATA_TEXT:
984
985 if (mime_data->dt_encoded) {
986 r = mailimf_string_write_driver(do_write, data, col,
987 mime_data->dt_data.dt_text.dt_data,
988 mime_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_driver(do_write, data, col, mime_data->dt_encoding, istext,
994 mime_data->dt_data.dt_text.dt_data,
995 mime_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(mime_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 == MAP_FAILED) {
1018 res = MAILIMF_ERROR_FILE;
1019 goto close;
1020 }
1021
1022 if (mime_data->dt_encoded) {
1023 r = mailimf_string_write_driver(do_write, data, 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_driver(do_write, data, col, mime_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_driver(int (* do_write)(void *, const char *, size_t), void * data, 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_driver(do_write, data, col, istext, text, size);
1065 break;
1066
1067 case MAILMIME_MECHANISM_BASE64:
1068 return mailmime_base64_write_driver(do_write, data, 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_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, 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_driver(do_write, data, 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_driver(do_write, data, 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_driver(do_write, data, 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(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1172 char ** pstart, size_t * plen)
1173{
1174 int r;
1175
1176 if (* plen >= MAX_WRITE_SIZE) {
1177 r = mailimf_string_write_driver(do_write, data, 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(int (* do_write)(void *, const char *, size_t), void * data, int * col,
1188 const char ** pstart, size_t * plen)
1189{
1190 int r;
1191
1192 if (* plen > 0) {
1193 r = mailimf_string_write_driver(do_write, data, 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_driver(int (* do_write)(void *, const char *, size_t), void * data, 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(do_write, data, col, &start, &len);
1226 if (r != MAILIMF_NO_ERROR)
1227 return r;
1228 start = text + i;
1229
1230 r = mailimf_string_write_driver(do_write, data, 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(do_write, data, 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_driver(do_write, data, 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(do_write, data, col, &start, &len);
1283 if (r != MAILIMF_NO_ERROR)
1284 return r;
1285 start = text + i + 1;
1286
1287 r = mailimf_string_write_driver(do_write, data, 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(do_write, data, 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_driver(do_write, data, 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(do_write, data, col, &start, &len);
1320 if (r != MAILIMF_NO_ERROR)
1321 return r;
1322 start = text + i + 1;
1323 r = mailimf_string_write_driver(do_write, data, 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(do_write, data, 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_driver(do_write, data, 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(do_write, data, 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_driver(do_write, data, 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(do_write, data, 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_driver(do_write, data, 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(do_write, data, 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_driver(do_write, data, 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/libetpan/src/low-level/mime/mailmime_write_generic.h b/libetpan/src/low-level/mime/mailmime_write_generic.h
new file mode 100644
index 0000000..0d9a725
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_generic.h
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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_GENERIC_H
37
38#define MAILMIME_WRITE_GENERIC_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_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
48 struct mailmime_fields * fields);
49
50int mailmime_content_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
51 struct mailmime_content * content);
52
53int mailmime_content_type_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
54 struct mailmime_content * content);
55
56int mailmime_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
57 struct mailmime * build_info);
58
59int mailmime_quoted_printable_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col, int istext,
60 const char * text, size_t size);
61
62int mailmime_base64_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
63 const char * text, size_t size);
64
65int mailmime_data_write_driver(int (* do_write)(void *, const char *, size_t), void * data, int * col,
66 struct mailmime_data * mime_data,
67 int istext);
68
69#ifdef __cplusplus
70}
71#endif
72
73#endif
diff --git a/libetpan/src/low-level/mime/mailmime_write_mem.c b/libetpan/src/low-level/mime/mailmime_write_mem.c
new file mode 100644
index 0000000..4b41d34
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_mem.c
@@ -0,0 +1,106 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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_mem.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 "mailmime_content.h"
48#include "mailmime_types_helper.h"
49#include "mailmime_write_generic.h"
50
51static int do_write(void * data, const char * str, size_t length)
52{
53 MMAPString * f;
54
55 f = data;
56
57 if (mmap_string_append_len(f, str, length) == NULL)
58 return 0;
59 else
60 return length;
61}
62
63int mailmime_fields_write_mem(MMAPString * f, int * col,
64 struct mailmime_fields * fields)
65{
66 return mailmime_fields_write_driver(do_write, f, col, fields);
67}
68
69int mailmime_content_write_mem(MMAPString * f, int * col,
70 struct mailmime_content * content)
71{
72 return mailmime_content_write_driver(do_write, f, col, content);
73}
74
75int mailmime_content_type_write_mem(MMAPString * f, int * col,
76 struct mailmime_content * content)
77{
78 return mailmime_content_type_write_driver(do_write, f, col, content);
79}
80
81int mailmime_write_mem(MMAPString * f, int * col,
82 struct mailmime * build_info)
83{
84 return mailmime_write_driver(do_write, f, col, build_info);
85}
86
87int mailmime_quoted_printable_write_mem(MMAPString * f, int * col, int istext,
88 const char * text, size_t size)
89{
90 return mailmime_quoted_printable_write_driver(do_write, f, col,
91 istext, text, size);
92}
93
94int mailmime_base64_write_mem(MMAPString * f, int * col,
95 const char * text, size_t size)
96{
97 return mailmime_base64_write_driver(do_write, f, col, text, size);
98}
99
100int mailmime_data_write_mem(MMAPString * f, int * col,
101 struct mailmime_data * data,
102 int istext)
103{
104 return mailmime_data_write_driver(do_write, f, col, data, istext);
105}
106
diff --git a/libetpan/src/low-level/mime/mailmime_write_mem.h b/libetpan/src/low-level/mime/mailmime_write_mem.h
new file mode 100644
index 0000000..f86d129
--- a/dev/null
+++ b/libetpan/src/low-level/mime/mailmime_write_mem.h
@@ -0,0 +1,73 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - 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 AUTHORS 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 AUTHORS 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_MEM_H
37
38#define MAILMIME_WRITE_MEM_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmime_types.h>
45#include <libetpan/mmapstring.h>
46
47int mailmime_fields_write_mem(MMAPString * f, int * col,
48 struct mailmime_fields * fields);
49
50int mailmime_content_write_mem(MMAPString * f, int * col,
51 struct mailmime_content * content);
52
53int mailmime_content_type_write_mem(MMAPString * f, int * col,
54 struct mailmime_content * content);
55
56int mailmime_write_mem(MMAPString * f, int * col,
57 struct mailmime * build_info);
58
59int mailmime_quoted_printable_write_mem(MMAPString * f, int * col, int istext,
60 const char * text, size_t size);
61
62int mailmime_base64_write_mem(MMAPString * f, int * col,
63 const char * text, size_t size);
64
65int mailmime_data_write_mem(MMAPString * f, int * col,
66 struct mailmime_data * data,
67 int istext);
68
69#ifdef __cplusplus
70}
71#endif
72
73#endif