summaryrefslogtreecommitdiffabout
path: root/libetpan/src/low-level/mbox
Unidiff
Diffstat (limited to 'libetpan/src/low-level/mbox') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/low-level/mbox/TODO0
-rw-r--r--libetpan/src/low-level/mbox/mailmbox.c1525
-rw-r--r--libetpan/src/low-level/mbox/mailmbox.h144
-rw-r--r--libetpan/src/low-level/mbox/mailmbox_parse.c620
-rw-r--r--libetpan/src/low-level/mbox/mailmbox_parse.h56
-rw-r--r--libetpan/src/low-level/mbox/mailmbox_types.c251
-rw-r--r--libetpan/src/low-level/mbox/mailmbox_types.h143
7 files changed, 2739 insertions, 0 deletions
diff --git a/libetpan/src/low-level/mbox/TODO b/libetpan/src/low-level/mbox/TODO
new file mode 100644
index 0000000..e69de29
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/TODO
diff --git a/libetpan/src/low-level/mbox/mailmbox.c b/libetpan/src/low-level/mbox/mailmbox.c
new file mode 100644
index 0000000..9937f3a
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox.c
@@ -0,0 +1,1525 @@
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 "mailmbox.h"
37
38#include <sys/file.h>
39#include <sys/stat.h>
40#include <unistd.h>
41#include <sys/mman.h>
42#include <fcntl.h>
43#include <time.h>
44#include <sys/types.h>
45#include <unistd.h>
46
47#include <string.h>
48#include <ctype.h>
49#include <stdlib.h>
50#include <stdio.h>
51
52#include "libetpan-config.h"
53
54#include "mmapstring.h"
55#include "mailmbox_parse.h"
56#include "maillock.h"
57
58/*
59 http://www.qmail.org/qmail-manual-html/man5/mbox.html
60 RFC 2076
61*/
62
63#define TMPDIR "/tmp"
64
65/* mbox is a file with a corresponding filename */
66
67#define UID_HEADER "X-LibEtPan-UID:"
68
69#ifndef TRUE
70#define TRUE 1
71#endif
72
73#ifndef FALSE
74#define FALSE 0
75#endif
76
77int mailmbox_write_lock(struct mailmbox_folder * folder)
78{
79 int r;
80
81 if (folder->mb_read_only)
82 return MAILMBOX_ERROR_READONLY;
83
84 r = maillock_write_lock(folder->mb_filename, folder->mb_fd);
85 if (r == 0)
86 return MAILMBOX_NO_ERROR;
87 else
88 return MAILMBOX_ERROR_FILE;
89}
90
91int mailmbox_write_unlock(struct mailmbox_folder * folder)
92{
93 int r;
94
95 r = maillock_write_unlock(folder->mb_filename, folder->mb_fd);
96 if (r == 0)
97 return MAILMBOX_NO_ERROR;
98 else
99 return MAILMBOX_ERROR_FILE;
100}
101
102int mailmbox_read_lock(struct mailmbox_folder * folder)
103{
104 int r;
105
106 r = maillock_read_lock(folder->mb_filename, folder->mb_fd);
107 if (r == 0)
108 return MAILMBOX_NO_ERROR;
109 else
110 return MAILMBOX_ERROR_FILE;
111}
112
113int mailmbox_read_unlock(struct mailmbox_folder * folder)
114{
115 int r;
116
117 r = maillock_read_unlock(folder->mb_filename, folder->mb_fd);
118 if (r == 0)
119 return MAILMBOX_NO_ERROR;
120 else
121 return MAILMBOX_ERROR_FILE;
122}
123
124
125/*
126 map the file into memory.
127 the file must be locked.
128*/
129
130int mailmbox_map(struct mailmbox_folder * folder)
131{
132 char * str;
133 struct stat buf;
134 int res;
135 int r;
136
137 r = stat(folder->mb_filename, &buf);
138 if (r < 0) {
139 res = MAILMBOX_ERROR_FILE;
140 goto err;
141 }
142
143 if (folder->mb_read_only)
144 str = (char *) mmap(0, buf.st_size, PROT_READ,
145 MAP_PRIVATE, folder->mb_fd, 0);
146 else
147 str = (char *) mmap(0, buf.st_size, PROT_READ | PROT_WRITE,
148 MAP_SHARED, folder->mb_fd, 0);
149 if (str == MAP_FAILED) {
150 res = MAILMBOX_ERROR_FILE;
151 goto err;
152 }
153
154 folder->mb_mapping = str;
155 folder->mb_mapping_size = buf.st_size;
156
157 return MAILMBOX_NO_ERROR;
158
159 err:
160 return res;
161}
162
163/*
164 unmap the file
165*/
166
167void mailmbox_unmap(struct mailmbox_folder * folder)
168{
169 munmap(folder->mb_mapping, folder->mb_mapping_size);
170 folder->mb_mapping = NULL;
171 folder->mb_mapping_size = 0;
172}
173
174void mailmbox_sync(struct mailmbox_folder * folder)
175{
176 msync(folder->mb_mapping, folder->mb_mapping_size, MS_SYNC);
177}
178
179void mailmbox_timestamp(struct mailmbox_folder * folder)
180{
181 int r;
182 struct stat buf;
183
184 r = stat(folder->mb_filename, &buf);
185 if (r < 0)
186 folder->mb_mtime = (time_t) -1;
187 else
188 folder->mb_mtime = buf.st_mtime;
189}
190
191/*
192 open the file
193*/
194
195int mailmbox_open(struct mailmbox_folder * folder)
196{
197 int fd;
198 int read_only;
199
200 fd = -1;
201 read_only = TRUE;
202
203 if (!folder->mb_read_only) {
204 read_only = FALSE;
205 fd = open(folder->mb_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
206 }
207
208 if (folder->mb_read_only || (fd < 0)) {
209 read_only = TRUE;
210 fd = open(folder->mb_filename, O_RDONLY);
211 if (fd < 0)
212 return MAILMBOX_ERROR_FILE_NOT_FOUND;
213 }
214
215 folder->mb_fd = fd;
216 folder->mb_read_only = read_only;
217
218 return MAILMBOX_NO_ERROR;
219}
220
221/*
222 close the file
223*/
224
225void mailmbox_close(struct mailmbox_folder * folder)
226{
227 close(folder->mb_fd);
228 folder->mb_fd = -1;
229}
230
231
232static int mailmbox_validate_lock(struct mailmbox_folder * folder,
233 int (* custom_lock)(struct mailmbox_folder *),
234 int (* custom_unlock)(struct mailmbox_folder *))
235{
236 struct stat buf;
237 int res;
238 int r;
239
240 r = stat(folder->mb_filename, &buf);
241 if (r < 0) {
242 buf.st_mtime = (time_t) -1;
243 }
244
245 if ((buf.st_mtime != folder->mb_mtime) ||
246 ((size_t) buf.st_size != folder->mb_mapping_size)) {
247 int r;
248
249 mailmbox_unmap(folder);
250 mailmbox_close(folder);
251
252 r = mailmbox_open(folder);
253 if (r != MAILMBOX_NO_ERROR) {
254 res = r;
255 goto err;
256 }
257
258 r = custom_lock(folder);
259 if (r != MAILMBOX_NO_ERROR) {
260 res = r;
261 goto err;
262 }
263
264 r = mailmbox_map(folder);
265 if (r != MAILMBOX_NO_ERROR) {
266 res = r;
267 goto err_unlock;
268 }
269
270 r = mailmbox_parse(folder);
271 if (r != MAILMBOX_NO_ERROR) {
272 res = r;
273 goto err_unlock;
274 }
275
276 folder->mb_mtime = buf.st_mtime;
277
278 return MAILMBOX_NO_ERROR;
279 }
280 else {
281 r = custom_lock(folder);
282 if (r != MAILMBOX_NO_ERROR) {
283 res = r;
284 goto err;
285 }
286 }
287
288 return MAILMBOX_NO_ERROR;
289
290 err_unlock:
291 custom_unlock(folder);
292 err:
293 return res;
294}
295
296
297int mailmbox_validate_write_lock(struct mailmbox_folder * folder)
298{
299 return mailmbox_validate_lock(folder,
300 mailmbox_write_lock,
301 mailmbox_write_unlock);
302}
303
304
305int mailmbox_validate_read_lock(struct mailmbox_folder * folder)
306{
307 return mailmbox_validate_lock(folder,
308 mailmbox_read_lock,
309 mailmbox_read_unlock);
310}
311
312
313/* ********************************************************************** */
314/* append messages */
315
316#define MAX_FROM_LINE_SIZE 256
317
318static inline size_t get_line(const char * line, size_t length,
319 const char ** pnext_line, size_t * pcount)
320{
321 size_t count;
322
323 count = 0;
324
325 while (1) {
326 if (length == 0)
327 break;
328
329 if (* line == '\r') {
330 line ++;
331
332 count ++;
333 length --;
334
335 if (length > 0) {
336 if (* line == '\n') {
337 line ++;
338
339 count ++;
340 length --;
341
342 break;
343 }
344 }
345 }
346 else if (* line == '\n') {
347 line ++;
348
349 count ++;
350 length --;
351
352 break;
353 }
354 else {
355 line ++;
356 length --;
357 count ++;
358 }
359 }
360
361 * pnext_line = line;
362 * pcount = count;
363
364 return count;
365}
366
367/*
368 TODO : should strip \r\n if any
369 see also in write_fixed_line
370*/
371
372static inline size_t get_fixed_line_size(const char * line, size_t length,
373 const char ** pnext_line, size_t * pcount,
374 size_t * pfixed_count)
375{
376 size_t count;
377 const char * next_line;
378 size_t fixed_count;
379
380 if (!get_line(line, length, &next_line, &count))
381 return 0;
382
383 fixed_count = count;
384 if (count >= 5) {
385 if (line[0] == 'F') {
386 if (strncmp(line, "From ", 5) == 0)
387 fixed_count ++;
388 }
389 }
390
391 * pnext_line = next_line;
392 * pcount = count;
393 * pfixed_count = fixed_count;
394
395 return count;
396}
397
398static size_t get_fixed_message_size(const char * message, size_t size,
399 uint32_t uid, int force_no_uid)
400{
401 size_t fixed_size;
402 size_t cur_token;
403 size_t left;
404 const char * next;
405 const char * cur;
406 int end;
407 int r;
408 uint32_t tmp_uid;
409
410 cur_token = 0;
411
412 fixed_size = 0;
413
414 /* headers */
415
416 end = FALSE;
417 while (!end) {
418 size_t begin;
419 int ignore;
420
421 ignore = FALSE;
422 begin = cur_token;
423 if (cur_token + strlen(UID_HEADER) <= size) {
424 if (message[cur_token] == 'X') {
425 if (strncasecmp(message + cur_token, UID_HEADER,
426 strlen(UID_HEADER)) == 0) {
427 ignore = TRUE;
428 }
429 }
430 }
431
432 r = mailimf_ignore_field_parse(message, size, &cur_token);
433 switch (r) {
434 case MAILIMF_NO_ERROR:
435 if (!ignore)
436 fixed_size += cur_token - begin;
437 break;
438 case MAILIMF_ERROR_PARSE:
439 default:
440 end = TRUE;
441 break;
442 }
443 }
444
445 if (!force_no_uid) {
446 /* UID header */
447
448 fixed_size += strlen(UID_HEADER " \r\n");
449
450 tmp_uid = uid;
451 while (tmp_uid >= 10) {
452 tmp_uid /= 10;
453 fixed_size ++;
454 }
455 fixed_size ++;
456 }
457
458 /* body */
459
460 left = size - cur_token;
461 next = message + cur_token;
462 while (left > 0) {
463 size_t count;
464 size_t fixed_count;
465
466 cur = next;
467
468 if (!get_fixed_line_size(cur, left, &next, &count, &fixed_count))
469 break;
470
471 fixed_size += fixed_count;
472 left -= count;
473 }
474
475 return fixed_size;
476}
477
478static inline char * write_fixed_line(char * str,
479 const char * line, size_t length,
480 const char ** pnext_line, size_t * pcount)
481{
482 size_t count;
483 const char * next_line;
484
485 if (!get_line(line, length, &next_line, &count))
486 return str;
487
488 if (count >= 5) {
489 if (line[0] == 'F') {
490 if (strncmp(line, "From ", 5) == 0) {
491 * str = '>';
492 str ++;
493 }
494 }
495 }
496
497 memcpy(str, line, count);
498
499 * pnext_line = next_line;
500 * pcount = count;
501 str += count;
502
503 return str;
504}
505
506static char * write_fixed_message(char * str,
507 const char * message, size_t size,
508 uint32_t uid, int force_no_uid)
509{
510 size_t fixed_size;
511 size_t cur_token;
512 size_t left;
513 int end;
514 int r;
515 const char * cur_src;
516 size_t numlen;
517
518 cur_token = 0;
519
520 fixed_size = 0;
521
522 /* headers */
523
524 end = FALSE;
525 while (!end) {
526 size_t begin;
527 int ignore;
528
529 ignore = FALSE;
530 begin = cur_token;
531 if (cur_token + strlen(UID_HEADER) <= size) {
532 if (message[cur_token] == 'X') {
533 if (strncasecmp(message + cur_token, UID_HEADER,
534 strlen(UID_HEADER)) == 0) {
535 ignore = TRUE;
536 }
537 }
538 }
539
540 r = mailimf_ignore_field_parse(message, size, &cur_token);
541 switch (r) {
542 case MAILIMF_NO_ERROR:
543 if (!ignore) {
544 memcpy(str, message + begin, cur_token - begin);
545 str += cur_token - begin;
546 }
547 break;
548 case MAILIMF_ERROR_PARSE:
549 default:
550 end = TRUE;
551 break;
552 }
553 }
554
555 if (!force_no_uid) {
556 /* UID header */
557
558 memcpy(str, UID_HEADER " ", strlen(UID_HEADER " "));
559 str += strlen(UID_HEADER " ");
560 numlen = snprintf(str, 20, "%i\r\n", uid);
561 str += numlen;
562 }
563
564 /* body */
565
566 cur_src = message + cur_token;
567 left = size - cur_token;
568 while (left > 0) {
569 size_t count;
570 const char * next;
571
572 str = write_fixed_line(str, cur_src, left, &next, &count);
573
574 cur_src = next;
575 left -= count;
576 }
577
578 return str;
579}
580
581#define DEFAULT_FROM_LINE "From - Wed Jun 30 21:49:08 1993\n"
582
583int
584mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder,
585 carray * append_tab)
586{
587 size_t extra_size;
588 int r;
589 char from_line[MAX_FROM_LINE_SIZE] = DEFAULT_FROM_LINE;
590 struct tm time_info;
591 time_t date;
592 int res;
593 size_t old_size;
594 char * str;
595 unsigned int i;
596 size_t from_size;
597 size_t maxuid;
598 size_t left;
599 size_t crlf_count;
600
601 if (folder->mb_read_only) {
602 res = MAILMBOX_ERROR_READONLY;
603 goto err;
604 }
605
606 date = time(NULL);
607 from_size = strlen(DEFAULT_FROM_LINE);
608 if (localtime_r(&date, &time_info) != NULL)
609 from_size = strftime(from_line, MAX_FROM_LINE_SIZE, "From - %c\n", &time_info);
610
611 maxuid = /* */ folder->mb_max_uid;
612
613 extra_size = 0;
614 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
615 struct mailmbox_append_info * info;
616
617 info = carray_get(append_tab, i);
618 extra_size += from_size;
619 extra_size += get_fixed_message_size(info->ai_message, info->ai_size,
620 folder->mb_max_uid + i + 1,
621 folder->mb_no_uid);
622 extra_size += 2; /* CR LF */
623
624 info->ai_uid = folder->mb_max_uid + i + 1;
625 }
626
627 left = folder->mb_mapping_size;
628 crlf_count = 0;
629 while (left >= 1) {
630 if (folder->mb_mapping[left - 1] == '\n') {
631 crlf_count ++;
632 left --;
633 }
634 else if (folder->mb_mapping[left - 1] == '\r') {
635 left --;
636 }
637 else
638 break;
639
640 if (crlf_count == 2)
641 break;
642 }
643
644 old_size = folder->mb_mapping_size;
645 mailmbox_unmap(folder);
646
647 if (old_size != 0) {
648 if (crlf_count != 2)
649 extra_size += (2 - crlf_count) * 2;
650 }
651
652 r = ftruncate(folder->mb_fd, extra_size + old_size);
653 if (r < 0) {
654 mailmbox_map(folder);
655 res = MAILMBOX_ERROR_FILE;
656 goto err;
657 }
658
659 r = mailmbox_map(folder);
660 if (r < 0) {
661 ftruncate(folder->mb_fd, old_size);
662 return MAILMBOX_ERROR_FILE;
663 }
664
665 str = folder->mb_mapping + old_size;
666
667 if (old_size != 0) {
668 for(i = 0 ; i < 2 - crlf_count ; i ++) {
669 * str = '\r';
670 str ++;
671 * str = '\n';
672 str ++;
673 }
674 }
675
676 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
677 struct mailmbox_append_info * info;
678
679 info = carray_get(append_tab, i);
680
681 memcpy(str, from_line, from_size);
682
683 str += strlen(from_line);
684
685 str = write_fixed_message(str, info->ai_message, info->ai_size,
686 folder->mb_max_uid + i + 1,
687 folder->mb_no_uid);
688
689 * str = '\r';
690 str ++;
691 * str = '\n';
692 str ++;
693 }
694
695 folder->mb_max_uid += carray_count(append_tab);
696
697 return MAILMBOX_NO_ERROR;
698
699 err:
700 return res;
701}
702
703int
704mailmbox_append_message_list(struct mailmbox_folder * folder,
705 carray * append_tab)
706{
707 int r;
708 int res;
709 size_t cur_token;
710
711 r = mailmbox_validate_write_lock(folder);
712 if (r != MAILMBOX_NO_ERROR) {
713 res = r;
714 goto err;
715 }
716
717 r = mailmbox_expunge_no_lock(folder);
718 if (r != MAILMBOX_NO_ERROR) {
719 res = r;
720 goto unlock;
721 }
722
723 cur_token = folder->mb_mapping_size;
724
725 r = mailmbox_append_message_list_no_lock(folder, append_tab);
726 if (r != MAILMBOX_NO_ERROR) {
727 res = r;
728 goto unlock;
729 }
730
731 mailmbox_sync(folder);
732
733 r = mailmbox_parse_additionnal(folder, &cur_token);
734 if (r != MAILMBOX_NO_ERROR) {
735 res = r;
736 goto unlock;
737 }
738
739 mailmbox_timestamp(folder);
740
741 mailmbox_write_unlock(folder);
742
743 return MAILMBOX_NO_ERROR;
744
745 unlock:
746 mailmbox_write_unlock(folder);
747 err:
748 return res;
749}
750
751int
752mailmbox_append_message_uid(struct mailmbox_folder * folder,
753 const char * data, size_t len, unsigned int * puid)
754{
755 carray * tab;
756 struct mailmbox_append_info * append_info;
757 int res;
758 int r;
759
760 tab = carray_new(1);
761 if (tab == NULL) {
762 res = MAILMBOX_ERROR_MEMORY;
763 goto err;
764 }
765
766 append_info = mailmbox_append_info_new(data, len);
767 if (append_info == NULL) {
768 res = MAILMBOX_ERROR_MEMORY;
769 goto free_list;
770 }
771
772 r = carray_add(tab, append_info, NULL);
773 if (r < 0) {
774 res = MAILMBOX_ERROR_MEMORY;
775 goto free_append_info;
776 }
777
778 r = mailmbox_append_message_list(folder, tab);
779
780 if (puid != NULL)
781 * puid = append_info->ai_uid;
782
783 mailmbox_append_info_free(append_info);
784 carray_free(tab);
785
786 return r;
787
788 free_append_info:
789 mailmbox_append_info_free(append_info);
790 free_list:
791 carray_free(tab);
792 err:
793 return res;
794}
795
796int
797mailmbox_append_message(struct mailmbox_folder * folder,
798 const char * data, size_t len)
799{
800 return mailmbox_append_message_uid(folder, data, len, NULL);
801}
802
803/* ********************************************************************** */
804
805int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder,
806 uint32_t num, char ** result,
807 size_t * result_len)
808{
809 struct mailmbox_msg_info * info;
810 int res;
811 chashdatum key;
812 chashdatum data;
813 int r;
814
815 key.data = &num;
816 key.len = sizeof(num);
817
818 r = chash_get(folder->mb_hash, &key, &data);
819 if (r < 0) {
820 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
821 goto err;
822 }
823
824 info = data.data;
825
826 if (info->msg_deleted) {
827 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
828 goto err;
829 }
830
831 * result = folder->mb_mapping + info->msg_headers;
832 * result_len = info->msg_size - info->msg_start_len;
833
834 return MAILMBOX_NO_ERROR;
835
836 err:
837 return res;
838}
839
840int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder,
841 uint32_t num, char ** result,
842 size_t * result_len)
843{
844 struct mailmbox_msg_info * info;
845 int res;
846 chashdatum key;
847 chashdatum data;
848 int r;
849
850 key.data = &num;
851 key.len = sizeof(num);
852
853 r = chash_get(folder->mb_hash, &key, &data);
854 if (r < 0) {
855 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
856 goto err;
857 }
858
859 info = data.data;
860
861 if (info->msg_deleted) {
862 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
863 goto err;
864 }
865
866 * result = folder->mb_mapping + info->msg_headers;
867 * result_len = info->msg_headers_len;
868
869 return MAILMBOX_NO_ERROR;
870
871 err:
872 return res;
873}
874
875int mailmbox_fetch_msg(struct mailmbox_folder * folder,
876 uint32_t num, char ** result,
877 size_t * result_len)
878{
879 MMAPString * mmapstr;
880 int res;
881 char * data;
882 size_t len;
883 int r;
884 size_t fixed_size;
885 char * end;
886
887 r = mailmbox_validate_read_lock(folder);
888 if (r != MAILMBOX_NO_ERROR) {
889 res = r;
890 goto err;
891 }
892
893 r = mailmbox_fetch_msg_no_lock(folder, num, &data, &len);
894 if (r != MAILMBOX_NO_ERROR) {
895 res = r;
896 goto unlock;
897 }
898
899 /* size with no uid */
900 fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */);
901
902#if 0
903 mmapstr = mmap_string_new_len(data, fixed_size);
904 if (mmapstr == NULL) {
905 res = MAILMBOX_ERROR_MEMORY;
906 goto unlock;
907 }
908#endif
909 mmapstr = mmap_string_sized_new(fixed_size);
910 if (mmapstr == NULL) {
911 res = MAILMBOX_ERROR_MEMORY;
912 goto unlock;
913 }
914
915 end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */);
916 * end = '\0';
917 mmapstr->len = fixed_size;
918
919 r = mmap_string_ref(mmapstr);
920 if (r < 0) {
921 mmap_string_free(mmapstr);
922 res = MAILMBOX_ERROR_MEMORY;
923 goto unlock;
924 }
925
926 * result = mmapstr->str;
927 * result_len = mmapstr->len;
928
929 mailmbox_read_unlock(folder);
930
931 return MAILMBOX_NO_ERROR;
932
933 unlock:
934 mailmbox_read_unlock(folder);
935 err:
936 return res;
937}
938
939int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder,
940 uint32_t num, char ** result,
941 size_t * result_len)
942{
943 MMAPString * mmapstr;
944 int res;
945 char * data;
946 size_t len;
947 int r;
948 size_t fixed_size;
949 char * end;
950
951 r = mailmbox_validate_read_lock(folder);
952 if (r != MAILMBOX_NO_ERROR) {
953 res = r;
954 goto err;
955 }
956
957 r = mailmbox_fetch_msg_headers_no_lock(folder, num, &data, &len);
958 if (r != MAILMBOX_NO_ERROR) {
959 res = r;
960 goto unlock;
961 }
962
963#if 0
964 mmapstr = mmap_string_new_len(data, len);
965 if (mmapstr == NULL) {
966 res = MAILMBOX_ERROR_MEMORY;
967 goto unlock;
968 }
969#endif
970 /* size with no uid */
971 fixed_size = get_fixed_message_size(data, len, 0, 1 /* force no uid */);
972
973 mmapstr = mmap_string_sized_new(fixed_size);
974 if (mmapstr == NULL) {
975 res = MAILMBOX_ERROR_MEMORY;
976 goto unlock;
977 }
978
979 end = write_fixed_message(mmapstr->str, data, len, 0, 1 /* force no uid */);
980 * end = '\0';
981 mmapstr->len = fixed_size;
982
983 r = mmap_string_ref(mmapstr);
984 if (r < 0) {
985 mmap_string_free(mmapstr);
986 res = MAILMBOX_ERROR_MEMORY;
987 goto unlock;
988 }
989
990 * result = mmapstr->str;
991 * result_len = mmapstr->len;
992
993 mailmbox_read_unlock(folder);
994
995 return MAILMBOX_NO_ERROR;
996
997 unlock:
998 mailmbox_read_unlock(folder);
999 err:
1000 return res;
1001}
1002
1003void mailmbox_fetch_result_free(char * msg)
1004{
1005 mmap_string_unref(msg);
1006}
1007
1008
1009int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder,
1010 struct mailmbox_folder * src_folder,
1011 carray * tab)
1012{
1013 int r;
1014 int res;
1015 carray * append_tab;
1016 unsigned int i;
1017
1018 r = mailmbox_validate_read_lock(src_folder);
1019 if (r != MAILMBOX_NO_ERROR) {
1020 res = r;
1021 goto err;
1022 }
1023
1024 append_tab = carray_new(carray_count(tab));
1025 if (append_tab == NULL) {
1026 res = MAILMBOX_ERROR_MEMORY;
1027 goto src_unlock;
1028 }
1029
1030 for(i = 0 ; i < carray_count(tab) ; i ++) {
1031 struct mailmbox_append_info * append_info;
1032 char * data;
1033 size_t len;
1034 uint32_t uid;
1035
1036 uid = * ((uint32_t *) carray_get(tab, i));
1037
1038 r = mailmbox_fetch_msg_no_lock(src_folder, uid, &data, &len);
1039 if (r != MAILMBOX_NO_ERROR) {
1040 res = r;
1041 goto free_list;
1042 }
1043
1044 append_info = mailmbox_append_info_new(data, len);
1045 if (append_info == NULL) {
1046 res = MAILMBOX_ERROR_MEMORY;
1047 goto free_list;
1048 }
1049
1050 r = carray_add(append_tab, append_info, NULL);
1051 if (r < 0) {
1052 mailmbox_append_info_free(append_info);
1053 res = MAILMBOX_ERROR_MEMORY;
1054 goto free_list;
1055 }
1056 }
1057
1058 r = mailmbox_append_message_list(dest_folder, append_tab);
1059 if (r != MAILMBOX_NO_ERROR) {
1060 res = r;
1061 goto src_unlock;
1062 }
1063
1064 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
1065 struct mailmbox_append_info * append_info;
1066
1067 append_info = carray_get(append_tab, i);
1068 mailmbox_append_info_free(append_info);
1069 }
1070 carray_free(append_tab);
1071
1072 mailmbox_read_unlock(src_folder);
1073
1074 return MAILMBOX_NO_ERROR;
1075
1076 free_list:
1077 for(i = 0 ; i < carray_count(append_tab) ; i ++) {
1078 struct mailmbox_append_info * append_info;
1079
1080 append_info = carray_get(append_tab, i);
1081 mailmbox_append_info_free(append_info);
1082 }
1083 carray_free(append_tab);
1084 src_unlock:
1085 mailmbox_read_unlock(src_folder);
1086 err:
1087 return res;
1088}
1089
1090int mailmbox_copy_msg(struct mailmbox_folder * dest_folder,
1091 struct mailmbox_folder * src_folder,
1092 uint32_t uid)
1093{
1094 carray * tab;
1095 int res;
1096 uint32_t * puid;
1097 int r;
1098
1099 tab = carray_new(1);
1100 if (tab == NULL) {
1101 res = MAILMBOX_ERROR_MEMORY;
1102 goto err;
1103 }
1104
1105 puid = malloc(sizeof(* puid));
1106 if (puid == NULL) {
1107 res = MAILMBOX_ERROR_MEMORY;
1108 goto free_array;
1109 }
1110 * puid = uid;
1111
1112 r = mailmbox_copy_msg_list(dest_folder, src_folder, tab);
1113 res = r;
1114
1115 free(puid);
1116 free_array:
1117 carray_free(tab);
1118 err:
1119 return res;
1120}
1121
1122static int mailmbox_expunge_to_file_no_lock(char * dest_filename, int dest_fd,
1123 struct mailmbox_folder * folder,
1124 size_t * result_size)
1125{
1126 int r;
1127 int res;
1128 unsigned long i;
1129 size_t cur_offset;
1130 char * dest;
1131 size_t size;
1132
1133 size = 0;
1134 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
1135 struct mailmbox_msg_info * info;
1136
1137 info = carray_get(folder->mb_tab, i);
1138
1139 if (!info->msg_deleted) {
1140 size += info->msg_size + info->msg_padding;
1141
1142 if (!folder->mb_no_uid) {
1143 if (!info->msg_written_uid) {
1144 uint32_t uid;
1145
1146 size += strlen(UID_HEADER " \r\n");
1147
1148 uid = info->msg_uid;
1149 while (uid >= 10) {
1150 uid /= 10;
1151 size ++;
1152 }
1153 size ++;
1154 }
1155 }
1156 }
1157 }
1158
1159 r = ftruncate(dest_fd, size);
1160 if (r < 0) {
1161 res = MAILMBOX_ERROR_FILE;
1162 goto err;
1163 }
1164
1165 dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, dest_fd, 0);
1166 if (dest == MAP_FAILED) {
1167 res = MAILMBOX_ERROR_FILE;
1168 goto err;
1169 }
1170
1171 cur_offset = 0;
1172 for(i = 0 ; i < carray_count(folder->mb_tab) ; i ++) {
1173 struct mailmbox_msg_info * info;
1174
1175 info = carray_get(folder->mb_tab, i);
1176
1177 if (!info->msg_deleted) {
1178 memcpy(dest + cur_offset, folder->mb_mapping + info->msg_start,
1179 info->msg_headers_len + info->msg_start_len);
1180 cur_offset += info->msg_headers_len + info->msg_start_len;
1181
1182 if (!folder->mb_no_uid) {
1183 if (!info->msg_written_uid) {
1184 size_t numlen;
1185
1186 memcpy(dest + cur_offset, UID_HEADER " ", strlen(UID_HEADER " "));
1187 cur_offset += strlen(UID_HEADER " ");
1188 numlen = snprintf(dest + cur_offset, size - cur_offset,
1189 "%i\r\n", info->msg_uid);
1190 cur_offset += numlen;
1191 }
1192 }
1193
1194 memcpy(dest + cur_offset,
1195 folder->mb_mapping + info->msg_headers + info->msg_headers_len,
1196 info->msg_size - (info->msg_start_len + info->msg_headers_len)
1197 + info->msg_padding);
1198
1199 cur_offset += info->msg_size -
1200 (info->msg_start_len + info->msg_headers_len)
1201 + info->msg_padding;
1202 }
1203 }
1204 fflush(stdout);
1205
1206 msync(dest, size, MS_SYNC);
1207 munmap(dest, size);
1208
1209 * result_size = size;
1210
1211 return MAILMBOX_NO_ERROR;
1212
1213 err:
1214 return res;
1215}
1216
1217static int copy_to_old_file(char * source_filename,
1218 char * destination_filename, size_t size)
1219{
1220 int source_fd;
1221 int dest_fd;
1222 char * source;
1223 char * dest;
1224 int res;
1225 int r;
1226
1227 source_fd = open(source_filename, O_RDONLY);
1228 if (source_fd < 0) {
1229 res = MAILMBOX_ERROR_FILE;
1230 goto err;
1231 }
1232
1233 source = (char *) mmap(0, size, PROT_READ, MAP_PRIVATE, source_fd, 0);
1234 if (source == MAP_FAILED) {
1235 res = MAILMBOX_ERROR_FILE;
1236 goto close_source;
1237 }
1238
1239 dest_fd = open(destination_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1240 if (dest_fd < 0) {
1241 res = MAILMBOX_ERROR_FILE;
1242 goto unmap_source;
1243 }
1244
1245 r = ftruncate(dest_fd, size);
1246 if (r < 0) {
1247 res = MAILMBOX_ERROR_FILE;
1248 goto close_dest;
1249 }
1250
1251 dest = (char *) mmap(0, size, PROT_READ | PROT_WRITE,
1252 MAP_SHARED, dest_fd, 0);
1253 if (dest == MAP_FAILED) {
1254 res = MAILMBOX_ERROR_FILE;
1255 goto close_dest;
1256 }
1257
1258 memcpy(dest, source, size);
1259
1260 munmap(dest, size);
1261 close(source_fd);
1262 munmap(source, size);
1263 close(source_fd);
1264
1265 return MAILMBOX_NO_ERROR;
1266
1267 unmap_dest:
1268 munmap(dest, size);
1269 close_dest:
1270 close(source_fd);
1271 unmap_source:
1272 munmap(source, size);
1273 close_source:
1274 close(source_fd);
1275 err:
1276 return res;
1277}
1278
1279int mailmbox_expunge_no_lock(struct mailmbox_folder * folder)
1280{
1281 char tmpfile[PATH_MAX];
1282 int r;
1283 int res;
1284 int dest_fd;
1285 size_t size;
1286 mode_t old_mask;
1287
1288 if (folder->mb_read_only)
1289 return MAILMBOX_ERROR_READONLY;
1290
1291 if (((folder->mb_written_uid >= folder->mb_max_uid) || folder->mb_no_uid) &&
1292 (!folder->mb_changed)) {
1293 /* no need to expunge */
1294 return MAILMBOX_NO_ERROR;
1295 }
1296
1297 snprintf(tmpfile, PATH_MAX, "%sXXXXXX", folder->mb_filename);
1298 old_mask = umask(0077);
1299 dest_fd = mkstemp(tmpfile);
1300 umask(old_mask);
1301
1302 if (dest_fd < 0) {
1303 /* fallback to tmp dir */
1304
1305 snprintf(tmpfile, PATH_MAX, TMPDIR "/etpan-unsafe-XXXXXX");
1306
1307 old_mask = umask(0077);
1308 dest_fd = mkstemp(tmpfile);
1309 umask(old_mask);
1310
1311 if (dest_fd < 0) {
1312 res = MAILMBOX_ERROR_FILE;
1313 goto err;
1314 }
1315 }
1316
1317 r = mailmbox_expunge_to_file_no_lock(tmpfile, dest_fd,
1318 folder, &size);
1319 if (r != MAILMBOX_NO_ERROR) {
1320 res = r;
1321 goto unlink;
1322 }
1323
1324 close(dest_fd);
1325
1326 r = rename(tmpfile, folder->mb_filename);
1327 if (r < 0) {
1328 mailmbox_unmap(folder);
1329 mailmbox_close(folder);
1330
1331 /* fallback on copy to old file */
1332
1333 r = copy_to_old_file(tmpfile, folder->mb_filename, size);
1334 if (r != MAILMBOX_NO_ERROR) {
1335 res = r;
1336 goto err;
1337 }
1338
1339 unlink(tmpfile);
1340 }
1341 else {
1342 mailmbox_unmap(folder);
1343 mailmbox_close(folder);
1344 }
1345
1346 r = mailmbox_open(folder);
1347 if (r != MAILMBOX_NO_ERROR) {
1348 res = r;
1349 goto err;
1350 }
1351
1352 r = mailmbox_map(folder);
1353 if (r != MAILMBOX_NO_ERROR) {
1354 res = r;
1355 goto err;
1356 }
1357
1358 r = mailmbox_parse(folder);
1359 if (r != MAILMBOX_NO_ERROR) {
1360 res = r;
1361 goto err;
1362 }
1363
1364 mailmbox_timestamp(folder);
1365
1366 folder->mb_changed = FALSE;
1367 folder->mb_deleted_count = 0;
1368
1369 return MAILMBOX_NO_ERROR;
1370
1371 unlink:
1372 close(dest_fd);
1373 unlink(tmpfile);
1374 err:
1375 return res;
1376}
1377
1378int mailmbox_expunge(struct mailmbox_folder * folder)
1379{
1380 int r;
1381 int res;
1382
1383 r = mailmbox_validate_write_lock(folder);
1384 if (r != MAILMBOX_NO_ERROR) {
1385 res = r;
1386 goto err;
1387 }
1388
1389 r = mailmbox_expunge_no_lock(folder);
1390 res = r;
1391
1392 mailmbox_write_unlock(folder);
1393 err:
1394 return res;
1395}
1396
1397int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid)
1398{
1399 struct mailmbox_msg_info * info;
1400 int res;
1401 chashdatum key;
1402 chashdatum data;
1403 int r;
1404
1405 if (folder->mb_read_only) {
1406 res = MAILMBOX_ERROR_READONLY;
1407 goto err;
1408 }
1409
1410 key.data = &uid;
1411 key.len = sizeof(uid);
1412
1413 r = chash_get(folder->mb_hash, &key, &data);
1414 if (r < 0) {
1415 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
1416 goto err;
1417 }
1418
1419 info = data.data;
1420
1421 if (info->msg_deleted) {
1422 res = MAILMBOX_ERROR_MSG_NOT_FOUND;
1423 goto err;
1424 }
1425
1426 info->msg_deleted = TRUE;
1427 folder->mb_changed = TRUE;
1428 folder->mb_deleted_count ++;
1429
1430 return MAILMBOX_NO_ERROR;
1431
1432 err:
1433 return res;
1434}
1435
1436
1437/*
1438 INIT of MBOX
1439
1440 - open file
1441 - map the file
1442
1443 - lock the file
1444
1445 - parse memory
1446
1447 - unlock the file
1448*/
1449
1450int mailmbox_init(const char * filename,
1451 int force_readonly,
1452 int force_no_uid,
1453 uint32_t default_written_uid,
1454 struct mailmbox_folder ** result_folder)
1455{
1456 struct mailmbox_folder * folder;
1457 int r;
1458 int res;
1459
1460 folder = mailmbox_folder_new(filename);
1461 if (folder == NULL) {
1462 res = MAILMBOX_ERROR_MEMORY;
1463 goto err;
1464 }
1465 folder->mb_no_uid = force_no_uid;
1466 folder->mb_read_only = force_readonly;
1467 folder->mb_written_uid = default_written_uid;
1468
1469 folder->mb_changed = FALSE;
1470 folder->mb_deleted_count = 0;
1471
1472 r = mailmbox_open(folder);
1473 if (r != MAILMBOX_NO_ERROR) {
1474 res = r;
1475 goto free;
1476 }
1477
1478 r = mailmbox_map(folder);
1479 if (r != MAILMBOX_NO_ERROR) {
1480 res = r;
1481 goto close;
1482 }
1483
1484 r = mailmbox_validate_read_lock(folder);
1485 if (r != MAILMBOX_NO_ERROR) {
1486 res = r;
1487 goto unmap;
1488 }
1489
1490 mailmbox_read_unlock(folder);
1491
1492 * result_folder = folder;
1493
1494 return MAILMBOX_NO_ERROR;
1495
1496 unmap:
1497 mailmbox_unmap(folder);
1498 close:
1499 mailmbox_close(folder);
1500 free:
1501 mailmbox_folder_free(folder);
1502 err:
1503 return res;
1504}
1505
1506
1507/*
1508 when MBOX is DONE
1509
1510 - check for changes
1511
1512 - unmap the file
1513 - close file
1514*/
1515
1516void mailmbox_done(struct mailmbox_folder * folder)
1517{
1518 if (!folder->mb_read_only)
1519 mailmbox_expunge(folder);
1520
1521 mailmbox_unmap(folder);
1522 mailmbox_close(folder);
1523
1524 mailmbox_folder_free(folder);
1525}
diff --git a/libetpan/src/low-level/mbox/mailmbox.h b/libetpan/src/low-level/mbox/mailmbox.h
new file mode 100644
index 0000000..ea21d48
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox.h
@@ -0,0 +1,144 @@
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 MAILMBOX_H
37
38#define MAILMBOX_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/mailmbox_types.h>
45
46int
47mailmbox_append_message_list(struct mailmbox_folder * folder,
48 carray * append_tab);
49
50int
51mailmbox_append_message(struct mailmbox_folder * folder,
52 const char * data, size_t len);
53
54int
55mailmbox_append_message_uid(struct mailmbox_folder * folder,
56 const char * data, size_t len, unsigned int * puid);
57
58int mailmbox_fetch_msg(struct mailmbox_folder * folder,
59 uint32_t num, char ** result,
60 size_t * result_len);
61
62int mailmbox_fetch_msg_headers(struct mailmbox_folder * folder,
63 uint32_t num, char ** result,
64 size_t * result_len);
65
66void mailmbox_fetch_result_free(char * msg);
67
68int mailmbox_copy_msg_list(struct mailmbox_folder * dest_folder,
69 struct mailmbox_folder * src_folder,
70 carray * tab);
71
72int mailmbox_copy_msg(struct mailmbox_folder * dest_folder,
73 struct mailmbox_folder * src_folder,
74 uint32_t uid);
75
76int mailmbox_expunge(struct mailmbox_folder * folder);
77
78int mailmbox_delete_msg(struct mailmbox_folder * folder, uint32_t uid);
79
80int mailmbox_init(const char * filename,
81 int force_readonly,
82 int force_no_uid,
83 uint32_t default_written_uid,
84 struct mailmbox_folder ** result_folder);
85
86void mailmbox_done(struct mailmbox_folder * folder);
87
88/* low-level access primitives */
89
90int mailmbox_write_lock(struct mailmbox_folder * folder);
91
92int mailmbox_write_unlock(struct mailmbox_folder * folder);
93
94int mailmbox_read_lock(struct mailmbox_folder * folder);
95
96int mailmbox_read_unlock(struct mailmbox_folder * folder);
97
98
99/* memory map */
100
101int mailmbox_map(struct mailmbox_folder * folder);
102
103void mailmbox_unmap(struct mailmbox_folder * folder);
104
105void mailmbox_sync(struct mailmbox_folder * folder);
106
107
108/* open & close file */
109
110int mailmbox_open(struct mailmbox_folder * folder);
111
112void mailmbox_close(struct mailmbox_folder * folder);
113
114
115/* validate cache */
116
117int mailmbox_validate_write_lock(struct mailmbox_folder * folder);
118
119int mailmbox_validate_read_lock(struct mailmbox_folder * folder);
120
121
122/* fetch message */
123
124int mailmbox_fetch_msg_no_lock(struct mailmbox_folder * folder,
125 uint32_t num, char ** result,
126 size_t * result_len);
127
128int mailmbox_fetch_msg_headers_no_lock(struct mailmbox_folder * folder,
129 uint32_t num, char ** result,
130 size_t * result_len);
131
132/* append message */
133
134int
135mailmbox_append_message_list_no_lock(struct mailmbox_folder * folder,
136 carray * append_tab);
137
138int mailmbox_expunge_no_lock(struct mailmbox_folder * folder);
139
140#ifdef __cplusplus
141}
142#endif
143
144#endif
diff --git a/libetpan/src/low-level/mbox/mailmbox_parse.c b/libetpan/src/low-level/mbox/mailmbox_parse.c
new file mode 100644
index 0000000..65642ac
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox_parse.c
@@ -0,0 +1,620 @@
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 "mailmbox_parse.h"
37
38#include "mailmbox.h"
39
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <string.h>
43#include <stdlib.h>
44
45#define UID_HEADER "X-LibEtPan-UID:"
46
47#ifndef TRUE
48#define TRUE 1
49#endif
50
51#ifndef FALSE
52#define FALSE 0
53#endif
54
55enum {
56 UNSTRUCTURED_START,
57 UNSTRUCTURED_CR,
58 UNSTRUCTURED_LF,
59 UNSTRUCTURED_WSP,
60 UNSTRUCTURED_OUT
61};
62
63static inline int
64mailmbox_fields_parse(char * str, size_t length,
65 size_t * index,
66 uint32_t * puid,
67 size_t * phlen)
68{
69 size_t cur_token;
70 int r;
71 size_t hlen;
72 size_t uid;
73 int end;
74
75 cur_token = * index;
76
77 end = FALSE;
78 uid = 0;
79 while (!end) {
80 size_t begin;
81
82 begin = cur_token;
83
84 r = mailimf_ignore_field_parse(str, length, &cur_token);
85 switch (r) {
86 case MAILIMF_NO_ERROR:
87 if (str[begin] == 'X') {
88
89 if (strncasecmp(str + begin, UID_HEADER, strlen(UID_HEADER)) == 0) {
90 begin += strlen(UID_HEADER);
91
92 while (str[begin] == ' ')
93 begin ++;
94
95 uid = strtoul(str + begin, NULL, 10);
96 }
97 }
98
99 break;
100 case MAILIMF_ERROR_PARSE:
101 default:
102 end = TRUE;
103 break;
104 }
105 }
106
107 hlen = cur_token - * index;
108
109 * phlen = hlen;
110 * puid = uid;
111 * index = cur_token;
112
113 return MAILMBOX_NO_ERROR;
114}
115
116enum {
117 IN_MAIL,
118 FIRST_CR,
119 FIRST_LF,
120 SECOND_CR,
121 SECOND_LF,
122 PARSING_F,
123 PARSING_R,
124 PARSING_O,
125 PARSING_M,
126 OUT_MAIL
127};
128
129
130
131
132static inline int
133mailmbox_single_parse(char * str, size_t length,
134 size_t * index,
135 size_t * pstart,
136 size_t * pstart_len,
137 size_t * pheaders,
138 size_t * pheaders_len,
139 size_t * pbody,
140 size_t * pbody_len,
141 size_t * psize,
142 size_t * ppadding,
143 uint32_t * puid)
144{
145 size_t cur_token;
146 size_t start;
147 size_t start_len;
148 size_t headers;
149 size_t headers_len;
150 size_t body;
151 size_t end;
152 size_t next;
153 size_t message_length;
154 uint32_t uid;
155 int r;
156#if 0
157 int in_mail_data;
158#endif
159#if 0
160 size_t begin;
161#endif
162
163 int state;
164
165 cur_token = * index;
166
167 if (cur_token >= length)
168 return MAILMBOX_ERROR_PARSE;
169
170 start = cur_token;
171 start_len = 0;
172 headers = cur_token;
173
174 if (cur_token + 5 < length) {
175 if (strncmp(str + cur_token, "From ", 5) == 0) {
176 cur_token += 5;
177 while (str[cur_token] != '\n') {
178 cur_token ++;
179 if (cur_token >= length)
180 break;
181 }
182 if (cur_token < length) {
183 cur_token ++;
184 headers = cur_token;
185 start_len = headers - start;
186 }
187 }
188 }
189
190 next = length;
191
192 r = mailmbox_fields_parse(str, length, &cur_token,
193 &uid, &headers_len);
194 if (r != MAILMBOX_NO_ERROR)
195 return r;
196
197 /* save position */
198#if 0
199 begin = cur_token;
200#endif
201
202 mailimf_crlf_parse(str, length, &cur_token);
203
204#if 0
205 if (str[cur_token] == 'F') {
206 printf("start !\n");
207 printf("%50.50s\n", str + cur_token);
208 getchar();
209 }
210#endif
211
212 body = cur_token;
213
214 /* restore position */
215 /* cur_token = begin; */
216
217 state = FIRST_LF;
218
219 end = length;
220
221#if 0
222 in_mail_data = 0;
223#endif
224 while (state != OUT_MAIL) {
225
226 if (cur_token >= length) {
227 if (state == IN_MAIL)
228 end = length;
229 next = length;
230 break;
231 }
232
233 switch(state) {
234 case IN_MAIL:
235 switch(str[cur_token]) {
236 case '\r':
237 state = FIRST_CR;
238 break;
239 case '\n':
240 state = FIRST_LF;
241 break;
242 case 'F':
243 if (cur_token == body) {
244 end = cur_token;
245 next = cur_token;
246 state = PARSING_F;
247 }
248 break;
249#if 0
250 default:
251 in_mail_data = 1;
252 break;
253#endif
254 }
255 break;
256
257 case FIRST_CR:
258 end = cur_token;
259 switch(str[cur_token]) {
260 case '\r':
261 state = SECOND_CR;
262 break;
263 case '\n':
264 state = FIRST_LF;
265 break;
266 default:
267 state = IN_MAIL;
268#if 0
269 in_mail_data = 1;
270#endif
271 break;
272 }
273 break;
274
275 case FIRST_LF:
276 end = cur_token;
277 switch(str[cur_token]) {
278 case '\r':
279 state = SECOND_CR;
280 break;
281 case '\n':
282 state = SECOND_LF;
283 break;
284 default:
285 state = IN_MAIL;
286#if 0
287 in_mail_data = 1;
288#endif
289 break;
290 }
291 break;
292
293 case SECOND_CR:
294 switch(str[cur_token]) {
295 case '\r':
296 end = cur_token;
297 break;
298 case '\n':
299 state = SECOND_LF;
300 break;
301 case 'F':
302 next = cur_token;
303 state = PARSING_F;
304 break;
305 default:
306 state = IN_MAIL;
307#if 0
308 in_mail_data = 1;
309#endif
310 break;
311 }
312 break;
313
314 case SECOND_LF:
315 switch(str[cur_token]) {
316 case '\r':
317 state = SECOND_CR;
318 break;
319 case '\n':
320 end = cur_token;
321 break;
322 case 'F':
323 next = cur_token;
324 state = PARSING_F;
325 break;
326 default:
327 state = IN_MAIL;
328#if 0
329 in_mail_data = 1;
330#endif
331 break;
332 }
333 break;
334
335 case PARSING_F:
336 switch(str[cur_token]) {
337 case 'r':
338 state = PARSING_R;
339 break;
340 default:
341 state = IN_MAIL;
342#if 0
343 in_mail_data = 1;
344#endif
345 break;
346 }
347 break;
348
349 case PARSING_R:
350 switch(str[cur_token]) {
351 case 'o':
352 state = PARSING_O;
353 break;
354 default:
355 state = IN_MAIL;
356#if 0
357 in_mail_data = 1;
358#endif
359 break;
360 }
361 break;
362
363 case PARSING_O:
364 switch(str[cur_token]) {
365 case 'm':
366 state = PARSING_M;
367 break;
368 default:
369 state = IN_MAIL;
370#if 0
371 in_mail_data = 1;
372#endif
373 break;
374 }
375 break;
376
377 case PARSING_M:
378 switch(str[cur_token]) {
379 case ' ':
380 state = OUT_MAIL;
381 break;
382 default:
383 state = IN_MAIL;
384 break;
385 }
386 break;
387 }
388
389 cur_token ++;
390 }
391
392 message_length = end - start;
393
394 * pstart = start;
395 * pstart_len = start_len;
396 * pheaders = headers;
397 * pheaders_len = headers_len;
398 * pbody = body;
399 * pbody_len = end - body;
400 * psize = message_length;
401 * ppadding = next - end;
402 * puid = uid;
403
404 * index = next;
405
406 return MAILMBOX_NO_ERROR;
407}
408
409
410int
411mailmbox_parse_additionnal(struct mailmbox_folder * folder,
412 size_t * index)
413{
414 size_t cur_token;
415
416 size_t start;
417 size_t start_len;
418 size_t headers;
419 size_t headers_len;
420 size_t body;
421 size_t body_len;
422 size_t size;
423 size_t padding;
424 uint32_t uid;
425 int r;
426 int res;
427
428 uint32_t max_uid;
429 uint32_t first_index;
430 unsigned int i;
431 unsigned int j;
432
433 cur_token = * index;
434
435 /* remove temporary UID that we will parse */
436
437 first_index = carray_count(folder->mb_tab);
438
439 for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
440 struct mailmbox_msg_info * info;
441
442 info = carray_get(folder->mb_tab, i);
443
444 if (info->msg_start < cur_token) {
445 continue;
446 }
447
448 if (!info->msg_written_uid) {
449 chashdatum key;
450
451 key.data = &info->msg_uid;
452 key.len = sizeof(info->msg_uid);
453
454 chash_delete(folder->mb_hash, &key, NULL);
455 carray_delete_fast(folder->mb_tab, i);
456 mailmbox_msg_info_free(info);
457 if (i < first_index)
458 first_index = i;
459 }
460 }
461
462 /* make a sequence in the table */
463
464 max_uid = folder->mb_written_uid;
465
466 i = 0;
467 j = 0;
468 while (i < carray_count(folder->mb_tab)) {
469 struct mailmbox_msg_info * info;
470
471 info = carray_get(folder->mb_tab, i);
472 if (info != NULL) {
473 carray_set(folder->mb_tab, j, info);
474
475 if (info->msg_uid > max_uid)
476 max_uid = info->msg_uid;
477
478 info->msg_index = j;
479 j ++;
480 }
481 i ++;
482 }
483 carray_set_size(folder->mb_tab, j);
484
485 /* parse content */
486
487 first_index = j;
488
489 while (1) {
490 struct mailmbox_msg_info * info;
491 chashdatum key;
492 chashdatum data;
493
494 r = mailmbox_single_parse(folder->mb_mapping, folder->mb_mapping_size,
495 &cur_token,
496 &start, &start_len,
497 &headers, &headers_len,
498 &body, &body_len,
499 &size, &padding, &uid);
500 if (r == MAILMBOX_NO_ERROR) {
501 /* do nothing */
502 }
503 else if (r == MAILMBOX_ERROR_PARSE)
504 break;
505 else {
506 res = r;
507 goto err;
508 }
509
510 key.data = &uid;
511 key.len = sizeof(uid);
512
513 r = chash_get(folder->mb_hash, &key, &data);
514 if (r == 0) {
515 info = data.data;
516
517 if (!info->msg_written_uid) {
518 /* some new mail has been written and override an
519 existing temporary UID */
520
521 chash_delete(folder->mb_hash, &key, NULL);
522 info->msg_uid = 0;
523
524 if (info->msg_index < first_index)
525 first_index = info->msg_index;
526 }
527 else
528 uid = 0;
529 }
530
531 if (uid > max_uid)
532 max_uid = uid;
533
534 r = mailmbox_msg_info_update(folder,
535 start, start_len, headers, headers_len,
536 body, body_len, size, padding, uid);
537 if (r != MAILMBOX_NO_ERROR) {
538 res = r;
539 goto err;
540 }
541 }
542
543 * index = cur_token;
544
545 folder->mb_written_uid = max_uid;
546
547 /* attribute uid */
548
549 for(i = first_index ; i < carray_count(folder->mb_tab) ; i ++) {
550 struct mailmbox_msg_info * info;
551 chashdatum key;
552 chashdatum data;
553
554 info = carray_get(folder->mb_tab, i);
555
556 if (info->msg_uid != 0) {
557 continue;
558 }
559
560 max_uid ++;
561 info->msg_uid = max_uid;
562
563 key.data = &info->msg_uid;
564 key.len = sizeof(info->msg_uid);
565 data.data = info;
566 data.len = 0;
567
568 r = chash_set(folder->mb_hash, &key, &data, NULL);
569 if (r < 0) {
570 res = MAILMBOX_ERROR_MEMORY;
571 goto err;
572 }
573 }
574
575 folder->mb_max_uid = max_uid;
576
577 return MAILMBOX_NO_ERROR;
578
579 err:
580 return res;
581}
582
583static void flush_uid(struct mailmbox_folder * folder)
584{
585 unsigned int i;
586
587 for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
588 struct mailmbox_msg_info * info;
589
590 info = carray_get(folder->mb_tab, i);
591 if (info != NULL)
592 mailmbox_msg_info_free(info);
593 }
594
595 chash_clear(folder->mb_hash);
596 carray_set_size(folder->mb_tab, 0);
597}
598
599int mailmbox_parse(struct mailmbox_folder * folder)
600{
601 int r;
602 int res;
603 size_t cur_token;
604
605 flush_uid(folder);
606
607 cur_token = 0;
608
609 r = mailmbox_parse_additionnal(folder, &cur_token);
610
611 if (r != MAILMBOX_NO_ERROR) {
612 res = r;
613 goto err;
614 }
615
616 return MAILMBOX_NO_ERROR;
617
618 err:
619 return res;
620}
diff --git a/libetpan/src/low-level/mbox/mailmbox_parse.h b/libetpan/src/low-level/mbox/mailmbox_parse.h
new file mode 100644
index 0000000..6b533a9
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox_parse.h
@@ -0,0 +1,56 @@
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 MAILMBOX_PARSE_H
37
38#define MAILMBOX_PARSE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include "mailmbox_types.h"
45
46int mailmbox_parse(struct mailmbox_folder * folder);
47
48int
49mailmbox_parse_additionnal(struct mailmbox_folder * folder,
50 size_t * index);
51
52#ifdef __cplusplus
53}
54#endif
55
56#endif
diff --git a/libetpan/src/low-level/mbox/mailmbox_types.c b/libetpan/src/low-level/mbox/mailmbox_types.c
new file mode 100644
index 0000000..aaf76dc
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox_types.c
@@ -0,0 +1,251 @@
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 "mailmbox_types.h"
37
38#include <string.h>
39#include <stdlib.h>
40
41#ifndef TRUE
42#define TRUE 1
43#endif
44
45#ifndef FALSE
46#define FALSE 0
47#endif
48
49/* *********************************************************************** */
50
51int mailmbox_msg_info_update(struct mailmbox_folder * folder,
52 size_t msg_start, size_t msg_start_len,
53 size_t msg_headers, size_t msg_headers_len,
54 size_t msg_body, size_t msg_body_len,
55 size_t msg_size, size_t msg_padding,
56 uint32_t msg_uid)
57{
58 struct mailmbox_msg_info * info;
59 int res;
60 chashdatum key;
61 chashdatum data;
62 int r;
63
64 key.data = &msg_uid;
65 key.len = sizeof(msg_uid);
66 r = chash_get(folder->mb_hash, &key, &data);
67 if (r < 0) {
68 unsigned int index;
69
70 info = mailmbox_msg_info_new(msg_start, msg_start_len,
71 msg_headers, msg_headers_len,
72 msg_body, msg_body_len, msg_size, msg_padding, msg_uid);
73 if (info == NULL) {
74 res = MAILMBOX_ERROR_MEMORY;
75 goto err;
76 }
77
78 r = carray_add(folder->mb_tab, info, &index);
79 if (r < 0) {
80 mailmbox_msg_info_free(info);
81 res = MAILMBOX_ERROR_MEMORY;
82 goto err;
83 }
84
85 if (msg_uid != 0) {
86 chashdatum key;
87 chashdatum data;
88
89 key.data = &msg_uid;
90 key.len = sizeof(msg_uid);
91 data.data = info;
92 data.len = 0;
93
94 r = chash_set(folder->mb_hash, &key, &data, NULL);
95 if (r < 0) {
96 mailmbox_msg_info_free(info);
97 carray_delete(folder->mb_tab, index);
98 res = MAILMBOX_ERROR_MEMORY;
99 goto err;
100 }
101 }
102
103 info->msg_index = index;
104 }
105 else {
106 info = data.data;
107
108 info->msg_start = msg_start;
109 info->msg_start_len = msg_start_len;
110 info->msg_headers = msg_headers;
111 info->msg_headers_len = msg_headers_len;
112 info->msg_body = msg_body;
113 info->msg_body_len = msg_body_len;
114 info->msg_size = msg_size;
115 info->msg_padding = msg_padding;
116 }
117
118 return MAILMBOX_NO_ERROR;
119
120 err:
121 return res;
122}
123
124
125struct mailmbox_msg_info *
126mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len,
127 size_t msg_headers, size_t msg_headers_len,
128 size_t msg_body, size_t msg_body_len,
129 size_t msg_size, size_t msg_padding,
130 uint32_t msg_uid)
131{
132 struct mailmbox_msg_info * info;
133
134 info = malloc(sizeof(* info));
135 if (info == NULL)
136 return NULL;
137
138 info->msg_index = 0;
139 info->msg_uid = msg_uid;
140 if (msg_uid != 0)
141 info->msg_written_uid = TRUE;
142 else
143 info->msg_written_uid = FALSE;
144 info->msg_deleted = FALSE;
145
146 info->msg_start = msg_start;
147 info->msg_start_len = msg_start_len;
148
149 info->msg_headers = msg_headers;
150 info->msg_headers_len = msg_headers_len;
151
152 info->msg_body = msg_body;
153 info->msg_body_len = msg_body_len;
154
155 info->msg_size = msg_size;
156
157 info->msg_padding = msg_padding;
158
159 return info;
160}
161
162void mailmbox_msg_info_free(struct mailmbox_msg_info * info)
163{
164 free(info);
165}
166
167
168/* append info */
169
170struct mailmbox_append_info *
171mailmbox_append_info_new(const char * ai_message, size_t ai_size)
172{
173 struct mailmbox_append_info * info;
174
175 info = malloc(sizeof(* info));
176 if (info == NULL)
177 return NULL;
178
179 info->ai_message = ai_message;
180 info->ai_size = ai_size;
181 info->ai_uid = 0;
182
183 return info;
184}
185
186void mailmbox_append_info_free(struct mailmbox_append_info * info)
187{
188 free(info);
189}
190
191struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename)
192{
193 struct mailmbox_folder * folder;
194
195 folder = malloc(sizeof(* folder));
196 if (folder == NULL)
197 goto err;
198
199 strncpy(folder->mb_filename, mb_filename, PATH_MAX);
200
201 folder->mb_mtime = (time_t) -1;
202
203 folder->mb_fd = -1;
204 folder->mb_read_only = TRUE;
205 folder->mb_no_uid = TRUE;
206
207 folder->mb_changed = FALSE;
208 folder->mb_deleted_count = 0;
209
210 folder->mb_mapping = NULL;
211 folder->mb_mapping_size = 0;
212
213 folder->mb_written_uid = 0;
214 folder->mb_max_uid = 0;
215
216 folder->mb_hash = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
217 if (folder->mb_hash == NULL)
218 goto free;
219
220 folder->mb_tab = carray_new(128);
221 if (folder->mb_tab == NULL)
222 goto free_hash;
223
224 return folder;
225
226 free_hash:
227 chash_free(folder->mb_hash);
228 free:
229 free(folder);
230 err:
231 return NULL;
232}
233
234void mailmbox_folder_free(struct mailmbox_folder * folder)
235{
236 unsigned int i;
237
238 for(i = 0 ; i < carray_count(folder->mb_tab) ; i++) {
239 struct mailmbox_msg_info * info;
240
241 info = carray_get(folder->mb_tab, i);
242 if (info != NULL)
243 mailmbox_msg_info_free(info);
244 }
245
246 carray_free(folder->mb_tab);
247
248 chash_free(folder->mb_hash);
249
250 free(folder);
251}
diff --git a/libetpan/src/low-level/mbox/mailmbox_types.h b/libetpan/src/low-level/mbox/mailmbox_types.h
new file mode 100644
index 0000000..4ce241d
--- a/dev/null
+++ b/libetpan/src/low-level/mbox/mailmbox_types.h
@@ -0,0 +1,143 @@
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 MAILMBOX_TYPES_H
37
38#define MAILMBOX_TYPES_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <sys/types.h>
45
46#include <libetpan/libetpan-config.h>
47
48#include <libetpan/mailimf.h>
49#include <libetpan/carray.h>
50#include <libetpan/chash.h>
51
52enum {
53 MAILMBOX_NO_ERROR = 0,
54 MAILMBOX_ERROR_PARSE,
55 MAILMBOX_ERROR_INVAL,
56 MAILMBOX_ERROR_FILE_NOT_FOUND,
57 MAILMBOX_ERROR_MEMORY,
58 MAILMBOX_ERROR_TEMPORARY_FILE,
59 MAILMBOX_ERROR_FILE,
60 MAILMBOX_ERROR_MSG_NOT_FOUND,
61 MAILMBOX_ERROR_READONLY,
62};
63
64
65struct mailmbox_folder {
66 char mb_filename[PATH_MAX];
67
68 time_t mb_mtime;
69
70 int mb_fd;
71 int mb_read_only;
72 int mb_no_uid;
73
74 int mb_changed;
75 unsigned int mb_deleted_count;
76
77 char * mb_mapping;
78 size_t mb_mapping_size;
79
80 uint32_t mb_written_uid;
81 uint32_t mb_max_uid;
82
83 chash * mb_hash;
84 carray * mb_tab;
85};
86
87struct mailmbox_folder * mailmbox_folder_new(const char * mb_filename);
88void mailmbox_folder_free(struct mailmbox_folder * folder);
89
90
91struct mailmbox_msg_info {
92 unsigned int msg_index;
93 uint32_t msg_uid;
94 int msg_written_uid;
95 int msg_deleted;
96
97 size_t msg_start;
98 size_t msg_start_len;
99
100 size_t msg_headers;
101 size_t msg_headers_len;
102
103 size_t msg_body;
104 size_t msg_body_len;
105
106 size_t msg_size;
107
108 size_t msg_padding;
109};
110
111
112int mailmbox_msg_info_update(struct mailmbox_folder * folder,
113 size_t msg_start, size_t msg_start_len,
114 size_t msg_headers, size_t msg_headers_len,
115 size_t msg_body, size_t msg_body_len,
116 size_t msg_size, size_t msg_padding,
117 uint32_t msg_uid);
118
119struct mailmbox_msg_info *
120mailmbox_msg_info_new(size_t msg_start, size_t msg_start_len,
121 size_t msg_headers, size_t msg_headers_len,
122 size_t msg_body, size_t msg_body_len,
123 size_t msg_size, size_t msg_padding,
124 uint32_t msg_uid);
125
126void mailmbox_msg_info_free(struct mailmbox_msg_info * info);
127
128struct mailmbox_append_info {
129 const char * ai_message;
130 size_t ai_size;
131 unsigned int ai_uid;
132};
133
134struct mailmbox_append_info *
135mailmbox_append_info_new(const char * ai_message, size_t ai_size);
136
137void mailmbox_append_info_free(struct mailmbox_append_info * info);
138
139#ifdef __cplusplus
140}
141#endif
142
143#endif