summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/generic/imapdriver_cached.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/generic/imapdriver_cached.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/generic/imapdriver_cached.c1274
1 files changed, 1274 insertions, 0 deletions
diff --git a/kmicromail/libetpan/generic/imapdriver_cached.c b/kmicromail/libetpan/generic/imapdriver_cached.c
new file mode 100644
index 0000000..e6af8e8
--- a/dev/null
+++ b/kmicromail/libetpan/generic/imapdriver_cached.c
@@ -0,0 +1,1274 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2002 - 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 REGENTS 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 REGENTS 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 "imapdriver_cached.h"
37
38#include "libetpan-config.h"
39
40#include <stdio.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include <string.h>
45#include <unistd.h>
46#include <stdlib.h>
47
48#include "mail.h"
49#include "imapdriver_tools.h"
50#include "mail_cache_db.h"
51#include "mailmessage.h"
52#include "imapdriver_cached_message.h"
53#include "maildriver.h"
54#include "imapdriver_types.h"
55#include "generic_cache.h"
56#include "imfcache.h"
57#include "maildriver_tools.h"
58#include "imapdriver.h"
59
60static int imapdriver_cached_initialize(mailsession * session);
61static void imapdriver_cached_uninitialize(mailsession * session);
62
63static int imapdriver_cached_parameters(mailsession * session,
64 int id, void * value);
65
66static int imapdriver_cached_connect_stream(mailsession * session,
67 mailstream * s);
68
69static int imapdriver_cached_starttls(mailsession * session);
70
71static int imapdriver_cached_login(mailsession * session,
72 char * userid, char * password);
73static int imapdriver_cached_logout(mailsession * session);
74static int imapdriver_cached_noop(mailsession * session);
75static int imapdriver_cached_build_folder_name(mailsession * session,
76 char * mb,
77 char * name, char ** result);
78static int imapdriver_cached_create_folder(mailsession * session, char * mb);
79static int imapdriver_cached_delete_folder(mailsession * session, char * mb);
80static int imapdriver_cached_rename_folder(mailsession * session, char * mb,
81 char * new_name);
82static int imapdriver_cached_check_folder(mailsession * session);
83static int imapdriver_cached_examine_folder(mailsession * session,
84 char * mb);
85static int imapdriver_cached_select_folder(mailsession * session, char * mb);
86static int imapdriver_cached_expunge_folder(mailsession * session);
87static int imapdriver_cached_status_folder(mailsession * session, char * mb,
88 uint32_t * result_messages,
89 uint32_t * result_recent,
90 uint32_t * result_unseen);
91static int imapdriver_cached_messages_number(mailsession * session,
92 char * mb,
93 uint32_t * result);
94static int imapdriver_cached_recent_number(mailsession * session, char * mb,
95 uint32_t * result);
96static int imapdriver_cached_unseen_number(mailsession * session, char * mb,
97 uint32_t * result);
98static int imapdriver_cached_list_folders(mailsession * session, char * mb,
99 struct mail_list ** result);
100static int imapdriver_cached_lsub_folders(mailsession * session, char * mb,
101 struct mail_list ** result);
102static int imapdriver_cached_subscribe_folder(mailsession * session,
103 char * mb);
104static int imapdriver_cached_unsubscribe_folder(mailsession * session,
105 char * mb);
106static int imapdriver_cached_append_message(mailsession * session,
107 char * message, size_t size);
108static int imapdriver_cached_copy_message(mailsession * session,
109 uint32_t num, char * mb);
110
111static int imapdriver_cached_get_messages_list(mailsession * session,
112 struct mailmessage_list **
113 result);
114static int
115imapdriver_cached_get_envelopes_list(mailsession * session,
116 struct mailmessage_list * env_list);
117static int imapdriver_cached_remove_message(mailsession * session,
118 uint32_t num);
119
120#if 0
121static int imapdriver_cached_search_messages(mailsession * session,
122 char * charset,
123 struct mail_search_key * key,
124 struct mail_search_result **
125 result);
126#endif
127
128static int imapdriver_cached_get_message(mailsession * session,
129 uint32_t num, mailmessage ** result);
130
131static int imapdriver_cached_get_message_by_uid(mailsession * session,
132 const char * uid,
133 mailmessage ** result);
134
135static mailsession_driver local_imap_cached_session_driver = {
136 .sess_name = "imap-cached",
137
138 .sess_initialize = imapdriver_cached_initialize,
139 .sess_uninitialize = imapdriver_cached_uninitialize,
140
141 .sess_parameters = imapdriver_cached_parameters,
142
143 .sess_connect_stream = imapdriver_cached_connect_stream,
144 .sess_connect_path = NULL,
145 .sess_starttls = imapdriver_cached_starttls,
146 .sess_login = imapdriver_cached_login,
147 .sess_logout = imapdriver_cached_logout,
148 .sess_noop = imapdriver_cached_noop,
149
150 .sess_build_folder_name = imapdriver_cached_build_folder_name,
151 .sess_create_folder = imapdriver_cached_create_folder,
152 .sess_delete_folder = imapdriver_cached_delete_folder,
153 .sess_rename_folder = imapdriver_cached_rename_folder,
154 .sess_check_folder = imapdriver_cached_check_folder,
155 .sess_examine_folder = imapdriver_cached_examine_folder,
156 .sess_select_folder = imapdriver_cached_select_folder,
157 .sess_expunge_folder = imapdriver_cached_expunge_folder,
158 .sess_status_folder = imapdriver_cached_status_folder,
159 .sess_messages_number = imapdriver_cached_messages_number,
160 .sess_recent_number = imapdriver_cached_recent_number,
161 .sess_unseen_number = imapdriver_cached_unseen_number,
162 .sess_list_folders = imapdriver_cached_list_folders,
163 .sess_lsub_folders = imapdriver_cached_lsub_folders,
164 .sess_subscribe_folder = imapdriver_cached_subscribe_folder,
165 .sess_unsubscribe_folder = imapdriver_cached_unsubscribe_folder,
166
167 .sess_append_message = imapdriver_cached_append_message,
168 .sess_copy_message = imapdriver_cached_copy_message,
169 .sess_move_message = NULL,
170
171 .sess_get_messages_list = imapdriver_cached_get_messages_list,
172 .sess_get_envelopes_list = imapdriver_cached_get_envelopes_list,
173 .sess_remove_message = imapdriver_cached_remove_message,
174#if 0
175 .sess_search_messages = imapdriver_cached_search_messages,
176#endif
177
178 .sess_get_message = imapdriver_cached_get_message,
179 .sess_get_message_by_uid = imapdriver_cached_get_message_by_uid,
180};
181
182mailsession_driver * imap_cached_session_driver =
183&local_imap_cached_session_driver;
184
185#define CACHE_MESSAGE_LIST
186
187static inline struct imap_cached_session_state_data *
188get_cached_data(mailsession * session)
189{
190 return session->sess_data;
191}
192
193static inline mailsession * get_ancestor(mailsession * s)
194{
195 return get_cached_data(s)->imap_ancestor;
196}
197
198static inline
199struct imap_session_state_data * get_ancestor_data(mailsession * s)
200{
201 return get_ancestor(s)->sess_data;
202}
203
204static inline mailimap * get_imap_session(mailsession * session)
205{
206 return get_ancestor_data(session)->imap_session;
207}
208
209static int imapdriver_cached_initialize(mailsession * session)
210{
211 struct imap_cached_session_state_data * data;
212
213 data = malloc(sizeof(* data));
214 if (data == NULL)
215 goto err;
216
217 data->imap_ancestor = mailsession_new(imap_session_driver);
218 if (data->imap_ancestor == NULL)
219 goto free_data;
220 data->imap_quoted_mb = NULL;
221 data->imap_cache_directory[0] = '\0';
222 data->imap_uid_list = carray_new(128);
223 if (data->imap_uid_list == NULL)
224 goto free_session;
225
226 session->sess_data = data;
227
228 return MAIL_NO_ERROR;
229
230 free_session:
231 mailsession_free(data->imap_ancestor);
232 free_data:
233 free(data);
234 err:
235 return MAIL_ERROR_MEMORY;
236}
237
238static void
239free_quoted_mb(struct imap_cached_session_state_data * imap_cached_data)
240{
241 if (imap_cached_data->imap_quoted_mb != NULL) {
242 free(imap_cached_data->imap_quoted_mb);
243 imap_cached_data->imap_quoted_mb = NULL;
244 }
245}
246
247struct uid_cache_item {
248 uint32_t uid;
249 uint32_t size;
250};
251
252static int update_uid_cache(mailsession * session,
253 struct mailmessage_list * env_list)
254{
255 unsigned int i;
256 int r;
257 struct imap_cached_session_state_data * data;
258 int res;
259
260 data = get_cached_data(session);
261
262 /* free all UID cache */
263 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
264 struct uid_cache_item * cache_item;
265
266 cache_item = carray_get(data->imap_uid_list, i);
267 free(cache_item);
268 }
269
270 /* build UID cache */
271 r = carray_set_size(data->imap_uid_list,
272 carray_count(env_list->msg_tab));
273 if (r < 0) {
274 res = MAIL_ERROR_MEMORY;
275 goto err;
276 }
277
278 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
279 struct uid_cache_item * cache_item;
280 mailmessage * msg;
281
282 cache_item = malloc(sizeof(* cache_item));
283 if (cache_item == NULL) {
284 res = MAIL_ERROR_MEMORY;
285 goto err;
286 }
287 msg = carray_get(env_list->msg_tab, i);
288 cache_item->uid = msg->msg_index;
289 cache_item->size = msg->msg_size;
290
291 carray_set(data->imap_uid_list, i, cache_item);
292 }
293
294 return MAIL_NO_ERROR;
295
296 err:
297 return res;
298}
299
300static void check_for_uid_cache(mailsession * session)
301{
302#if 0
303 mailsession * imap;
304#endif
305 mailimap * imap;
306#if 0
307 struct imap_session_state_data * imap_data;
308#endif
309 clist * list;
310 clistiter * cur;
311 struct imap_cached_session_state_data * data;
312 unsigned int i;
313 unsigned dest;
314
315 data = get_cached_data(session);
316#if 0
317 imap = get_ancestor(session);
318
319 imap_data = imap->data;
320#endif
321
322 imap = get_imap_session(session);
323
324 if (imap->imap_response_info == NULL)
325 return;
326
327 list = imap->imap_response_info->rsp_expunged;
328 if (list == NULL)
329 return;
330
331 dest = 0;
332 i = 0;
333 /* remove expunged */
334 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
335 uint32_t expunged;
336
337 expunged = * (uint32_t *) clist_content(cur);
338
339 while (i < carray_count(data->imap_uid_list)) {
340 struct uid_cache_item * cache_item;
341
342 if (dest + 1 == expunged) {
343 cache_item = carray_get(data->imap_uid_list, i);
344 free(cache_item);
345 i ++;
346 break;
347 }
348 else {
349 cache_item = carray_get(data->imap_uid_list, i);
350 carray_set(data->imap_uid_list, dest, cache_item);
351 i ++;
352 dest ++;
353 }
354 }
355 }
356 /* complete list */
357 while (i < carray_count(data->imap_uid_list)) {
358 struct uid_cache_item * cache_item;
359
360 cache_item = carray_get(data->imap_uid_list, i);
361 carray_set(data->imap_uid_list, dest, cache_item);
362 i ++;
363 dest ++;
364 }
365 carray_set_size(data->imap_uid_list, dest);
366}
367
368static void imapdriver_cached_uninitialize(mailsession * session)
369{
370 struct imap_cached_session_state_data * data;
371 unsigned int i;
372
373 data = get_cached_data(session);
374
375 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
376 struct uid_cache_item * cache_item;
377
378 cache_item = carray_get(data->imap_uid_list, i);
379 free(cache_item);
380 }
381 carray_free(data->imap_uid_list);
382 free_quoted_mb(data);
383 mailsession_free(data->imap_ancestor);
384 free(data);
385
386 session->sess_data = NULL;
387}
388
389
390static int imapdriver_cached_parameters(mailsession * session,
391 int id, void * value)
392{
393 struct imap_cached_session_state_data * data;
394 int r;
395
396 data = get_cached_data(session);
397
398 switch (id) {
399 case IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY:
400 strncpy(data->imap_cache_directory, value, PATH_MAX);
401 data->imap_cache_directory[PATH_MAX - 1] = '\0';
402
403 r = generic_cache_create_dir(data->imap_cache_directory);
404 if (r != MAIL_NO_ERROR)
405 return r;
406
407 return MAIL_NO_ERROR;
408 }
409
410 return MAIL_ERROR_INVAL;
411}
412
413
414static int imapdriver_cached_connect_stream(mailsession * session,
415 mailstream * s)
416{
417 int r;
418
419 check_for_uid_cache(session);
420
421 r = mailsession_connect_stream(get_ancestor(session), s);
422
423 check_for_uid_cache(session);
424
425 return r;
426}
427
428static int imapdriver_cached_starttls(mailsession * session)
429{
430 int r;
431
432 r = mailsession_starttls(get_ancestor(session));
433
434 check_for_uid_cache(session);
435
436 return r;
437}
438
439static int imapdriver_cached_login(mailsession * session,
440 char * userid, char * password)
441{
442 int r;
443
444 r = mailsession_login(get_ancestor(session), userid, password);
445
446 check_for_uid_cache(session);
447
448 return r;
449}
450
451static int imapdriver_cached_logout(mailsession * session)
452{
453 int r;
454
455 r = mailsession_logout(get_ancestor(session));
456
457 check_for_uid_cache(session);
458
459 if (r == MAIL_NO_ERROR) {
460 struct imap_cached_session_state_data * imap_cached_data;
461
462 imap_cached_data = get_cached_data(session);
463
464 free_quoted_mb(imap_cached_data);
465 }
466
467 return r;
468}
469
470static int imapdriver_cached_noop(mailsession * session)
471{
472 int r;
473
474 r = mailsession_noop(get_ancestor(session));
475
476 check_for_uid_cache(session);
477
478 return r;
479}
480
481static int imapdriver_cached_build_folder_name(mailsession * session,
482 char * mb,
483 char * name, char ** result)
484{
485 int r;
486
487 r = mailsession_build_folder_name(get_ancestor(session), mb,
488 name, result);
489
490 check_for_uid_cache(session);
491
492 return r;
493}
494
495static int imapdriver_cached_create_folder(mailsession * session, char * mb)
496{
497 int r;
498
499 r = mailsession_create_folder(get_ancestor(session), mb);
500
501 check_for_uid_cache(session);
502
503 return r;
504}
505
506static int imapdriver_cached_delete_folder(mailsession * session, char * mb)
507{
508 int r;
509
510 r = mailsession_delete_folder(get_ancestor(session), mb);
511
512 check_for_uid_cache(session);
513
514 return r;
515}
516
517static int imapdriver_cached_rename_folder(mailsession * session, char * mb,
518 char * new_name)
519{
520 int r;
521
522 r = mailsession_rename_folder(get_ancestor(session), mb, new_name);
523
524 check_for_uid_cache(session);
525
526 return r;
527}
528
529static int imapdriver_cached_check_folder(mailsession * session)
530{
531 int r;
532
533 r = mailsession_check_folder(get_ancestor(session));
534
535 check_for_uid_cache(session);
536
537 return r;
538}
539
540static int imapdriver_cached_examine_folder(mailsession * session,
541 char * mb)
542{
543 int r;
544
545 r = mailsession_examine_folder(get_ancestor(session), mb);
546
547 check_for_uid_cache(session);
548
549 return r;
550}
551
552static int get_cache_folder(mailsession * session, char ** result)
553{
554#if 0
555 mailsession * imap_session;
556#endif
557 mailimap * imap;
558 char * mb;
559 char * cache_dir;
560 char * dirname;
561 char * quoted_mb;
562 int res;
563 int r;
564 char key[PATH_MAX];
565#if 0
566 struct imap_session_state_data * imap_data;
567 struct imap_cached_session_state_data * cached_data;
568#endif
569
570#if 0
571 imap_session = get_ancestor(session);
572 imap_data = imap_session->data;
573 imap = imap_data->session;
574#endif
575 imap = get_imap_session(session);
576
577 mb = get_ancestor_data(session)->imap_mailbox;
578
579 cache_dir = get_cached_data(session)->imap_cache_directory;
580
581 if (imap->imap_state != MAILIMAP_STATE_SELECTED)
582 return MAIL_ERROR_BAD_STATE;
583
584 if (imap->imap_selection_info == NULL)
585 return MAIL_ERROR_BAD_STATE;
586
587 quoted_mb = maildriver_quote_mailbox(mb);
588 if (quoted_mb == NULL) {
589 res = MAIL_ERROR_MEMORY;
590 goto err;
591 }
592
593 snprintf(key, PATH_MAX, "%s/%s", cache_dir, quoted_mb);
594
595 dirname = strdup(key);
596 if (dirname == NULL) {
597 res = MAIL_ERROR_MEMORY;
598 goto free_mb;
599 }
600
601 r = generic_cache_create_dir(dirname);
602 if (r != MAIL_NO_ERROR) {
603 res = r;
604 goto free_dirname;
605 }
606
607 free(quoted_mb);
608
609 * result = dirname;
610
611 return MAIL_NO_ERROR;
612
613 free_dirname:
614 free(dirname);
615 free_mb:
616 free(quoted_mb);
617 err:
618 return res;
619}
620
621static int imapdriver_cached_select_folder(mailsession * session, char * mb)
622{
623 int r;
624 char * quoted_mb;
625 struct imap_cached_session_state_data * data;
626 mailsession * imap;
627 char * old_mb;
628
629 imap = get_ancestor(session);
630
631 old_mb = get_ancestor_data(session)->imap_mailbox;
632 if (old_mb != NULL)
633 if (strcmp(mb, old_mb) == 0)
634 return MAIL_NO_ERROR;
635
636 r = mailsession_select_folder(get_ancestor(session), mb);
637 if (r != MAIL_NO_ERROR)
638 return r;
639
640 check_for_uid_cache(session);
641
642 r = get_cache_folder(session, &quoted_mb);
643 if (r != MAIL_NO_ERROR)
644 return r;
645
646 data = get_cached_data(session);
647 if (data->imap_quoted_mb != NULL)
648 free(data->imap_quoted_mb);
649 data->imap_quoted_mb = quoted_mb;
650
651 /* clear UID cache */
652 carray_set_size(data->imap_uid_list, 0);
653
654 return MAIL_NO_ERROR;
655}
656
657static int imapdriver_cached_expunge_folder(mailsession * session)
658{
659 int r;
660
661 r = mailsession_expunge_folder(get_ancestor(session));
662
663 check_for_uid_cache(session);
664
665 return r;
666}
667
668static int imapdriver_cached_status_folder(mailsession * session, char * mb,
669 uint32_t * result_messages, uint32_t * result_recent,
670 uint32_t * result_unseen)
671{
672 int r;
673
674 r = mailsession_status_folder(get_ancestor(session), mb, result_messages,
675 result_recent, result_unseen);
676
677 check_for_uid_cache(session);
678
679 return r;
680}
681
682static int imapdriver_cached_messages_number(mailsession * session,
683 char * mb,
684 uint32_t * result)
685{
686 int r;
687
688 r = mailsession_messages_number(get_ancestor(session), mb, result);
689
690 check_for_uid_cache(session);
691
692 return r;
693}
694
695static int imapdriver_cached_recent_number(mailsession * session, char * mb,
696 uint32_t * result)
697{
698 int r;
699
700 r = mailsession_recent_number(get_ancestor(session), mb, result);
701
702 check_for_uid_cache(session);
703
704 return r;
705}
706
707static int imapdriver_cached_unseen_number(mailsession * session, char * mb,
708 uint32_t * result)
709{
710 int r;
711
712 r = mailsession_unseen_number(get_ancestor(session), mb, result);
713
714 check_for_uid_cache(session);
715
716 return r;
717}
718
719static int imapdriver_cached_list_folders(mailsession * session, char * mb,
720 struct mail_list ** result)
721{
722 int r;
723
724 r = mailsession_list_folders(get_ancestor(session), mb, result);
725
726 check_for_uid_cache(session);
727
728 return r;
729}
730
731static int imapdriver_cached_lsub_folders(mailsession * session, char * mb,
732 struct mail_list ** result)
733{
734 int r;
735
736 r = mailsession_lsub_folders(get_ancestor(session), mb, result);
737
738 check_for_uid_cache(session);
739
740 return r;
741}
742
743static int imapdriver_cached_subscribe_folder(mailsession * session,
744 char * mb)
745{
746 int r;
747
748 r = mailsession_subscribe_folder(get_ancestor(session), mb);
749
750 check_for_uid_cache(session);
751
752 return r;
753}
754
755static int imapdriver_cached_unsubscribe_folder(mailsession * session,
756 char * mb)
757{
758 int r;
759
760 r = mailsession_unsubscribe_folder(get_ancestor(session), mb);
761
762 check_for_uid_cache(session);
763
764 return r;
765}
766
767static int imapdriver_cached_append_message(mailsession * session,
768 char * message, size_t size)
769{
770 int r;
771
772 r = mailsession_append_message(get_ancestor(session), message, size);
773
774 check_for_uid_cache(session);
775
776 return r;
777}
778
779static int imapdriver_cached_copy_message(mailsession * session,
780 uint32_t num, char * mb)
781{
782 int r;
783
784 r = mailsession_copy_message(get_ancestor(session), num, mb);
785
786 check_for_uid_cache(session);
787
788 return r;
789}
790
791static int cmp_uid(uint32_t ** pa, uint32_t ** pb)
792{
793 uint32_t * a;
794 uint32_t * b;
795
796 a = * pa;
797 b = * pb;
798
799 return * a - * b;
800}
801
802
803static int imapdriver_cached_get_messages_list(mailsession * session,
804 struct mailmessage_list **
805 result)
806{
807#if 0
808 mailsession * imap_session;
809#endif
810 mailimap * imap;
811 uint32_t uid_max;
812 struct imap_cached_session_state_data * data;
813 struct mailmessage_list * env_list;
814 unsigned i;
815 int r;
816 int res;
817 carray * tab;
818
819#if 0
820 data = session->data;
821 imap_session = get_ancestor(session);
822 imap = ((struct imap_session_state_data *) (imap_session->data))->session;
823#endif
824 data = get_cached_data(session);
825 imap = get_imap_session(session);
826
827 uid_max = 0;
828
829#ifdef CACHE_MESSAGE_LIST
830 /* get UID max */
831 uid_max = 0;
832 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
833 struct uid_cache_item * cache_item;
834
835 cache_item = carray_get(data->imap_uid_list, i);
836 if (cache_item->uid > uid_max)
837 uid_max = cache_item->uid;
838 }
839#endif
840
841 r = imap_get_messages_list(imap, session, imap_cached_message_driver,
842 uid_max + 1, &env_list);
843
844 check_for_uid_cache(session);
845
846 if (r != MAIL_NO_ERROR) {
847 res = r;
848 goto err;
849 }
850
851#ifdef CACHE_MESSAGE_LIST
852 /* remove unsollicited message */
853 i = 0;
854 while (i < carray_count(env_list->msg_tab)) {
855 mailmessage * msg;
856
857 msg = carray_get(env_list->msg_tab, i);
858 if (msg->msg_index < uid_max + 1)
859 carray_delete(env_list->msg_tab, i);
860 else
861 i ++;
862 }
863
864 tab = carray_new(carray_count(env_list->msg_tab) +
865 carray_count(data->imap_uid_list));
866 if (tab == NULL) {
867 res = MAIL_ERROR_MEMORY;
868 goto free;
869 }
870 carray_set_size(tab,
871 carray_count(env_list->msg_tab) + carray_count(data->imap_uid_list));
872
873 /* sort cached data before adding them to the list */
874 qsort(carray_data(data->imap_uid_list), carray_count(data->imap_uid_list),
875 sizeof(* carray_data(data->imap_uid_list)),
876 (int (*)(const void *, const void *)) cmp_uid);
877
878 /* adds cached UID */
879 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
880 struct uid_cache_item * cache_item;
881 mailmessage * msg;
882
883 cache_item = carray_get(data->imap_uid_list, i);
884
885 msg = mailmessage_new();
886 if (msg == NULL) {
887 res = MAIL_ERROR_MEMORY;
888 goto free;
889 }
890
891 r = mailmessage_init(msg, session, imap_cached_message_driver,
892 cache_item->uid, cache_item->size);
893 if (r != MAIL_NO_ERROR) {
894 mailmessage_free(msg);
895 res = r;
896 goto free;
897 }
898
899 carray_set(tab, i, msg);
900 }
901
902 /* adds new elements */
903 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
904 mailmessage * msg;
905
906 msg = carray_get(env_list->msg_tab, i);
907 carray_set(tab, carray_count(data->imap_uid_list) + i, msg);
908 }
909
910 /* replace list of messages in env_list */
911 carray_free(env_list->msg_tab);
912 env_list->msg_tab = tab;
913
914 r = update_uid_cache(session, env_list);
915 if (r != MAIL_NO_ERROR) {
916 res = r;
917 goto free;
918 }
919#endif
920
921 * result = env_list;
922
923 return MAIL_NO_ERROR;
924
925 free:
926 mailmessage_list_free(env_list);
927 err:
928 return res;
929}
930
931static int get_flags_list(mailsession * session,
932 struct mailmessage_list * env_list)
933{
934 struct mailimap_set * set;
935 struct mailimap_fetch_att * fetch_att;
936 struct mailimap_fetch_type * fetch_type;
937 int res;
938 clist * fetch_result;
939 int r;
940 clist * msg_list;
941#if 0
942 struct imap_session_state_data * data;
943#endif
944 unsigned i;
945 unsigned dest;
946
947#if 0
948 data = session->data;
949#endif
950
951 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
952 if (fetch_type == NULL) {
953 res = MAIL_ERROR_MEMORY;
954 goto err;
955 }
956
957 fetch_att = mailimap_fetch_att_new_uid();
958 if (fetch_att == NULL) {
959 res = MAIL_ERROR_MEMORY;
960 goto free_fetch_type;
961 }
962
963 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
964 if (r != MAILIMAP_NO_ERROR) {
965 mailimap_fetch_att_free(fetch_att);
966 res = MAIL_ERROR_MEMORY;
967 goto free_fetch_type;
968 }
969
970 fetch_att = mailimap_fetch_att_new_flags();
971 if (fetch_att == NULL) {
972 res = MAIL_ERROR_MEMORY;
973 goto free_fetch_type;
974 }
975
976 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
977 if (r != MAILIMAP_NO_ERROR) {
978 mailimap_fetch_att_free(fetch_att);
979 res = MAIL_ERROR_MEMORY;
980 goto free_fetch_type;
981 }
982
983 r = maildriver_env_list_to_msg_list_no_flags(env_list, &msg_list);
984 if (r != MAIL_NO_ERROR) {
985 res = MAIL_ERROR_MEMORY;
986 goto free_fetch_type;
987 }
988
989 if (clist_begin(msg_list) == NULL) {
990 /* no need to fetch envelopes */
991
992 clist_free(msg_list);
993 mailimap_fetch_type_free(fetch_type);
994 return MAIL_NO_ERROR;
995 }
996
997 r = msg_list_to_imap_set(msg_list, &set);
998 if (r != MAIL_NO_ERROR) {
999 clist_foreach(msg_list, (clist_func) free, NULL);
1000 clist_free(msg_list);
1001 res = MAIL_ERROR_MEMORY;
1002 goto free_fetch_type;
1003 }
1004 clist_foreach(msg_list, (clist_func) free, NULL);
1005 clist_free(msg_list);
1006
1007 r = mailimap_uid_fetch(get_imap_session(session), set,
1008 fetch_type, &fetch_result);
1009
1010 mailimap_fetch_type_free(fetch_type);
1011 mailimap_set_free(set);
1012
1013 switch (r) {
1014 case MAILIMAP_NO_ERROR:
1015 break;
1016 default:
1017 return imap_error_to_mail_error(r);
1018 }
1019
1020 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
1021 mailimap_fetch_list_free(fetch_result);
1022
1023 if (r != MAIL_NO_ERROR) {
1024 res = MAIL_ERROR_MEMORY;
1025 goto err;
1026 }
1027
1028 /* remove messages that don't have flags */
1029 i = 0;
1030 dest = 0;
1031 while (i < carray_count(env_list->msg_tab)) {
1032 mailmessage * msg;
1033
1034 msg = carray_get(env_list->msg_tab, i);
1035 if (msg->msg_flags != NULL) {
1036 carray_set(env_list->msg_tab, dest, msg);
1037 dest ++;
1038 }
1039 else {
1040 mailmessage_free(msg);
1041 }
1042 i ++;
1043 }
1044 carray_set_size(env_list->msg_tab, dest);
1045
1046 return MAIL_NO_ERROR;
1047
1048 free_fetch_type:
1049 mailimap_fetch_type_free(fetch_type);
1050 err:
1051 return res;
1052}
1053
1054
1055#define ENV_NAME "env.db"
1056
1057static void get_uid_from_filename(char * filename)
1058{
1059 char * p;
1060
1061 p = strstr(filename, "-part");
1062 if (p != NULL)
1063 * p = 0;
1064 p = strstr(filename, "-envelope");
1065 if (p != NULL)
1066 * p = 0;
1067 p = strstr(filename, "-rfc822");
1068 if (p != NULL)
1069 * p = 0;
1070}
1071
1072static int
1073imapdriver_cached_get_envelopes_list(mailsession * session,
1074 struct mailmessage_list * env_list)
1075{
1076 int r;
1077 int res;
1078 uint32_t i;
1079 struct imap_cached_session_state_data * data;
1080 MMAPString * mmapstr;
1081 struct mail_cache_db * cache_db;
1082 char filename[PATH_MAX];
1083
1084 data = get_cached_data(session);
1085 if (data->imap_quoted_mb == NULL) {
1086 res = MAIL_ERROR_BAD_STATE;
1087 goto err;
1088 }
1089
1090 mmapstr = mmap_string_new("");
1091 if (mmapstr == NULL) {
1092 res = MAIL_ERROR_MEMORY;
1093 goto err;
1094 }
1095
1096 snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME);
1097
1098 r = mail_cache_db_open_lock(filename, &cache_db);
1099 if (r < 0) {
1100 res = MAIL_ERROR_MEMORY;
1101 goto free_mmapstr;
1102 }
1103
1104 /* fill with cached */
1105
1106 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1107 mailmessage * msg;
1108 struct mailimf_fields * fields;
1109
1110 msg = carray_get(env_list->msg_tab, i);
1111
1112 if (msg->msg_fields == NULL) {
1113 r = imapdriver_get_cached_envelope(cache_db, mmapstr,
1114 session, msg, &fields);
1115 if (r == MAIL_NO_ERROR) {
1116 msg->msg_cached = TRUE;
1117 msg->msg_fields = fields;
1118 }
1119 }
1120 }
1121
1122 mail_cache_db_close_unlock(filename, cache_db);
1123
1124 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
1125
1126 check_for_uid_cache(session);
1127
1128 if (r != MAIL_NO_ERROR) {
1129 res = r;
1130 goto free_mmapstr;
1131 }
1132
1133 r = get_flags_list(session, env_list);
1134
1135 if (r != MAIL_NO_ERROR) {
1136 res = r;
1137 goto free_mmapstr;
1138 }
1139
1140#ifdef CACHE_MESSAGE_LIST
1141 r = update_uid_cache(session, env_list);
1142 if (r != MAIL_NO_ERROR) {
1143 res = r;
1144 goto free_mmapstr;
1145 }
1146#endif
1147
1148 /* must write cache */
1149
1150 r = mail_cache_db_open_lock(filename, &cache_db);
1151 if (r < 0) {
1152 res = MAIL_ERROR_MEMORY;
1153 goto free_mmapstr;
1154 }
1155
1156 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1157 mailmessage * msg;
1158
1159 msg = carray_get(env_list->msg_tab, i);
1160
1161 if (msg->msg_fields != NULL) {
1162 if (!msg->msg_cached) {
1163 r = imapdriver_write_cached_envelope(cache_db, mmapstr,
1164 session, msg, msg->msg_fields);
1165 }
1166 }
1167 }
1168
1169 /* flush cache */
1170
1171 maildriver_cache_clean_up(cache_db, NULL, env_list);
1172
1173 mail_cache_db_close_unlock(filename, cache_db);
1174 mmap_string_free(mmapstr);
1175
1176 /* remove cache files */
1177
1178 maildriver_message_cache_clean_up(data->imap_quoted_mb, env_list,
1179 get_uid_from_filename);
1180
1181 return MAIL_NO_ERROR;
1182
1183 free_mmapstr:
1184 mmap_string_free(mmapstr);
1185 err:
1186 return res;
1187}
1188
1189static int imapdriver_cached_remove_message(mailsession * session,
1190 uint32_t num)
1191{
1192 int r;
1193
1194 r = mailsession_remove_message(get_ancestor(session), num);
1195
1196 check_for_uid_cache(session);
1197
1198 return r;
1199}
1200
1201#if 0
1202static int imapdriver_cached_search_messages(mailsession * session,
1203 char * charset,
1204 struct mail_search_key * key,
1205 struct mail_search_result **
1206 result)
1207{
1208 int r;
1209
1210 r = mailsession_search_messages(get_ancestor(session), charset, key, result);
1211
1212 check_for_uid_cache(session);
1213
1214 return r;
1215}
1216#endif
1217
1218static int imapdriver_cached_get_message(mailsession * session,
1219 uint32_t num, mailmessage ** result)
1220{
1221 mailmessage * msg_info;
1222 int r;
1223
1224 msg_info = mailmessage_new();
1225 if (msg_info == NULL)
1226 return MAIL_ERROR_MEMORY;
1227
1228 r = mailmessage_init(msg_info, session, imap_cached_message_driver, num, 0);
1229 if (r != MAIL_NO_ERROR) {
1230 mailmessage_free(msg_info);
1231 return r;
1232 }
1233
1234 * result = msg_info;
1235
1236 return MAIL_NO_ERROR;
1237}
1238
1239/* Retrieve a message by UID
1240 * libEtPan! uid format for IMAP is "UIDVALIDITY-UID"
1241 * where UIDVALIDITY and UID are decimal representation of
1242 * respectively uidvalidity and uid numbers.
1243 * Return value:
1244 * MAIL_ERROR_INVAL if uid is NULL or has an incorrect format.
1245 * MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found
1246 * MAIL_NO_ERROR if message was found. Result is in result
1247 */
1248static int imapdriver_cached_get_message_by_uid(mailsession * session,
1249 const char * uid,
1250 mailmessage ** result)
1251{
1252 uint32_t uidvalidity;
1253 uint32_t num;
1254 char * p1, * p2;
1255 mailimap *imap;
1256
1257 if (uid == NULL)
1258 return MAIL_ERROR_INVAL;
1259
1260 uidvalidity = strtoul(uid, &p1, 10);
1261 if (p1 == uid || * p1 != '-')
1262 return MAIL_ERROR_INVAL;
1263
1264 p1++;
1265 num = strtoul(p1, &p2, 10);
1266 if (p2 == p1 || * p2 != '\0')
1267 return MAIL_ERROR_INVAL;
1268
1269 imap = get_imap_session(session);
1270 if (imap->imap_selection_info->sel_uidvalidity != uidvalidity)
1271 return MAIL_ERROR_MSG_NOT_FOUND;
1272
1273 return imapdriver_cached_get_message(session, num, result);
1274}