summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/db/dbdriver.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/db/dbdriver.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/db/dbdriver.c1134
1 files changed, 1134 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/db/dbdriver.c b/libetpan/src/driver/implementation/db/dbdriver.c
new file mode 100644
index 0000000..e374e64
--- a/dev/null
+++ b/libetpan/src/driver/implementation/db/dbdriver.c
@@ -0,0 +1,1134 @@
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 "dbdriver.h"
37#include "imfcache.h"
38#include "generic_cache.h"
39#include "libetpan-config.h"
40#include "dbdriver_message.h"
41#include "mail_cache_db.h"
42#include <string.h>
43#include <stdlib.h>
44#include "mailmessage.h"
45
46static int initialize(mailsession * session);
47
48static void uninitialize(mailsession * session);
49
50static int connect_path(mailsession * session, char * path);
51
52static int logout(mailsession * session);
53
54static int expunge_folder(mailsession * session);
55
56static int status_folder(mailsession * session, char * mb,
57 uint32_t * result_messages, uint32_t * result_recent,
58 uint32_t * result_unseen);
59
60static int recent_number(mailsession * session, char * mb,
61 uint32_t * result);
62
63static int unseen_number(mailsession * session, char * mb,
64 uint32_t * result);
65
66static int messages_number(mailsession * session, char * mb,
67 uint32_t * result);
68
69static int append_message(mailsession * session,
70 char * message, size_t size);
71
72static int append_message_flags(mailsession * session,
73 char * message, size_t size, struct mail_flags * flags);
74
75static int get_messages_list(mailsession * session,
76 struct mailmessage_list ** result);
77
78static int get_envelopes_list(mailsession * session,
79 struct mailmessage_list * env_list);
80
81static int check_folder(mailsession * session);
82
83static int get_message(mailsession * session,
84 uint32_t num, mailmessage ** result);
85
86static int get_message_by_uid(mailsession * session,
87 const char * uid, mailmessage ** result);
88
89static mailsession_driver local_db_session_driver = {
90 .sess_name = "db",
91
92 .sess_initialize = initialize,
93 .sess_uninitialize = uninitialize,
94
95 .sess_parameters = NULL,
96
97 .sess_connect_stream = NULL,
98 .sess_connect_path = connect_path,
99 .sess_starttls = NULL,
100 .sess_login = NULL,
101 .sess_logout = logout,
102 .sess_noop = NULL,
103
104 .sess_build_folder_name = NULL,
105 .sess_create_folder = NULL,
106 .sess_delete_folder = NULL,
107 .sess_rename_folder = NULL,
108 .sess_check_folder = check_folder,
109 .sess_examine_folder = NULL,
110 .sess_select_folder = NULL,
111 .sess_expunge_folder = expunge_folder,
112 .sess_status_folder = status_folder,
113 .sess_messages_number = messages_number,
114 .sess_recent_number = recent_number,
115 .sess_unseen_number = unseen_number,
116 .sess_list_folders = NULL,
117 .sess_lsub_folders = NULL,
118 .sess_subscribe_folder = NULL,
119 .sess_unsubscribe_folder = NULL,
120
121 .sess_append_message = append_message,
122 .sess_append_message_flags = append_message_flags,
123 .sess_copy_message = NULL,
124 .sess_move_message = NULL,
125
126 .sess_get_messages_list = get_messages_list,
127 .sess_get_envelopes_list = get_envelopes_list,
128 .sess_remove_message = NULL,
129
130 .sess_get_message = get_message,
131 .sess_get_message_by_uid = get_message_by_uid,
132};
133
134mailsession_driver * db_session_driver = &local_db_session_driver;
135
136static inline struct db_session_state_data * get_data(mailsession * session)
137{
138 return session->sess_data;
139}
140
141static int flags_store_process(mailsession * session)
142{
143 unsigned int i;
144 MMAPString * mmapstr;
145 int r;
146 int res;
147 struct mail_cache_db * maildb;
148 struct db_session_state_data * data;
149 struct mail_flags_store * flags_store;
150
151 data = get_data(session);
152
153 flags_store = data->db_flags_store;
154
155 if (carray_count(flags_store->fls_tab) == 0)
156 return MAIL_NO_ERROR;
157
158 mmapstr = mmap_string_new("");
159 if (mmapstr == NULL) {
160 res = MAIL_ERROR_MEMORY;
161 goto err;
162 }
163
164 r = mail_cache_db_open_lock(data->db_filename, &maildb);
165 if (r < 0) {
166 res = MAIL_ERROR_FILE;
167 goto free_mmapstr;
168 }
169
170 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
171 mailmessage * msg;
172 char key[PATH_MAX];
173
174 msg = carray_get(flags_store->fls_tab, i);
175
176 snprintf(key, sizeof(key), "%lu-flags", (unsigned long) msg->msg_index);
177
178 r = generic_cache_flags_write(maildb, mmapstr,
179 key, msg->msg_flags);
180 }
181
182 mail_flags_store_clear(flags_store);
183
184 mail_cache_db_close_unlock(data->db_filename, maildb);
185 mmap_string_free(mmapstr);
186
187 return MAIL_NO_ERROR;
188
189 free_mmapstr:
190 mmap_string_free(mmapstr);
191 err:
192 return res;
193}
194
195static int db_get_next_validity(struct mail_cache_db * maildb,
196 uint32_t * p_validity)
197{
198 int r;
199 char key_value[PATH_MAX];
200 uint32_t validity;
201 void * serialized;
202 size_t serialized_len;
203 int res;
204 MMAPString * mmapstr;
205 size_t cur_token;
206
207 mmapstr = mmap_string_new_len(serialized, serialized_len);
208 if (mmapstr == NULL) {
209 res = MAIL_ERROR_MEMORY;
210 goto err;
211 }
212
213 snprintf(key_value, sizeof(key_value), "next-validity");
214
215 r = mail_cache_db_get(maildb, key_value, strlen(key_value),
216 &serialized, &serialized_len);
217
218 if (r >= 0) {
219 size_t cur_token;
220
221 cur_token = 0;
222 r = mailimf_cache_int_read(mmapstr, &cur_token, &validity);
223 if (r < 0)
224 validity = 0;
225 }
226 else {
227 validity = 0;
228 }
229
230 mmap_string_set_size(mmapstr, 0);
231 cur_token = 0;
232 r = mailimf_cache_int_write(mmapstr, &cur_token, validity + 1);
233 if (r < 0) {
234 res = MAIL_ERROR_MEMORY;
235 goto free_mmapstr;
236 }
237
238 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
239 mmapstr->str, mmapstr->len);
240 if (r < 0) {
241 res = MAIL_ERROR_FILE;
242 goto free_mmapstr;
243 }
244
245 mmap_string_free(mmapstr);
246
247 * p_validity = validity;
248
249 return MAIL_NO_ERROR;
250
251 free_mmapstr:
252 mmap_string_free(mmapstr);
253 err:
254 return res;
255}
256
257static int db_get_next_msg_number(struct mail_cache_db * maildb,
258 uint32_t * p_num)
259{
260 int r;
261 char key_value[PATH_MAX];
262 uint32_t num;
263 void * serialized;
264 size_t serialized_len;
265 int res;
266 MMAPString * mmapstr;
267 size_t cur_token;
268
269 mmapstr = mmap_string_new("");
270 if (mmapstr == NULL) {
271 res = MAIL_ERROR_MEMORY;
272 goto err;
273 }
274
275 snprintf(key_value, sizeof(key_value), "next-msg");
276
277 r = mail_cache_db_get(maildb, key_value, strlen(key_value),
278 &serialized, &serialized_len);
279
280 if (r >= 0) {
281 size_t cur_token;
282
283 if (mmap_string_append_len(mmapstr, serialized, serialized_len) == NULL) {
284 res = MAIL_ERROR_MEMORY;
285 goto err;
286 }
287
288 cur_token = 0;
289 r = mailimf_cache_int_read(mmapstr, &cur_token, &num);
290 if (r < 0)
291 num = 1;
292 }
293 else {
294 num = 1;
295 }
296
297 mmap_string_set_size(mmapstr, 0);
298 cur_token = 0;
299 r = mailimf_cache_int_write(mmapstr, &cur_token, num + 1);
300 if (r < 0) {
301 res = MAIL_ERROR_MEMORY;
302 goto free_mmapstr;
303 }
304
305 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
306 mmapstr->str, mmapstr->len);
307 if (r < 0) {
308 res = MAIL_ERROR_FILE;
309 goto free_mmapstr;
310 }
311
312 mmap_string_free(mmapstr);
313
314 * p_num = num;
315
316 return MAIL_NO_ERROR;
317
318 free_mmapstr:
319 mmap_string_free(mmapstr);
320 err:
321 return res;
322}
323
324static int db_set_message_list(struct mail_cache_db * maildb,
325 carray * msglist)
326{
327 MMAPString * mmapstr;
328 char key_value[PATH_MAX];
329 int r;
330 unsigned int i;
331 size_t cur_token;
332 int res;
333
334 mmapstr = mmap_string_new("");
335 if (mmapstr == NULL) {
336 res = MAIL_ERROR_MEMORY;
337 goto err;
338 }
339
340 cur_token = 0;
341 for(i = 0 ; i < carray_count(msglist) ; i ++) {
342 uint32_t * msg;
343
344 msg = carray_get(msglist, i);
345 r = mailimf_cache_int_write(mmapstr, &cur_token, * msg);
346 if (r != MAIL_NO_ERROR) {
347 res = r;
348 goto free_mmapstr;
349 }
350 }
351
352 snprintf(key_value, sizeof(key_value), "message-list");
353 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
354 mmapstr->str, mmapstr->len);
355 if (r < 0) {
356 res = MAIL_ERROR_FILE;
357 goto err;
358 }
359
360 mmap_string_free(mmapstr);
361
362 return MAIL_NO_ERROR;
363
364 free_mmapstr:
365 mmap_string_free(mmapstr);
366 err:
367 return res;
368}
369
370static int db_get_message_list(struct mail_cache_db * maildb,
371 carray ** p_msglist)
372{
373 carray * msglist;
374 void * serialized;
375 size_t serialized_len;
376 int r;
377 char key_value[PATH_MAX];
378 int res;
379 unsigned int i;
380
381 msglist = carray_new(16);
382 if (msglist == NULL) {
383 res = MAIL_ERROR_MEMORY;
384 goto err;
385 }
386
387 snprintf(key_value, sizeof(key_value), "message-list");
388 r = mail_cache_db_get(maildb, key_value, strlen(key_value),
389 &serialized, &serialized_len);
390 if (r >= 0) {
391 MMAPString * mmapstr;
392 size_t cur_token;
393
394 /* collect message list */
395
396 mmapstr = mmap_string_new_len(serialized, serialized_len);
397 if (mmapstr == NULL) {
398 res = MAIL_ERROR_MEMORY;
399 goto free_msglist;
400 }
401
402 cur_token = 0;
403 do {
404 uint32_t num;
405 uint32_t * msg;
406
407 r = mailimf_cache_int_read(mmapstr, &cur_token, &num);
408 if (r != MAIL_NO_ERROR)
409 break;
410
411 msg = malloc(sizeof(* msg));
412 if (msg == NULL) {
413 res = MAIL_ERROR_MEMORY;
414 mmap_string_free(mmapstr);
415 goto free_msglist;
416 }
417 * msg = num;
418
419 r = carray_add(msglist, msg, NULL);
420 if (r < 0) {
421 res = MAIL_ERROR_MEMORY;
422 free(msg);
423 mmap_string_free(mmapstr);
424 goto free_msglist;
425 }
426 } while (1);
427
428 mmap_string_free(mmapstr);
429 }
430
431 * p_msglist = msglist;
432
433 return MAIL_NO_ERROR;
434
435 free_msglist:
436 for(i = 0 ; i < carray_count(msglist) ; i ++) {
437 uint32_t * msg;
438
439 msg = carray_get(msglist, i);
440 free(msg);
441 }
442 carray_free(msglist);
443 err:
444 return res;
445}
446
447static int initialize(mailsession * session)
448{
449 struct db_session_state_data * data;
450
451 data = malloc(sizeof(* data));
452 if (data == NULL)
453 goto err;
454
455 data->db_filename[0] = '\0';
456
457 data->db_flags_store = mail_flags_store_new();
458 if (data->db_flags_store == NULL)
459 goto free;
460
461 session->sess_data = data;
462
463 return MAIL_NO_ERROR;
464
465 free:
466 free(data);
467 err:
468 return MAIL_ERROR_MEMORY;
469}
470
471static void uninitialize(mailsession * session)
472{
473 struct db_session_state_data * data;
474
475 data = get_data(session);
476
477 flags_store_process(session);
478
479 mail_flags_store_free(data->db_flags_store);
480
481 free(data);
482
483 session->sess_data = NULL;
484}
485
486static int connect_path(mailsession * session, char * path)
487{
488 struct db_session_state_data * data;
489
490 data = get_data(session);
491
492 strncpy(data->db_filename, path, sizeof(data->db_filename));
493
494 return MAIL_NO_ERROR;
495}
496
497static int logout(mailsession * session)
498{
499 return MAIL_NO_ERROR;
500}
501
502static int expunge_folder(mailsession * session)
503{
504 int r;
505 char key_value[PATH_MAX];
506 struct mail_cache_db * maildb;
507 carray * msglist;
508 unsigned int i;
509 struct db_session_state_data * data;
510 int res;
511 chash * msg_table;
512 MMAPString * mmapstr;
513
514 data = get_data(session);
515
516 flags_store_process(session);
517
518 r = mail_cache_db_open_lock(data->db_filename, &maildb);
519 if (r < 0) {
520 res = MAIL_ERROR_FILE;
521 goto err;
522 }
523
524 r = db_get_message_list(maildb, &msglist);
525 if (r != MAIL_NO_ERROR) {
526 res = r;
527 goto close_db;
528 }
529
530 msg_table = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
531 if (msg_table == NULL) {
532 res = MAIL_ERROR_MEMORY;
533 goto free_msglist;
534 }
535
536 mmapstr = mmap_string_new("");
537 if (mmapstr == NULL) {
538 res = MAIL_ERROR_MEMORY;
539 goto free_msgtable;
540 }
541
542 i = 0;
543 while (i < carray_count(msglist)) {
544 uint32_t num;
545 uint32_t * msg;
546 chashdatum key;
547 chashdatum value;
548 struct mail_flags * flags;
549 int deleted;
550
551 msg = carray_get(msglist, i);
552 num = * msg;
553
554 deleted = 0;
555 snprintf(key_value, sizeof(key_value), "%lu-flags",
556 (unsigned long) num);
557 r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags);
558 if (r == MAIL_NO_ERROR) {
559 if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0)
560 deleted = 1;
561 }
562
563 if (!deleted) {
564 snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num);
565 key.data = key_value;
566 key.len = strlen(key_value);
567 chash_set(msg_table, &key, &value, NULL);
568
569 snprintf(key_value, sizeof(key_value), "%lu-envelope",
570 (unsigned long) num);
571 key.data = key_value;
572 key.len = strlen(key_value);
573 chash_set(msg_table, &key, &value, NULL);
574
575 snprintf(key_value, sizeof(key_value), "%lu-flags",
576 (unsigned long) num);
577 key.data = key_value;
578 key.len = strlen(key_value);
579 chash_set(msg_table, &key, &value, NULL);
580
581 i ++;
582 }
583 else {
584 free(msg);
585 carray_delete(msglist, i);
586 }
587 }
588
589 mmap_string_free(mmapstr);
590
591 r = mail_cache_db_clean_up(maildb, msg_table);
592
593 chash_free(msg_table);
594
595 r = db_set_message_list(maildb, msglist);
596
597 for(i = 0 ; i < carray_count(msglist) ; i ++) {
598 uint32_t * msg;
599
600 msg = carray_get(msglist, i);
601 free(msg);
602 }
603 carray_free(msglist);
604
605 mail_cache_db_close_unlock(data->db_filename, maildb);
606
607 return MAIL_NO_ERROR;
608
609 free_msgtable:
610 chash_free(msg_table);
611 free_msglist:
612 for(i = 0 ; i < carray_count(msglist) ; i ++) {
613 uint32_t * msg;
614
615 msg = carray_get(msglist, i);
616 free(msg);
617 }
618 close_db:
619 mail_cache_db_close_unlock(data->db_filename, maildb);
620 err:
621 return res;
622}
623
624static int status_folder(mailsession * session, char * mb,
625 uint32_t * result_messages, uint32_t * result_recent,
626 uint32_t * result_unseen)
627{
628 struct mail_cache_db * maildb;
629 char key_value[PATH_MAX];
630 MMAPString * mmapstr;
631 uint32_t messages;
632 uint32_t recent;
633 uint32_t unseen;
634 struct db_session_state_data * data;
635 int r;
636 int res;
637 carray * msglist;
638 unsigned int i;
639
640 data = get_data(session);
641
642 flags_store_process(session);
643
644 r = mail_cache_db_open_lock(data->db_filename, &maildb);
645 if (r < 0) {
646 res = MAIL_ERROR_FILE;
647 goto err;
648 }
649
650 r = db_get_message_list(maildb, &msglist);
651 if (r != MAIL_NO_ERROR) {
652 res = r;
653 goto close_db;
654 }
655
656 mmapstr = mmap_string_new("");
657 if (mmapstr == NULL) {
658 res = MAIL_ERROR_MEMORY;
659 goto free_list;
660 }
661
662 messages = 0;
663 recent = 0;
664 unseen = 0;
665 for(i = 0 ; i < carray_count(msglist) ; i ++) {
666 uint32_t num;
667 uint32_t * msg;
668 int r;
669 struct mail_flags * flags;
670
671 msg = carray_get(msglist, i);
672 num = * msg;
673 free(msg);
674 carray_set(msglist, i, NULL);
675
676 messages ++;
677
678 snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num);
679
680 r = generic_cache_flags_read(maildb, mmapstr, key_value, &flags);
681 if (r == MAIL_NO_ERROR) {
682 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
683 recent ++;
684 }
685 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
686 unseen ++;
687 }
688 mail_flags_free(flags);
689 }
690 }
691
692 mmap_string_free(mmapstr);
693
694 carray_free(msglist);
695
696 mail_cache_db_close_unlock(data->db_filename, maildb);
697
698 * result_messages = messages;
699 * result_unseen = unseen;
700 * result_recent = recent;
701
702 return MAIL_NO_ERROR;
703
704 free_list:
705 for(i = 0 ; i < carray_count(msglist) ; i ++) {
706 uint32_t * msg;
707
708 msg = carray_get(msglist, i);
709 if (msg != NULL)
710 free(msg);
711 }
712 carray_free(msglist);
713 close_db:
714 mail_cache_db_close_unlock(data->db_filename, maildb);
715 err:
716 return res;
717}
718
719static int recent_number(mailsession * session, char * mb,
720 uint32_t * result)
721{
722 uint32_t dummy_messages;
723 uint32_t dummy_unseen;
724
725 return status_folder(session, mb,
726 &dummy_messages, result, &dummy_unseen);
727}
728
729static int unseen_number(mailsession * session, char * mb,
730 uint32_t * result)
731{
732 uint32_t dummy_messages;
733 uint32_t dummy_recent;
734
735 return status_folder(session, mb,
736 &dummy_messages, &dummy_recent, result);
737}
738
739static int messages_number(mailsession * session, char * mb,
740 uint32_t * result)
741{
742 uint32_t dummy_unseen;
743 uint32_t dummy_recent;
744
745 return status_folder(session, mb,
746 result, &dummy_recent, &dummy_unseen);
747}
748
749static int append_message(mailsession * session,
750 char * message, size_t size)
751{
752 return append_message_flags(session, message, size, NULL);
753}
754
755static int append_message_flags(mailsession * session,
756 char * message, size_t size, struct mail_flags * flags)
757{
758 carray * msglist;
759 unsigned int i;
760 uint32_t * msg;
761 uint32_t num;
762 char key_value[PATH_MAX];
763 MMAPString * mmapstr;
764 struct mail_cache_db * maildb;
765 struct db_session_state_data * data;
766 size_t cur_token;
767 struct mailimf_fields * fields;
768 int r;
769 int res;
770
771 data = get_data(session);
772
773 r = mail_cache_db_open_lock(data->db_filename, &maildb);
774 if (r < 0) {
775 res = MAIL_ERROR_FILE;
776 goto err;
777 }
778
779 r = db_get_next_msg_number(maildb, &num);
780 if (r != MAIL_NO_ERROR) {
781 res = r;
782 goto err;
783 }
784
785 r = db_get_message_list(maildb, &msglist);
786 if (r != MAIL_NO_ERROR) {
787 res = r;
788 goto close_db;
789 }
790
791 msg = malloc(sizeof(* msg));
792 if (msg == NULL) {
793 res = MAIL_ERROR_MEMORY;
794 goto free_msglist;
795 }
796
797 * msg = num;
798
799 r = carray_add(msglist, msg, NULL);
800 if (r < 0) {
801 res = MAIL_ERROR_MEMORY;
802 free(msg);
803 goto free_msglist;
804 }
805
806 r = db_set_message_list(maildb, msglist);
807 if (r != MAIL_NO_ERROR) {
808 res = r;
809 goto free_msglist;
810 }
811
812 /* free msglist */
813
814 for(i = 0 ; i < carray_count(msglist) ; i ++) {
815 uint32_t * msg;
816
817 msg = carray_get(msglist, i);
818 free(msg);
819 }
820 carray_free(msglist);
821
822 snprintf(key_value, sizeof(key_value), "%lu", (unsigned long) num);
823
824 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
825 message, size);
826 if (r < 0) {
827 res = MAIL_ERROR_FILE;
828 goto close_db;
829 }
830
831 /* write envelope */
832
833 cur_token = 0;
834 r = mailimf_envelope_fields_parse(message, size, &cur_token, &fields);
835 if (r != MAILIMF_NO_ERROR) {
836 res = MAIL_ERROR_PARSE;
837 goto close_db;
838 }
839
840 mmapstr = mmap_string_new("");
841 if (mmapstr == NULL) {
842 res = MAIL_ERROR_MEMORY;
843 goto close_db;
844 }
845
846 cur_token = 0;
847 r = mailimf_cache_fields_write(mmapstr, &cur_token, fields);
848 if (r != MAIL_NO_ERROR) {
849 res = r;
850 mmap_string_free(mmapstr);
851 goto close_db;
852 }
853
854 snprintf(key_value, sizeof(key_value), "%lu-envelope", (unsigned long) num);
855
856 r = mail_cache_db_put(maildb, key_value, strlen(key_value),
857 mmapstr->str, mmapstr->len);
858
859 mmap_string_free(mmapstr);
860
861 mailimf_fields_free(fields);
862
863 /* write flags */
864
865 if (flags != NULL) {
866 snprintf(key_value, sizeof(key_value), "%lu-flags", (unsigned long) num);
867
868 mmapstr = mmap_string_new("");
869 if (mmapstr == NULL) {
870 res = MAIL_ERROR_MEMORY;
871 goto close_db;
872 }
873
874 r = generic_cache_flags_write(maildb, mmapstr,
875 key_value, flags);
876
877 mmap_string_free(mmapstr);
878
879 if (r != MAIL_NO_ERROR) {
880 res = MAIL_ERROR_FILE;
881 goto close_db;
882 }
883 }
884
885 mail_cache_db_close_unlock(data->db_filename, maildb);
886
887 return MAIL_NO_ERROR;
888
889 free_msglist:
890 for(i = 0 ; i < carray_count(msglist) ; i ++) {
891 uint32_t * msg;
892
893 msg = carray_get(msglist, i);
894 free(msg);
895 }
896 carray_free(msglist);
897 close_db:
898 mail_cache_db_close_unlock(data->db_filename, maildb);
899 err:
900 return res;
901}
902
903static int get_messages_list(mailsession * session,
904 struct mailmessage_list ** result)
905{
906 int r;
907 char key[PATH_MAX];
908 struct mail_cache_db * maildb;
909 struct db_session_state_data * data;
910 int res;
911 carray * msglist;
912 unsigned int i;
913 carray * msgtab;
914 struct mailmessage_list * driver_msglist;
915
916 data = get_data(session);
917
918 r = mail_cache_db_open_lock(data->db_filename, &maildb);
919 if (r < 0) {
920 res = MAIL_ERROR_FILE;
921 goto err;
922 }
923
924 r = db_get_message_list(maildb, &msglist);
925 if (r != MAIL_NO_ERROR) {
926 res = r;
927 goto close_db;
928 }
929
930 msgtab = carray_new(16);
931 if (msgtab == NULL) {
932 res = MAIL_ERROR_MEMORY;
933 goto close_db;
934 }
935
936 for(i = 0 ; i < carray_count(msglist) ; i ++) {
937 uint32_t msg_num;
938 uint32_t * pmsg_num;
939 mailmessage * msg;
940 size_t size;
941
942 pmsg_num = carray_get(msglist, i);
943 msg_num = * pmsg_num;
944 free(pmsg_num);
945 carray_set(msglist, i, NULL);
946
947 snprintf(key, sizeof(key), "%lu", (unsigned long) msg_num);
948 r = mail_cache_db_get_size(maildb, key, strlen(key), &size);
949 if (r < 0) {
950 continue;
951 }
952
953 msg = mailmessage_new();
954 if (msg == NULL) {
955 res = MAIL_ERROR_MEMORY;
956 goto free_list;
957 }
958
959 r = mailmessage_init(msg, session, db_message_driver,
960 msg_num, size);
961 if (r != MAIL_NO_ERROR) {
962 mailmessage_free(msg);
963 res = r;
964 goto free_list;
965 }
966
967 r = carray_add(msgtab, msg, NULL);
968 if (r < 0) {
969 mailmessage_free(msg);
970 res = MAIL_ERROR_MEMORY;
971 goto free_list;
972 }
973 }
974 carray_free(msglist);
975
976 driver_msglist = mailmessage_list_new(msgtab);
977 if (driver_msglist == NULL) {
978 res = MAIL_ERROR_MEMORY;
979 goto free_list;
980 }
981
982 mail_cache_db_close_unlock(data->db_filename, maildb);
983
984 * result = driver_msglist;
985
986 return MAIL_NO_ERROR;
987
988 free_list:
989 for(i = 0 ; i < carray_count(msgtab) ; i ++) {
990 mailmessage * msg;
991
992 msg = carray_get(msgtab, i);
993 mailmessage_free(msg);
994 }
995 carray_free(msgtab);
996
997 for(i = 0 ; i < carray_count(msglist) ; i ++) {
998 uint32_t * msg;
999
1000 msg = carray_get(msglist, i);
1001 if (msg != NULL)
1002 free(msg);
1003 }
1004 carray_free(msglist);
1005 close_db:
1006 mail_cache_db_close_unlock(data->db_filename, maildb);
1007 err:
1008 return res;
1009}
1010
1011static int get_envelopes_list(mailsession * session,
1012 struct mailmessage_list * env_list)
1013{
1014 unsigned int i;
1015 char key[PATH_MAX];
1016 int r;
1017 struct mail_cache_db * maildb;
1018 int res;
1019 struct db_session_state_data * data;
1020 MMAPString * mmapstr;
1021
1022 data = get_data(session);
1023
1024 flags_store_process(session);
1025
1026 r = mail_cache_db_open_lock(data->db_filename, &maildb);
1027 if (r < 0) {
1028 res = MAIL_ERROR_FILE;
1029 goto err;
1030 }
1031
1032 mmapstr = mmap_string_new("");
1033 if (mmapstr == NULL) {
1034 res = MAIL_ERROR_MEMORY;
1035 goto close_db;
1036 }
1037
1038 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1039 mailmessage * msg;
1040
1041 msg = carray_get(env_list->msg_tab, i);
1042 if (msg->msg_fields == NULL) {
1043 snprintf(key, sizeof(key), "%lu-envelope",
1044 (unsigned long) msg->msg_index);
1045
1046 r = generic_cache_fields_read(maildb, mmapstr,
1047 key, &msg->msg_fields);
1048 }
1049
1050 if (msg->msg_flags == NULL) {
1051 snprintf(key, sizeof(key), "%lu-flags",
1052 (unsigned long) msg->msg_index);
1053
1054 r = generic_cache_flags_read(maildb, mmapstr,
1055 key, &msg->msg_flags);
1056 }
1057 }
1058
1059 mmap_string_free(mmapstr);
1060
1061 mail_cache_db_close_unlock(data->db_filename, maildb);
1062
1063 return MAIL_NO_ERROR;
1064
1065 close_db:
1066 mail_cache_db_close_unlock(data->db_filename, maildb);
1067 err:
1068 return res;
1069}
1070
1071static int check_folder(mailsession * session)
1072{
1073 flags_store_process(session);
1074
1075 return MAIL_NO_ERROR;
1076}
1077
1078static int get_message(mailsession * session,
1079 uint32_t num, mailmessage ** result)
1080{
1081 mailmessage * msg;
1082 int r;
1083 size_t size;
1084 char key[PATH_MAX];
1085 struct db_session_state_data * data;
1086 struct mail_cache_db * maildb;
1087 int res;
1088
1089 data = get_data(session);
1090
1091 r = mail_cache_db_open_lock(data->db_filename, &maildb);
1092 if (r < 0) {
1093 res = MAIL_ERROR_FILE;
1094 goto err;
1095 }
1096
1097 msg = mailmessage_new();
1098 if (msg == NULL) {
1099 res = MAIL_ERROR_MEMORY;
1100 goto close_db;
1101 }
1102
1103 size = 0;
1104 snprintf(key, sizeof(key), "%lu", (unsigned long) num);
1105 r = mail_cache_db_get_size(maildb, key, strlen(key), &size);
1106 /* ignore error */
1107
1108 r = mailmessage_init(msg, session, db_message_driver,
1109 num, size);
1110 if (r != MAIL_NO_ERROR) {
1111 mailmessage_free(msg);
1112 res = r;
1113 goto close_db;
1114 }
1115
1116 mail_cache_db_close_unlock(data->db_filename, maildb);
1117
1118 return MAIL_NO_ERROR;
1119
1120 close_db:
1121 mail_cache_db_close_unlock(data->db_filename, maildb);
1122 err:
1123 return res;
1124}
1125
1126static int get_message_by_uid(mailsession * session,
1127 const char * uid, mailmessage ** result)
1128{
1129 uint32_t msg_num;
1130
1131 msg_num = strtoul(uid, NULL, 10);
1132
1133 return get_message(session, msg_num, result);
1134}