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