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