summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/mime/mailmime_types_helper.c
Unidiff
Diffstat (limited to 'libetpan/src/low-level/mime/mailmime_types_helper.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/mime/mailmime_types_helper.c1385
1 files changed, 1385 insertions, 0 deletions
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