summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/pop3/pop3driver_cached.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/pop3/pop3driver_cached.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/pop3/pop3driver_cached.c899
1 files changed, 899 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/pop3/pop3driver_cached.c b/libetpan/src/driver/implementation/pop3/pop3driver_cached.c
new file mode 100644
index 0000000..d3cc98e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/pop3/pop3driver_cached.c
@@ -0,0 +1,899 @@
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 "pop3driver_cached.h"
37
38#include "libetpan-config.h"
39
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <fcntl.h>
43#include <string.h>
44#include <unistd.h>
45#include <stdlib.h>
46
47#include "mail.h"
48#include "mail_cache_db.h"
49
50#include "maildriver.h"
51#include "mailmessage.h"
52#include "pop3driver.h"
53#include "mailpop3.h"
54#include "generic_cache.h"
55#include "imfcache.h"
56#include "pop3driver_cached_message.h"
57#include "pop3driver_tools.h"
58#include "maildriver_tools.h"
59
60static int pop3driver_cached_initialize(mailsession * session);
61
62static void pop3driver_cached_uninitialize(mailsession * session);
63
64static int pop3driver_cached_parameters(mailsession * session,
65 int id, void * value);
66
67static int pop3driver_cached_connect_stream(mailsession * session,
68 mailstream * s);
69
70static int pop3driver_cached_starttls(mailsession * session);
71
72static int pop3driver_cached_login(mailsession * session,
73 char * userid, char * password);
74
75static int pop3driver_cached_logout(mailsession * session);
76
77static int pop3driver_cached_check_folder(mailsession * session);
78
79static int pop3driver_cached_noop(mailsession * session);
80
81static int pop3driver_cached_expunge_folder(mailsession * session);
82
83static int pop3driver_cached_status_folder(mailsession * session,
84 char * mb, uint32_t * result_messages, uint32_t * result_recent,
85 uint32_t * result_unseen);
86
87static int pop3driver_cached_messages_number(mailsession * session,
88 char * mb,
89 uint32_t * result);
90
91static int pop3driver_cached_recent_number(mailsession * session,
92 char * mb,
93 uint32_t * result);
94
95static int pop3driver_cached_unseen_number(mailsession * session,
96 char * mb,
97 uint32_t * result);
98
99static int pop3driver_cached_remove_message(mailsession * session,
100 uint32_t num);
101
102static int
103pop3driver_cached_get_messages_list(mailsession * session,
104 struct mailmessage_list ** result);
105
106static int
107pop3driver_cached_get_envelopes_list(mailsession * session,
108 struct mailmessage_list * env_list);
109
110static int pop3driver_cached_get_message(mailsession * session,
111 uint32_t num, mailmessage ** result);
112
113static int pop3driver_cached_get_message_by_uid(mailsession * session,
114 const char * uid, mailmessage ** result);
115
116static mailsession_driver local_pop3_cached_session_driver = {
117 .sess_name = "pop3-cached",
118
119 .sess_initialize = pop3driver_cached_initialize,
120 .sess_uninitialize = pop3driver_cached_uninitialize,
121
122 .sess_parameters = pop3driver_cached_parameters,
123
124 .sess_connect_stream = pop3driver_cached_connect_stream,
125 .sess_connect_path = NULL,
126 .sess_starttls = pop3driver_cached_starttls,
127 .sess_login = pop3driver_cached_login,
128 .sess_logout = pop3driver_cached_logout,
129 .sess_noop = pop3driver_cached_noop,
130
131 .sess_build_folder_name = NULL,
132 .sess_create_folder = NULL,
133 .sess_delete_folder = NULL,
134 .sess_rename_folder = NULL,
135 .sess_check_folder = pop3driver_cached_check_folder,
136 .sess_examine_folder = NULL,
137 .sess_select_folder = NULL,
138 .sess_expunge_folder = pop3driver_cached_expunge_folder,
139 .sess_status_folder = pop3driver_cached_status_folder,
140 .sess_messages_number = pop3driver_cached_messages_number,
141 .sess_recent_number = pop3driver_cached_recent_number,
142 .sess_unseen_number = pop3driver_cached_unseen_number,
143 .sess_list_folders = NULL,
144 .sess_lsub_folders = NULL,
145 .sess_subscribe_folder = NULL,
146 .sess_unsubscribe_folder = NULL,
147
148 .sess_append_message = NULL,
149 .sess_append_message_flags = NULL,
150 .sess_copy_message = NULL,
151 .sess_move_message = NULL,
152
153 .sess_get_messages_list = pop3driver_cached_get_messages_list,
154 .sess_get_envelopes_list = pop3driver_cached_get_envelopes_list,
155 .sess_remove_message = pop3driver_cached_remove_message,
156#if 0
157 .sess_search_messages = maildriver_generic_search_messages,
158#endif
159
160 .sess_get_message = pop3driver_cached_get_message,
161 .sess_get_message_by_uid = pop3driver_cached_get_message_by_uid,
162};
163
164mailsession_driver * pop3_cached_session_driver =
165&local_pop3_cached_session_driver;
166
167#define ENV_NAME "env.db"
168#define FLAGS_NAME "flags.db"
169
170
171static inline struct pop3_cached_session_state_data *
172get_cached_data(mailsession * session)
173{
174 return session->sess_data;
175}
176
177static inline mailsession * get_ancestor(mailsession * session)
178{
179 return get_cached_data(session)->pop3_ancestor;
180}
181
182static inline struct pop3_session_state_data *
183get_ancestor_data(mailsession * session)
184{
185 return get_ancestor(session)->sess_data;
186}
187
188static inline mailpop3 * get_pop3_session(mailsession * session)
189{
190 return get_ancestor_data(session)->pop3_session;
191}
192
193static int pop3driver_cached_initialize(mailsession * session)
194{
195 struct pop3_cached_session_state_data * data;
196
197 data = malloc(sizeof(* data));
198 if (data == NULL)
199 goto err;
200
201 data->pop3_flags_store = mail_flags_store_new();
202 if (data->pop3_flags_store == NULL)
203 goto free_data;
204
205 data->pop3_ancestor = mailsession_new(pop3_session_driver);
206 if (data->pop3_ancestor == NULL)
207 goto free_store;
208
209 data->pop3_flags_hash = chash_new(128, CHASH_COPYNONE);
210 if (data->pop3_flags_hash == NULL)
211 goto free_session;
212
213 session->sess_data = data;
214
215 return MAIL_NO_ERROR;
216
217 free_session:
218 mailsession_free(data->pop3_ancestor);
219 free_store:
220 mail_flags_store_free(data->pop3_flags_store);
221 free_data:
222 free(data);
223 err:
224 return MAIL_ERROR_MEMORY;
225}
226
227static int pop3_flags_store_process(char * flags_directory,
228 struct mail_flags_store * flags_store)
229{
230 char filename_flags[PATH_MAX];
231 struct mail_cache_db * cache_db_flags;
232 MMAPString * mmapstr;
233 unsigned int i;
234 int r;
235 int res;
236
237 if (carray_count(flags_store->fls_tab) == 0)
238 return MAIL_NO_ERROR;
239
240 snprintf(filename_flags, PATH_MAX, "%s/%s",
241 flags_directory, FLAGS_NAME);
242
243 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
244 if (r < 0) {
245 res = MAIL_ERROR_FILE;
246 goto err;
247 }
248
249 mmapstr = mmap_string_new("");
250 if (mmapstr == NULL) {
251 res = MAIL_ERROR_MEMORY;
252 goto close_db_flags;
253 }
254
255 for(i = 0 ; i < carray_count(flags_store->fls_tab) ; i ++) {
256 mailmessage * msg;
257
258 msg = carray_get(flags_store->fls_tab, i);
259
260 r = pop3driver_write_cached_flags(cache_db_flags, mmapstr,
261 msg->msg_uid, msg->msg_flags);
262 }
263
264 mmap_string_free(mmapstr);
265 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
266
267 mail_flags_store_clear(flags_store);
268
269 return MAIL_NO_ERROR;
270
271 close_db_flags:
272 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
273 err:
274 return res;
275}
276
277static void pop3driver_cached_uninitialize(mailsession * session)
278{
279 struct pop3_cached_session_state_data * data;
280
281 data = get_cached_data(session);
282
283 pop3_flags_store_process(data->pop3_flags_directory,
284 data->pop3_flags_store);
285
286 mail_flags_store_free(data->pop3_flags_store);
287
288 chash_free(data->pop3_flags_hash);
289 mailsession_free(data->pop3_ancestor);
290 free(data);
291
292 session->sess_data = data;
293}
294
295static int pop3driver_cached_check_folder(mailsession * session)
296{
297 struct pop3_cached_session_state_data * pop3_data;
298
299 pop3_data = get_cached_data(session);
300
301 pop3_flags_store_process(pop3_data->pop3_flags_directory,
302 pop3_data->pop3_flags_store);
303
304 return MAIL_NO_ERROR;
305}
306
307static int pop3driver_cached_parameters(mailsession * session,
308 int id, void * value)
309{
310 struct pop3_cached_session_state_data * data;
311 int r;
312
313 data = get_cached_data(session);
314
315 switch (id) {
316 case POP3DRIVER_CACHED_SET_CACHE_DIRECTORY:
317 strncpy(data->pop3_cache_directory, value, PATH_MAX);
318 data->pop3_cache_directory[PATH_MAX - 1] = '\0';
319
320 r = generic_cache_create_dir(data->pop3_cache_directory);
321 if (r != MAIL_NO_ERROR)
322 return r;
323
324 return MAIL_NO_ERROR;
325
326 case POP3DRIVER_CACHED_SET_FLAGS_DIRECTORY:
327 strncpy(data->pop3_flags_directory, value, PATH_MAX);
328 data->pop3_flags_directory[PATH_MAX - 1] = '\0';
329
330 r = generic_cache_create_dir(data->pop3_flags_directory);
331 if (r != MAIL_NO_ERROR)
332 return r;
333
334 return MAIL_NO_ERROR;
335
336 default:
337 return mailsession_parameters(data->pop3_ancestor, id, value);
338 }
339}
340
341static int pop3driver_cached_connect_stream(mailsession * session,
342 mailstream * s)
343{
344 int r;
345
346 r = mailsession_connect_stream(get_ancestor(session), s);
347 if (r != MAIL_NO_ERROR)
348 return r;
349
350 return MAIL_NO_ERROR;
351}
352
353static int pop3driver_cached_starttls(mailsession * session)
354{
355 return mailsession_starttls(get_ancestor(session));
356}
357
358
359static int pop3driver_cached_login(mailsession * session,
360 char * userid, char * password)
361{
362 return mailsession_login(get_ancestor(session), userid, password);
363}
364
365static int pop3driver_cached_logout(mailsession * session)
366{
367 struct pop3_cached_session_state_data * cached_data;
368
369 cached_data = get_cached_data(session);
370
371 pop3_flags_store_process(cached_data->pop3_flags_directory,
372 cached_data->pop3_flags_store);
373
374 return mailsession_logout(get_ancestor(session));
375}
376
377static int pop3driver_cached_noop(mailsession * session)
378{
379 return mailsession_noop(get_ancestor(session));
380}
381
382static int pop3driver_cached_expunge_folder(mailsession * session)
383{
384 int res;
385 struct pop3_cached_session_state_data * cached_data;
386 char filename_flags[PATH_MAX];
387 struct mail_cache_db * cache_db_flags;
388 MMAPString * mmapstr;
389 unsigned int i;
390 int r;
391 carray * msg_tab;
392 mailpop3 * pop3;
393
394 pop3 = get_pop3_session(session);
395
396 cached_data = get_cached_data(session);
397
398 pop3_flags_store_process(cached_data->pop3_flags_directory,
399 cached_data->pop3_flags_store);
400
401 snprintf(filename_flags, PATH_MAX, "%s/%s",
402 cached_data->pop3_flags_directory, FLAGS_NAME);
403
404 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
405 if (r < 0) {
406 res = MAIL_ERROR_MEMORY;
407 goto err;
408 }
409
410 mmapstr = mmap_string_new("");
411 if (mmapstr == NULL) {
412 res = MAIL_ERROR_MEMORY;
413 goto close_db_flags;
414 }
415
416 mailpop3_list(pop3, &msg_tab);
417
418 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
419 struct mailpop3_msg_info * pop3_info;
420 struct mail_flags * flags;
421
422 pop3_info = carray_get(msg_tab, i);
423 if (pop3_info == NULL)
424 continue;
425
426 if (pop3_info->msg_deleted)
427 continue;
428
429 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
430 session, pop3_info->msg_index, &flags);
431 if (r != MAIL_NO_ERROR)
432 continue;
433
434 if (flags->fl_flags & MAIL_FLAG_DELETED) {
435 r = mailpop3_dele(pop3, pop3_info->msg_index);
436 }
437
438 mail_flags_free(flags);
439 }
440
441 mmap_string_free(mmapstr);
442 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
443
444 return MAIL_NO_ERROR;
445
446 close_db_flags:
447 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
448 err:
449 return res;
450}
451
452static int pop3driver_cached_status_folder(mailsession * session,
453 char * mb, uint32_t * result_messages, uint32_t * result_recent,
454 uint32_t * result_unseen)
455{
456 int res;
457 struct pop3_cached_session_state_data * cached_data;
458 char filename_flags[PATH_MAX];
459 struct mail_cache_db * cache_db_flags;
460 MMAPString * mmapstr;
461 unsigned int i;
462 int r;
463 carray * msg_tab;
464 mailpop3 * pop3;
465 uint32_t recent;
466 uint32_t unseen;
467
468 recent = 0;
469 unseen = 0;
470
471 pop3 = get_pop3_session(session);
472
473 cached_data = get_cached_data(session);
474
475 pop3_flags_store_process(cached_data->pop3_flags_directory,
476 cached_data->pop3_flags_store);
477
478 snprintf(filename_flags, PATH_MAX, "%s/%s",
479 cached_data->pop3_flags_directory, FLAGS_NAME);
480
481 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
482 if (r < 0) {
483 res = MAIL_ERROR_MEMORY;
484 goto err;
485 }
486
487 mmapstr = mmap_string_new("");
488 if (mmapstr == NULL) {
489 res = MAIL_ERROR_MEMORY;
490 goto close_db_flags;
491 }
492
493 mailpop3_list(pop3, &msg_tab);
494
495 for(i = 0 ; i < carray_count(msg_tab) ; i++) {
496 struct mailpop3_msg_info * pop3_info;
497 struct mail_flags * flags;
498
499 pop3_info = carray_get(msg_tab, i);
500 if (pop3_info == NULL)
501 continue;
502
503 if (pop3_info->msg_deleted)
504 continue;
505
506 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
507 session, pop3_info->msg_index, &flags);
508 if (r != MAIL_NO_ERROR) {
509 recent ++;
510 unseen ++;
511 continue;
512 }
513
514 if ((flags->fl_flags & MAIL_FLAG_NEW) != 0) {
515 recent ++;
516 }
517 if ((flags->fl_flags & MAIL_FLAG_SEEN) == 0) {
518 unseen ++;
519 }
520 mail_flags_free(flags);
521
522 }
523
524 mmap_string_free(mmapstr);
525 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
526
527 * result_messages = carray_count(msg_tab) - pop3->pop3_deleted_count;
528 * result_recent = recent;
529 * result_unseen = unseen;
530
531 return MAIL_NO_ERROR;
532
533 close_db_flags:
534 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
535 err:
536 return res;
537}
538
539static int pop3driver_cached_messages_number(mailsession * session,
540 char * mb,
541 uint32_t * result)
542{
543 return mailsession_messages_number(get_ancestor(session), mb, result);
544}
545
546static int pop3driver_cached_recent_number(mailsession * session,
547 char * mb,
548 uint32_t * result)
549{
550 uint32_t messages;
551 uint32_t recent;
552 uint32_t unseen;
553 int r;
554
555 r = pop3driver_cached_status_folder(session, mb,
556 &messages, &recent, &unseen);
557 if (r != MAIL_NO_ERROR)
558 return r;
559
560 * result = recent;
561
562 return MAIL_NO_ERROR;
563}
564
565static int pop3driver_cached_unseen_number(mailsession * session,
566 char * mb,
567 uint32_t * result)
568{
569 uint32_t messages;
570 uint32_t recent;
571 uint32_t unseen;
572 int r;
573
574 r = pop3driver_cached_status_folder(session, mb,
575 &messages, &recent, &unseen);
576 if (r != MAIL_NO_ERROR)
577 return r;
578
579 * result = unseen;
580
581 return MAIL_NO_ERROR;
582}
583
584/* messages operations */
585
586static int pop3driver_cached_remove_message(mailsession * session,
587 uint32_t num)
588{
589 return mailsession_remove_message(get_ancestor(session), num);
590}
591
592static int
593pop3driver_cached_get_messages_list(mailsession * session,
594 struct mailmessage_list ** result)
595{
596 mailpop3 * pop3;
597
598 pop3 = get_pop3_session(session);
599
600 return pop3_get_messages_list(pop3, session,
601 pop3_cached_message_driver, result);
602}
603
604
605static int
606get_cached_envelope(struct mail_cache_db * cache_db, MMAPString * mmapstr,
607 mailsession * session, uint32_t num,
608 struct mailimf_fields ** result)
609{
610 int r;
611 char keyname[PATH_MAX];
612 struct mailpop3_msg_info * info;
613 struct mailimf_fields * fields;
614 int res;
615 mailpop3 * pop3;
616
617 pop3 = get_pop3_session(session);
618
619 r = mailpop3_get_msg_info(pop3, num, &info);
620 switch (r) {
621 case MAILPOP3_ERROR_BAD_STATE:
622 return MAIL_ERROR_BAD_STATE;
623 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
624 return MAIL_ERROR_MSG_NOT_FOUND;
625 case MAILPOP3_NO_ERROR:
626 break;
627 default:
628 return MAIL_ERROR_FETCH;
629 }
630
631 snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl);
632
633 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
634 if (r != MAIL_NO_ERROR) {
635 res = r;
636 goto err;
637 }
638
639 * result = fields;
640
641 return MAIL_NO_ERROR;
642
643 err:
644 return res;
645}
646
647static int
648write_cached_envelope(struct mail_cache_db * cache_db,
649 MMAPString * mmapstr,
650 mailsession * session, uint32_t num,
651 struct mailimf_fields * fields)
652{
653 int r;
654 char keyname[PATH_MAX];
655 int res;
656 struct mailpop3_msg_info * info;
657 mailpop3 * pop3;
658
659 pop3 = get_pop3_session(session);
660
661 r = mailpop3_get_msg_info(pop3, num, &info);
662 switch (r) {
663 case MAILPOP3_ERROR_BAD_STATE:
664 return MAIL_ERROR_BAD_STATE;
665 case MAILPOP3_ERROR_NO_SUCH_MESSAGE:
666 return MAIL_ERROR_MSG_NOT_FOUND;
667 case MAILPOP3_NO_ERROR:
668 break;
669 default:
670 return MAIL_ERROR_FETCH;
671 }
672
673 snprintf(keyname, PATH_MAX, "%s-envelope", info->msg_uidl);
674
675 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
676 if (r != MAIL_NO_ERROR) {
677 res = r;
678 goto err;
679 }
680
681 return MAIL_NO_ERROR;
682
683 err:
684 return res;
685}
686
687static void get_uid_from_filename(char * filename)
688{
689 char * p;
690
691 p = strstr(filename, "-header");
692 if (p != NULL)
693 * p = 0;
694}
695
696static int
697pop3driver_cached_get_envelopes_list(mailsession * session,
698 struct mailmessage_list * env_list)
699{
700 int r;
701 unsigned int i;
702 struct pop3_cached_session_state_data * cached_data;
703 char filename_env[PATH_MAX];
704 char filename_flags[PATH_MAX];
705 struct mail_cache_db * cache_db_env;
706 struct mail_cache_db * cache_db_flags;
707 MMAPString * mmapstr;
708 int res;
709
710 cached_data = get_cached_data(session);
711
712 pop3_flags_store_process(cached_data->pop3_flags_directory,
713 cached_data->pop3_flags_store);
714
715 snprintf(filename_env, PATH_MAX, "%s/%s",
716 cached_data->pop3_cache_directory, ENV_NAME);
717
718 mmapstr = mmap_string_new("");
719 if (mmapstr == NULL) {
720 res = MAIL_ERROR_MEMORY;
721 goto err;
722 }
723
724 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
725 if (r < 0) {
726 res = MAIL_ERROR_MEMORY;
727 goto free_mmapstr;
728 }
729
730 snprintf(filename_flags, PATH_MAX, "%s/%s",
731 cached_data->pop3_flags_directory, FLAGS_NAME);
732
733 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
734 if (r < 0) {
735 res = MAIL_ERROR_MEMORY;
736 goto close_db_env;
737 }
738
739 /* fill with cached */
740
741 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
742 mailmessage * msg;
743 struct mailimf_fields * fields;
744 struct mail_flags * flags;
745
746 msg = carray_get(env_list->msg_tab, i);
747
748 if (msg->msg_fields == NULL) {
749 r = get_cached_envelope(cache_db_env, mmapstr,
750 session, msg->msg_index, &fields);
751 if (r == MAIL_NO_ERROR) {
752 msg->msg_cached = TRUE;
753 msg->msg_fields = fields;
754 }
755 }
756
757 if (msg->msg_flags == NULL) {
758 r = pop3driver_get_cached_flags(cache_db_flags, mmapstr,
759 session, msg->msg_index, &flags);
760 if (r == MAIL_NO_ERROR) {
761 msg->msg_flags = flags;
762 }
763 }
764 }
765
766 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
767 mail_cache_db_close_unlock(filename_env, cache_db_env);
768
769 r = maildriver_generic_get_envelopes_list(session, env_list);
770
771 if (r != MAIL_NO_ERROR) {
772 res = r;
773 goto free_mmapstr;
774 }
775
776 /* add flags */
777
778 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
779 mailmessage * msg;
780
781 msg = carray_get(env_list->msg_tab, i);
782
783 if (msg->msg_flags == NULL)
784 msg->msg_flags = mail_flags_new_empty();
785 }
786
787 r = mail_cache_db_open_lock(filename_env, &cache_db_env);
788 if (r < 0) {
789 res = MAIL_ERROR_MEMORY;
790 goto free_mmapstr;
791 }
792
793 r = mail_cache_db_open_lock(filename_flags, &cache_db_flags);
794 if (r < 0) {
795 res = MAIL_ERROR_MEMORY;
796 goto close_db_env;
797 }
798
799 /* must write cache */
800
801 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
802 mailmessage * msg;
803
804 msg = carray_get(env_list->msg_tab, i);
805
806 if (msg->msg_fields != NULL) {
807 if (!msg->msg_cached) {
808 r = write_cached_envelope(cache_db_env, mmapstr,
809 session, msg->msg_index, msg->msg_fields);
810 }
811 }
812
813 if (msg->msg_flags != NULL) {
814 r = pop3driver_write_cached_flags(cache_db_flags, mmapstr,
815 msg->msg_uid, msg->msg_flags);
816 }
817 }
818
819 /* flush cache */
820
821 maildriver_cache_clean_up(cache_db_env, cache_db_flags, env_list);
822
823 mail_cache_db_close_unlock(filename_flags, cache_db_flags);
824 mail_cache_db_close_unlock(filename_env, cache_db_env);
825 mmap_string_free(mmapstr);
826
827 /* remove cache files */
828
829 maildriver_message_cache_clean_up(cached_data->pop3_cache_directory,
830 env_list, get_uid_from_filename);
831
832 return MAIL_NO_ERROR;
833
834 close_db_env:
835 mail_cache_db_close_unlock(filename_env, cache_db_env);
836 free_mmapstr:
837 mmap_string_free(mmapstr);
838 err:
839 return res;
840}
841
842static int pop3driver_cached_get_message(mailsession * session,
843 uint32_t num, mailmessage ** result)
844{
845 mailmessage * msg_info;
846 int r;
847
848 msg_info = mailmessage_new();
849 if (msg_info == NULL)
850 return MAIL_ERROR_MEMORY;
851
852 r = mailmessage_init(msg_info, session, pop3_cached_message_driver, num, 0);
853 if (r != MAIL_NO_ERROR) {
854 mailmessage_free(msg_info);
855 return r;
856 }
857
858 * result = msg_info;
859
860 return MAIL_NO_ERROR;
861}
862
863static int pop3driver_cached_get_message_by_uid(mailsession * session,
864 const char * uid, mailmessage ** result)
865{
866 mailpop3 * pop3;
867 struct mailpop3_msg_info * msg_info;
868 int found;
869 unsigned int i;
870
871 if (uid == NULL)
872 return MAIL_ERROR_INVAL;
873
874 pop3 = get_pop3_session(session);
875
876 found = 0;
877
878 /* iterate all messages and look for uid */
879 for(i = 0 ; i < carray_count(pop3->pop3_msg_tab) ; i++) {
880 msg_info = carray_get(pop3->pop3_msg_tab, i);
881
882 if (msg_info == NULL)
883 continue;
884
885 if (msg_info->msg_deleted)
886 continue;
887
888 /* uid found, stop looking */
889 if (strcmp(msg_info->msg_uidl, uid) == 0) {
890 found = 1;
891 break;
892 }
893 }
894
895 if (!found)
896 return MAIL_ERROR_MSG_NOT_FOUND;
897
898 return pop3driver_cached_get_message(session, msg_info->msg_index, result);
899}