summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/mime-message/mime_message_driver.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/mime-message/mime_message_driver.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/mime-message/mime_message_driver.c914
1 files changed, 914 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/mime-message/mime_message_driver.c b/libetpan/src/driver/implementation/mime-message/mime_message_driver.c
new file mode 100644
index 0000000..06defbd
--- a/dev/null
+++ b/libetpan/src/driver/implementation/mime-message/mime_message_driver.c
@@ -0,0 +1,914 @@
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 "mime_message_driver.h"
37
38#include "libetpan-config.h"
39
40#include <sys/stat.h>
41#include <sys/types.h>
42#include <unistd.h>
43#include <sys/mman.h>
44#include <stdlib.h>
45#include <string.h>
46
47#include "mailmessage.h"
48#include "mailmessage_tools.h"
49#include "maildriver_tools.h"
50
51#if 0
52static FILE * get_mime_tmp_file(mailmessage * msg,
53 char * filename, size_t size)
54{
55 int fd;
56 mode_t old_mask;
57 FILE * f;
58
59 if (msg->msg_data == NULL)
60 return NULL;
61
62 snprintf(filename, size, "%s/libetpan-mime-XXXXXX",
63 (char *) msg->msg_data);
64
65 old_mask = umask(0077);
66 fd = mkstemp(filename);
67 umask(old_mask);
68 if (fd == -1)
69 return NULL;
70
71 f = fdopen(fd, "r+");
72 if (f == NULL) {
73 close(fd);
74 unlink(filename);
75 }
76
77 return f;
78}
79#endif
80
81int mime_message_set_tmpdir(mailmessage * msg, char * tmpdir)
82{
83#if 0
84 if (msg->msg_data != NULL)
85 free(msg->msg_data);
86
87 msg->msg_data = strdup(tmpdir);
88 if (msg->msg_data == NULL)
89 return MAIL_ERROR_MEMORY;
90
91#endif
92 return MAIL_NO_ERROR;
93}
94
95void mime_message_detach_mime(mailmessage * msg)
96{
97 msg->msg_mime = NULL;
98}
99
100mailmessage * mime_message_init(struct mailmime * mime)
101{
102 mailmessage * msg;
103 int r;
104
105 msg = mailmessage_new();
106 if (msg == NULL)
107 goto err;
108
109 r = mailmessage_init(msg, NULL, mime_message_driver, 0, 0);
110 if (r != MAIL_NO_ERROR)
111 goto free;
112
113 if (mime != NULL) {
114 mailmime_free(msg->msg_mime);
115 msg->msg_mime = mime;
116 }
117
118 return msg;
119
120 free:
121 mailmessage_free(msg);
122 err:
123 return NULL;
124}
125
126static int initialize(mailmessage * msg)
127{
128 struct mailmime * mime;
129 int res;
130
131 mime = mailmime_new_message_data(NULL);
132 if (mime == NULL) {
133 res = MAIL_ERROR_MEMORY;
134 goto err;
135 }
136
137 msg->msg_mime = mime;
138
139 return MAIL_NO_ERROR;
140
141 err:
142 return res;
143}
144
145static void uninitialize(mailmessage * msg)
146{
147 /* tmp dir name */
148 if (msg->msg_data != NULL)
149 free(msg->msg_data);
150
151 if (msg->msg_mime != NULL)
152 mailmime_free(msg->msg_mime);
153 msg->msg_mime = NULL;
154}
155
156static void flush(mailmessage * msg)
157{
158 /* do nothing */
159}
160
161static void check(mailmessage * msg)
162{
163 /* do nothing */
164}
165
166static void fetch_result_free(mailmessage * msg_info, char * content)
167{
168 mmap_string_unref(content);
169}
170
171#if 0
172static int file_to_mmapstr(FILE * f,
173 char ** result, size_t * result_len)
174{
175 int fd;
176 char * data;
177 struct stat buf;
178 MMAPString * mmapstr;
179 int res;
180 int r;
181
182 fd = fileno(f);
183 if (fd == -1) {
184 res = MAIL_ERROR_FILE;
185
186 goto err;
187 }
188
189 fflush(f);
190 r = fstat(fd, &buf);
191 if (r == -1) {
192 res = MAIL_ERROR_FILE;
193
194 goto err;
195 }
196
197 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
198 if (data == MAP_FAILED) {
199 res = MAIL_ERROR_FILE;
200
201 goto err;
202 }
203
204 mmapstr = mmap_string_new_len(data, buf.st_size);
205 if (mmapstr == NULL) {
206 res = MAIL_ERROR_MEMORY;
207
208 goto unmap;
209 }
210
211 munmap(data, buf.st_size);
212
213 r = mmap_string_ref(mmapstr);
214 if (r != 0) {
215 res = MAIL_ERROR_MEMORY;
216
217 goto err;
218 }
219
220 * result = mmapstr->str;
221 * result_len = mmapstr->len;
222
223 return MAIL_NO_ERROR;
224
225 unmap:
226 munmap(data, buf.st_size);
227 err:
228 return res;
229}
230#endif
231
232#if 0
233static int file_body_to_mmapstr(FILE * f,
234 char ** result, size_t * result_len)
235{
236 int fd;
237 char * data;
238 struct stat buf;
239 MMAPString * mmapstr;
240 size_t cur_token;
241 int res;
242 int r;
243
244 fd = fileno(f);
245 if (fd == -1) {
246 res = MAIL_ERROR_FILE;
247
248 goto err;
249 }
250
251 fflush(f);
252 r = fstat(fd, &buf);
253 if (r == -1) {
254 res = MAIL_ERROR_FILE;
255
256 goto err;
257 }
258
259 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
260 if (data == MAP_FAILED) {
261 res = MAIL_ERROR_FILE;
262
263 goto err;
264 }
265
266 cur_token = 0;
267
268 /* skip header */
269
270 while (1) {
271 r = mailimf_ignore_field_parse(data,
272 buf.st_size, &cur_token);
273 if (r == MAILIMF_NO_ERROR) {
274 /* do nothing */
275 }
276 else
277 break;
278 }
279
280 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
281 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
282 res = maildriver_imf_error_to_mail_error(r);
283 goto unmap;
284 }
285
286 mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token);
287 if (mmapstr == NULL) {
288 res = MAIL_ERROR_MEMORY;
289
290 goto unmap;
291 }
292
293 munmap(data, buf.st_size);
294
295 r = mmap_string_ref(mmapstr);
296 if (r != 0) {
297 res = MAIL_ERROR_MEMORY;
298
299 goto err;
300 }
301
302 * result = mmapstr->str;
303 * result_len = mmapstr->len;
304
305 return MAIL_NO_ERROR;
306
307 unmap:
308 munmap(data, buf.st_size);
309 err:
310 return res;
311}
312#endif
313
314
315static int body_to_mmapstr(char * data, size_t size,
316 char ** result, size_t * result_len)
317{
318 MMAPString * mmapstr;
319 size_t cur_token;
320 int res;
321 int r;
322
323 cur_token = 0;
324
325 /* skip header */
326
327 while (1) {
328 r = mailimf_ignore_field_parse(data, size, &cur_token);
329 if (r == MAILIMF_NO_ERROR) {
330 /* do nothing */
331 }
332 else
333 break;
334 }
335
336 r = mailimf_crlf_parse(data, size, &cur_token);
337 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
338 res = maildriver_imf_error_to_mail_error(r);
339 goto err;
340 }
341
342 mmapstr = mmap_string_new_len(data + cur_token, size - cur_token);
343 if (mmapstr == NULL) {
344 res = MAIL_ERROR_MEMORY;
345
346 goto err;
347 }
348
349 r = mmap_string_ref(mmapstr);
350 if (r != 0) {
351 mmap_string_free(mmapstr);
352 res = MAIL_ERROR_MEMORY;
353
354 goto err;
355 }
356
357 * result = mmapstr->str;
358 * result_len = mmapstr->len;
359
360 return MAIL_NO_ERROR;
361
362 err:
363 return res;
364}
365
366
367#if 0
368static int file_body_body_to_mmapstr(FILE * f,
369 char ** result, size_t * result_len)
370{
371 int fd;
372 char * data;
373 struct stat buf;
374 MMAPString * mmapstr;
375 size_t cur_token;
376 int res;
377 int r;
378
379 fd = fileno(f);
380 if (fd == -1) {
381 res = MAIL_ERROR_FILE;
382
383 goto err;
384 }
385
386 fflush(f);
387 r = fstat(fd, &buf);
388 if (r == -1) {
389 res = MAIL_ERROR_FILE;
390
391 goto err;
392 }
393
394 data = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
395 if (data == MAP_FAILED) {
396 res = MAIL_ERROR_FILE;
397
398 goto err;
399 }
400
401 cur_token = 0;
402
403 /* skip header */
404
405 /* MIME header */
406
407 while (1) {
408 r = mailimf_ignore_field_parse(data,
409 buf.st_size, &cur_token);
410 if (r == MAILIMF_NO_ERROR) {
411 /* do nothing */
412 }
413 else
414 break;
415 }
416
417 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
418 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
419 res = maildriver_imf_error_to_mail_error(r);
420 goto unmap;
421 }
422
423 /* headers */
424
425 while (1) {
426 r = mailimf_ignore_field_parse(data,
427 buf.st_size, &cur_token);
428 if (r == MAILIMF_NO_ERROR) {
429 /* do nothing */
430 }
431 else
432 break;
433 }
434
435 r = mailimf_crlf_parse(data, buf.st_size, &cur_token);
436 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
437 res = maildriver_imf_error_to_mail_error(r);
438 goto unmap;
439 }
440
441 mmapstr = mmap_string_new_len(data + cur_token, buf.st_size - cur_token);
442 if (mmapstr == NULL) {
443 res = MAIL_ERROR_MEMORY;
444
445 goto unmap;
446 }
447
448 munmap(data, buf.st_size);
449
450 r = mmap_string_ref(mmapstr);
451 if (r != 0) {
452 res = MAIL_ERROR_MEMORY;
453
454 goto err;
455 }
456
457 * result = mmapstr->str;
458 * result_len = mmapstr->len;
459
460 return MAIL_NO_ERROR;
461
462 unmap:
463 munmap(data, buf.st_size);
464 err:
465 return res;
466}
467#endif
468
469static int body_body_to_mmapstr(char * data, size_t size,
470 char ** result, size_t * result_len)
471{
472 MMAPString * mmapstr;
473 size_t cur_token;
474 int res;
475 int r;
476
477 cur_token = 0;
478
479 /* skip header */
480
481 /* MIME header */
482
483 while (1) {
484 r = mailimf_ignore_field_parse(data, size, &cur_token);
485 if (r == MAILIMF_NO_ERROR) {
486 /* do nothing */
487 }
488 else
489 break;
490 }
491
492 r = mailimf_crlf_parse(data, size, &cur_token);
493 if ((r != MAILIMF_NO_ERROR) && (r != MAILIMF_ERROR_PARSE)) {
494 res = maildriver_imf_error_to_mail_error(r);
495 goto err;
496 }
497
498 return body_to_mmapstr(data + cur_token, size - cur_token,
499 result, result_len);
500
501 err:
502 return res;
503}
504
505
506static int fetch_section(mailmessage * msg_info,
507 struct mailmime * mime,
508 char ** result, size_t * result_len)
509{
510 int r;
511#if 0
512 FILE * f;
513#endif
514 int res;
515 int col;
516#if 0
517 char filename[PATH_MAX];
518#endif
519 MMAPString * str;
520
521 if (msg_info->msg_mime == NULL)
522 return MAIL_ERROR_INVAL;
523
524#if 0
525 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
526 if (f == NULL) {
527 res = MAIL_ERROR_FILE;
528 goto err;
529 }
530#endif
531
532 str = mmap_string_new("");
533 if (str == NULL) {
534 res = MAILIMF_ERROR_MEMORY;
535 goto err;
536 }
537
538 col = 0;
539 r = mailmime_write_mem(str, &col, mime);
540 if (r != MAILIMF_NO_ERROR) {
541 res = maildriver_imf_error_to_mail_error(r);
542 goto free;
543 }
544
545#if 0
546 if (mime->mm_parent == NULL)
547 r = file_to_mmapstr(f, result, result_len);
548 else
549 r = file_body_to_mmapstr(f, result, result_len);
550#endif
551 if (mime->mm_parent == NULL) {
552 r = mmap_string_ref(str);
553 if (r < 0) {
554 res = MAIL_ERROR_MEMORY;
555 goto free;
556 }
557
558 * result = str->str;
559 * result_len = str->len;
560
561 r = MAIL_NO_ERROR;
562 }
563 else {
564 r = body_to_mmapstr(str->str, str->len, result, result_len);
565 if (r == MAIL_NO_ERROR) {
566 mmap_string_free(str);
567 }
568 }
569
570 if (r != MAIL_NO_ERROR) {
571 res = r;
572 goto free;
573 }
574
575#if 0
576 fclose(f);
577 unlink(filename);
578#endif
579
580 return MAIL_NO_ERROR;
581
582 free:
583#if 0
584 fclose(f);
585 unlink(filename);
586#endif
587 mmap_string_free(str);
588 err:
589 return res;
590}
591
592
593static int fetch_section_header(mailmessage * msg_info,
594 struct mailmime * mime,
595 char ** result, size_t * result_len)
596{
597 int r;
598#if 0
599 FILE * f;
600#endif
601 int res;
602 int col;
603#if 0
604 char filename[PATH_MAX];
605#endif
606 MMAPString * str;
607
608 if (msg_info->msg_mime == NULL)
609 return MAIL_ERROR_INVAL;
610
611#if 0
612 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
613 if (f == NULL) {
614 res = MAIL_ERROR_FILE;
615 goto err;
616 }
617#endif
618
619 str = mmap_string_new("");
620 if (str == NULL) {
621 res = MAIL_ERROR_MEMORY;
622 goto err;
623 }
624
625 col = 0;
626 if (mime->mm_type == MAILMIME_MESSAGE) {
627 if (mime->mm_data.mm_message.mm_fields != NULL) {
628#if 0
629 r = mailimf_fields_write(f, &col, mime->mm_data.mm_message.mm_fields);
630#endif
631 r = mailimf_fields_write_mem(str, &col, mime->mm_data.mm_message.mm_fields);
632 if (r != MAILIMF_NO_ERROR) {
633 res = maildriver_imf_error_to_mail_error(r);
634 goto free;
635 }
636#if 0
637 mailimf_string_write(f, &col, "\r\n", 2);
638#endif
639 mailimf_string_write_mem(str, &col, "\r\n", 2);
640 }
641 }
642
643 r = mmap_string_ref(str);
644 if (r < 0) {
645 res = MAIL_ERROR_MEMORY;
646 goto free;
647 }
648
649#if 0
650 r = file_to_mmapstr(f, result, result_len);
651 if (r != MAIL_NO_ERROR) {
652 res = r;
653 goto free;
654 }
655#endif
656 * result = str->str;
657 * result_len = str->len;
658
659#if 0
660 fclose(f);
661 unlink(filename);
662#endif
663
664 return MAIL_NO_ERROR;
665
666#if 0
667 close:
668 fclose(f);
669 unlink(filename);
670#endif
671 free:
672 mmap_string_free(str);
673 err:
674 return res;
675}
676
677
678static int fetch_section_mime(mailmessage * msg_info,
679 struct mailmime * mime,
680 char ** result, size_t * result_len)
681{
682 int r;
683#if 0
684 FILE * f;
685#endif
686 int res;
687 int col;
688#if 0
689 char filename[PATH_MAX];
690#endif
691 MMAPString * str;
692
693 if (msg_info->msg_mime == NULL)
694 return MAIL_ERROR_INVAL;
695
696 str = mmap_string_new("");
697 if (str == NULL) {
698 res = MAIL_ERROR_MEMORY;
699 goto err;
700 }
701
702#if 0
703 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
704 if (f == NULL) {
705 res = MAIL_ERROR_FILE;
706 goto err;
707 }
708#endif
709
710 col = 0;
711 if (mime->mm_content_type != NULL) {
712#if 0
713 r = mailmime_content_write(f, &col, mime->mm_content_type);
714#endif
715 r = mailmime_content_write_mem(str, &col, mime->mm_content_type);
716 if (r != MAILIMF_NO_ERROR) {
717 res = maildriver_imf_error_to_mail_error(r);
718 goto free;
719 }
720 }
721 if (mime->mm_mime_fields != NULL) {
722 r = mailmime_fields_write_mem(str, &col, mime->mm_mime_fields);
723 if (r != MAILIMF_NO_ERROR) {
724 res = maildriver_imf_error_to_mail_error(r);
725 goto free;
726 }
727 }
728 mailimf_string_write_mem(str, &col, "\r\n", 2);
729
730#if 0
731 r = file_to_mmapstr(f, result, result_len);
732 if (r != MAIL_NO_ERROR) {
733 res = r;
734 goto free;
735 }
736
737 fclose(f);
738 unlink(filename);
739#endif
740
741 r = mmap_string_ref(str);
742 if (r < 0) {
743 res = MAIL_ERROR_MEMORY;
744 goto free;
745 }
746
747 * result = str->str;
748 * result_len = str->len;
749
750 return MAIL_NO_ERROR;
751
752#if 0
753 close:
754 fclose(f);
755 unlink(filename);
756#endif
757 free:
758 mmap_string_free(str);
759 err:
760 return res;
761}
762
763
764
765static int fetch_section_body(mailmessage * msg_info,
766 struct mailmime * mime,
767 char ** result, size_t * result_len)
768{
769 int r;
770#if 0
771 FILE * f;
772#endif
773 int res;
774 int col;
775#if 0
776 char filename[PATH_MAX];
777#endif
778 MMAPString * str;
779
780 if (msg_info->msg_mime == NULL)
781 return MAIL_ERROR_INVAL;
782
783 str = mmap_string_new("");
784 if (str == NULL) {
785 res = MAIL_ERROR_MEMORY;
786 goto err;
787 }
788
789#if 0
790 f = get_mime_tmp_file(msg_info, filename, sizeof(filename));
791 if (f == NULL) {
792 res = MAIL_ERROR_FILE;
793 goto err;
794 }
795#endif
796
797 col = 0;
798 if (mime->mm_mime_fields != NULL) {
799#if 0
800 r = mailmime_write(f, &col, mime);
801#endif
802 r = mailmime_write_mem(str, &col, mime);
803 if (r != MAILIMF_NO_ERROR) {
804 res = maildriver_imf_error_to_mail_error(r);
805 goto free;
806 }
807 }
808
809 if (mime->mm_type == MAILMIME_MESSAGE)
810 r = body_body_to_mmapstr(str->str, str->len, result, result_len);
811 else
812 r = body_to_mmapstr(str->str, str->len, result, result_len);
813
814 if (r != MAIL_NO_ERROR) {
815 res = r;
816 goto free;
817 }
818
819 mmap_string_free(str);
820
821#if 0
822 fclose(f);
823 unlink(filename);
824#endif
825
826 return MAIL_NO_ERROR;
827
828#if 0
829 close:
830 fclose(f);
831 unlink(filename);
832#endif
833 free:
834 mmap_string_free(str);
835 err:
836 return res;
837}
838
839
840static int get_bodystructure(mailmessage * msg_info,
841 struct mailmime ** result)
842{
843 if (msg_info->msg_mime == NULL)
844 return MAIL_ERROR_INVAL;
845
846 * result = msg_info->msg_mime;
847
848 return MAIL_NO_ERROR;
849}
850
851
852static int fetch(mailmessage * msg_info,
853 char ** result, size_t * result_len)
854{
855 return fetch_section(msg_info, msg_info->msg_mime, result, result_len);
856}
857
858static int fetch_header(mailmessage * msg_info,
859 char ** result, size_t * result_len)
860{
861 return fetch_section_header(msg_info,
862 msg_info->msg_mime, result, result_len);
863}
864
865static int fetch_body(mailmessage * msg_info,
866 char ** result, size_t * result_len)
867{
868 return fetch_section_body(msg_info, msg_info->msg_mime, result, result_len);
869}
870
871
872static int fetch_size(mailmessage * msg_info,
873 size_t * result)
874{
875 char * msg;
876 int r;
877
878 r = fetch(msg_info, &msg, result);
879 if (r != MAIL_NO_ERROR) {
880 return r;
881 }
882
883 fetch_result_free(msg_info, msg);
884
885 return MAIL_NO_ERROR;
886}
887
888
889static mailmessage_driver local_mime_message_driver = {
890 .msg_name = "mime",
891
892 .msg_initialize = initialize,
893 .msg_uninitialize = uninitialize,
894
895 .msg_flush = flush,
896 .msg_check = check,
897
898 .msg_fetch_result_free = fetch_result_free,
899
900 .msg_fetch = fetch,
901 .msg_fetch_header = fetch_header,
902 .msg_fetch_body = fetch_body,
903 .msg_fetch_size = fetch_size,
904 .msg_get_bodystructure = get_bodystructure,
905 .msg_fetch_section = fetch_section,
906 .msg_fetch_section_header = fetch_section_header,
907 .msg_fetch_section_mime = fetch_section_mime,
908 .msg_fetch_section_body = fetch_section_body,
909 .msg_fetch_envelope = mailmessage_generic_fetch_envelope,
910
911 .msg_get_flags = NULL,
912};
913
914mailmessage_driver * mime_message_driver = &local_mime_message_driver;