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