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