summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/imap
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/imap') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver.c1226
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached.c1370
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached_message.c664
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_cached_message.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_message.c1239
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_message.h52
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_tools.c3623
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_tools.h116
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_types.h144
-rw-r--r--libetpan/src/driver/implementation/imap/imapstorage.c297
-rw-r--r--libetpan/src/driver/implementation/imap/imapstorage.h90
13 files changed, 8977 insertions, 0 deletions
diff --git a/libetpan/src/driver/implementation/imap/imapdriver.c b/libetpan/src/driver/implementation/imap/imapdriver.c
new file mode 100644
index 0000000..815e077
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver.c
@@ -0,0 +1,1226 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver.h"
37
38#include "mail.h"
39#include "imapdriver_tools.h"
40#include "mailmessage.h"
41#include "imapdriver_message.h"
42#include "imapdriver_types.h"
43#include "maildriver.h"
44#include "maildriver_tools.h"
45#include "generic_cache.h"
46
47#include <stdlib.h>
48#include <string.h>
49
50static int imapdriver_initialize(mailsession * session);
51
52static void imapdriver_uninitialize(mailsession * session);
53
54static int imapdriver_connect_stream(mailsession * session, mailstream * s);
55
56static int imapdriver_starttls(mailsession * session);
57
58static int imapdriver_login(mailsession * session,
59 char * userid, char * password);
60
61static int imapdriver_logout(mailsession * session);
62
63static int imapdriver_noop(mailsession * session);
64
65static int imapdriver_build_folder_name(mailsession * session, char * mb,
66 char * name, char ** result);
67
68static int imapdriver_create_folder(mailsession * session, char * mb);
69
70static int imapdriver_delete_folder(mailsession * session, char * mb);
71
72static int imapdriver_rename_folder(mailsession * session, char * mb,
73 char * new_name);
74
75static int imapdriver_check_folder(mailsession * session);
76
77static int imapdriver_examine_folder(mailsession * session, char * mb);
78
79static int imapdriver_select_folder(mailsession * session, char * mb);
80static int imapdriver_expunge_folder(mailsession * session);
81
82static int imapdriver_status_folder(mailsession * session, char * mb,
83 uint32_t * result_messages, uint32_t * result_recent,
84 uint32_t * result_unseen);
85
86static int imapdriver_messages_number(mailsession * session, char * mb,
87 uint32_t * result);
88
89static int imapdriver_recent_number(mailsession * session, char * mb,
90 uint32_t * result);
91
92static int imapdriver_unseen_number(mailsession * session, char * mb,
93 uint32_t * result);
94
95static int imapdriver_list_folders(mailsession * session, char * mb,
96 struct mail_list ** result);
97static int imapdriver_lsub_folders(mailsession * session, char * mb,
98 struct mail_list ** result);
99static int imapdriver_subscribe_folder(mailsession * session, char * mb);
100static int imapdriver_unsubscribe_folder(mailsession * session, char * mb);
101static int imapdriver_append_message(mailsession * session,
102 char * message, size_t size);
103static int imapdriver_append_message_flags(mailsession * session,
104 char * message, size_t size, struct mail_flags * flags);
105static int imapdriver_copy_message(mailsession * session,
106 uint32_t num, char * mb);
107
108static int imapdriver_get_messages_list(mailsession * session,
109 struct mailmessage_list ** result);
110
111static int
112imapdriver_get_envelopes_list(mailsession * session,
113 struct mailmessage_list * env_list);
114
115
116#if 0
117static int imapdriver_search_messages(mailsession * session, char * charset,
118 struct mail_search_key * key,
119 struct mail_search_result ** result);
120#endif
121
122static int imapdriver_get_message(mailsession * session,
123 uint32_t num, mailmessage ** result);
124
125static int imapdriver_get_message_by_uid(mailsession * session,
126 const char * uid,
127 mailmessage ** result);
128
129static mailsession_driver local_imap_session_driver = {
130 .sess_name = "imap",
131
132 .sess_initialize = imapdriver_initialize,
133 .sess_uninitialize = imapdriver_uninitialize,
134
135 .sess_parameters = NULL,
136
137 .sess_connect_stream = imapdriver_connect_stream,
138 .sess_connect_path = NULL,
139 .sess_starttls = imapdriver_starttls,
140 .sess_login = imapdriver_login,
141 .sess_logout = imapdriver_logout,
142 .sess_noop = imapdriver_noop,
143
144 .sess_build_folder_name = imapdriver_build_folder_name,
145 .sess_create_folder = imapdriver_create_folder,
146 .sess_delete_folder = imapdriver_delete_folder,
147 .sess_rename_folder = imapdriver_rename_folder,
148 .sess_check_folder = imapdriver_check_folder,
149 .sess_examine_folder = imapdriver_examine_folder,
150 .sess_select_folder = imapdriver_select_folder,
151 .sess_expunge_folder = imapdriver_expunge_folder,
152 .sess_status_folder = imapdriver_status_folder,
153 .sess_messages_number = imapdriver_messages_number,
154 .sess_recent_number = imapdriver_recent_number,
155 .sess_unseen_number = imapdriver_unseen_number,
156 .sess_list_folders = imapdriver_list_folders,
157 .sess_lsub_folders = imapdriver_lsub_folders,
158 .sess_subscribe_folder = imapdriver_subscribe_folder,
159 .sess_unsubscribe_folder = imapdriver_unsubscribe_folder,
160
161 .sess_append_message = imapdriver_append_message,
162 .sess_append_message_flags = imapdriver_append_message_flags,
163 .sess_copy_message = imapdriver_copy_message,
164 .sess_move_message = NULL,
165
166 .sess_get_messages_list = imapdriver_get_messages_list,
167 .sess_get_envelopes_list = imapdriver_get_envelopes_list,
168 .sess_remove_message = NULL,
169#if 0
170 .sess_search_messages = imapdriver_search_messages,
171#endif
172
173 .sess_get_message = imapdriver_get_message,
174 .sess_get_message_by_uid = imapdriver_get_message_by_uid,
175};
176
177mailsession_driver * imap_session_driver = &local_imap_session_driver;
178
179static inline struct imap_session_state_data * get_data(mailsession * session)
180{
181 return session->sess_data;
182}
183
184static mailimap * get_imap_session(mailsession * session)
185{
186 return get_data(session)->imap_session;
187}
188
189static int imapdriver_initialize(mailsession * session)
190{
191 struct imap_session_state_data * data;
192 mailimap * imap;
193 struct mail_flags_store * flags_store;
194
195 imap = mailimap_new(0, NULL);
196 if (imap == NULL)
197 goto err;
198
199 flags_store = mail_flags_store_new();
200 if (flags_store == NULL)
201 goto free_session;
202
203 data = malloc(sizeof(* data));
204 if (data == NULL)
205 goto free_flags_store;
206
207 data->imap_mailbox = NULL;
208 data->imap_session = imap;
209 data->imap_flags_store = flags_store;
210
211 session->sess_data = data;
212
213 return MAIL_NO_ERROR;
214
215 free_flags_store:
216 mail_flags_store_free(flags_store);
217 free_session:
218 mailimap_free(imap);
219 err:
220 return MAIL_ERROR_MEMORY;
221}
222
223static void imap_flags_store_process(mailimap * imap,
224 struct mail_flags_store * flags_store)
225{
226 unsigned int i;
227 int r;
228 mailmessage * first;
229 mailmessage * last;
230
231 mail_flags_store_sort(flags_store);
232
233 if (carray_count(flags_store->fls_tab) == 0)
234 return;
235
236 first = carray_get(flags_store->fls_tab, 0);
237 last = first;
238
239 for(i = 1 ; i < carray_count(flags_store->fls_tab) ; i ++) {
240 mailmessage * msg;
241
242 msg = carray_get(flags_store->fls_tab, i);
243
244 if (last->msg_index + 1 == msg->msg_index) {
245 r = mail_flags_compare(first->msg_flags, msg->msg_flags);
246 if (r == 0) {
247 last = msg;
248 continue;
249 }
250 }
251
252 r = imap_store_flags(imap, first->msg_index,
253 last->msg_index, first->msg_flags);
254
255 first = msg;
256 last = msg;
257 }
258
259 r = imap_store_flags(imap, first->msg_index, last->msg_index,
260 first->msg_flags);
261
262 mail_flags_store_clear(flags_store);
263}
264
265static void imapdriver_uninitialize(mailsession * session)
266{
267 struct imap_session_state_data * data;
268
269 data = get_data(session);
270
271 imap_flags_store_process(data->imap_session,
272 data->imap_flags_store);
273 mail_flags_store_free(data->imap_flags_store);
274
275 mailimap_free(data->imap_session);
276 if (data->imap_mailbox != NULL)
277 free(data->imap_mailbox);
278 free(data);
279
280 session->sess_data = NULL;
281}
282
283static int imapdriver_connect_stream(mailsession * session, mailstream * s)
284{
285 int r;
286
287 r = mailimap_connect(get_imap_session(session), s);
288
289 return imap_error_to_mail_error(r);
290}
291
292static int imapdriver_login(mailsession * session,
293 char * userid, char * password)
294{
295 int r;
296
297 r = mailimap_login(get_imap_session(session), userid, password);
298
299 return imap_error_to_mail_error(r);
300}
301
302static int imapdriver_logout(mailsession * session)
303{
304 int r;
305
306 imap_flags_store_process(get_imap_session(session),
307 get_data(session)->imap_flags_store);
308
309 r = mailimap_logout(get_imap_session(session));
310
311 return imap_error_to_mail_error(r);
312}
313
314static int imapdriver_noop(mailsession * session)
315{
316 int r;
317
318 r = mailimap_noop(get_imap_session(session));
319
320 return imap_error_to_mail_error(r);
321}
322
323static int imapdriver_build_folder_name(mailsession * session, char * mb,
324 char * name, char ** result)
325{
326 char delimiter[2] = "X";
327 char * folder_name;
328 mailimap * imap;
329 struct mailimap_mailbox_list * mb_list;
330 int r;
331 clist * imap_list;
332
333 imap = get_imap_session(session);
334
335 r = mailimap_list(imap, mb, "", &imap_list);
336 if (r != MAILIMAP_NO_ERROR)
337 return r;
338
339 if (clist_begin(imap_list) == NULL)
340 return MAIL_ERROR_LIST;
341
342 mb_list = clist_begin(imap_list)->data;
343 delimiter[0] = mb_list->mb_delimiter;
344
345 folder_name = malloc(strlen(mb) + strlen(delimiter) + strlen(name) + 1);
346 if (folder_name == NULL)
347 return MAIL_ERROR_MEMORY;
348
349 strcpy(folder_name, mb);
350 strcat(folder_name, delimiter);
351 strcat(folder_name, name);
352
353 * result = folder_name;
354
355 return MAIL_NO_ERROR;
356}
357
358/* folders operations */
359
360static int imapdriver_create_folder(mailsession * session, char * mb)
361{
362 int r;
363
364 r = mailimap_create(get_imap_session(session), mb);
365
366 return imap_error_to_mail_error(r);
367}
368
369static int imapdriver_delete_folder(mailsession * session, char * mb)
370{
371 int r;
372
373 r = mailimap_delete(get_imap_session(session), mb);
374
375 return imap_error_to_mail_error(r);
376}
377
378static int imapdriver_rename_folder(mailsession * session, char * mb,
379 char * new_name)
380{
381 int r;
382
383 r = mailimap_rename(get_imap_session(session), mb, new_name);
384
385 return imap_error_to_mail_error(r);
386}
387
388static int imapdriver_check_folder(mailsession * session)
389{
390 int r;
391
392 imap_flags_store_process(get_imap_session(session),
393 get_data(session)->imap_flags_store);
394
395 r = mailimap_check(get_imap_session(session));
396
397 return imap_error_to_mail_error(r);
398}
399
400static int imapdriver_examine_folder(mailsession * session, char * mb)
401{
402 int r;
403
404 r = mailimap_examine(get_imap_session(session), mb);
405
406 return imap_error_to_mail_error(r);
407}
408
409static int imapdriver_select_folder(mailsession * session, char * mb)
410{
411 int r;
412 char * new_mb;
413 char * old_mb;
414
415 old_mb = get_data(session)->imap_mailbox;
416 if (old_mb != NULL)
417 if (strcmp(mb, old_mb) == 0)
418 return MAIL_NO_ERROR;
419
420 imap_flags_store_process(get_imap_session(session),
421 get_data(session)->imap_flags_store);
422
423 r = mailimap_select(get_imap_session(session), mb);
424
425 switch (r) {
426 case MAILIMAP_NO_ERROR:
427 new_mb = strdup(mb);
428 if (new_mb == NULL) {
429 if (old_mb != NULL)
430 free(old_mb);
431 get_data(session)->imap_mailbox = NULL;
432 return MAIL_ERROR_MEMORY;
433 }
434
435 get_data(session)->imap_mailbox = new_mb;
436
437 return MAIL_NO_ERROR;
438 default:
439 return imap_error_to_mail_error(r);
440 }
441}
442
443static int imapdriver_expunge_folder(mailsession * session)
444{
445 int r;
446
447 imap_flags_store_process(get_imap_session(session),
448 get_data(session)->imap_flags_store);
449
450 r = mailimap_expunge(get_imap_session(session));
451
452 return imap_error_to_mail_error(r);
453}
454
455static int status_selected_folder(mailsession * session, char * mb,
456 uint32_t * result_messages, uint32_t * result_recent,
457 uint32_t * result_unseen)
458{
459 int r;
460 int res;
461 mailimap * imap;
462 uint32_t exists;
463 uint32_t unseen;
464 uint32_t recent;
465 struct mailimap_search_key * search_key;
466 clist * search_result;
467
468 imap = get_imap_session(session);
469
470 exists = imap->imap_selection_info->sel_exists;
471 recent = imap->imap_selection_info->sel_recent;
472
473 search_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN,
474 NULL, NULL, NULL, NULL, NULL,
475 NULL, NULL, NULL, NULL, NULL,
476 NULL, NULL, NULL, NULL, 0,
477 NULL, NULL, NULL, NULL, NULL,
478 NULL, 0, NULL, NULL, NULL);
479 if (search_key == NULL) {
480 res = MAIL_ERROR_MEMORY;
481 goto err;
482 }
483
484 /* default : use the RECENT count if search fails */
485 unseen = recent;
486 r = mailimap_search(imap, NULL, search_key, &search_result);
487 mailimap_search_key_free(search_key);
488 if (r == MAILIMAP_NO_ERROR) {
489 /* if this succeed, we use the real count */
490 unseen = clist_count(search_result);
491 mailimap_mailbox_data_search_free(search_result);
492 }
493
494 * result_messages = exists;
495 * result_unseen = unseen;
496 * result_recent = recent;
497
498 return MAIL_NO_ERROR;
499
500 err:
501 return res;
502}
503
504static int status_unselected_folder(mailsession * session, char * mb,
505 uint32_t * result_messages, uint32_t * result_recent,
506 uint32_t * result_unseen)
507{
508 struct mailimap_status_att_list * att_list;
509 struct mailimap_mailbox_data_status * status;
510 int r;
511 int res;
512 clistiter * cur;
513 mailimap * imap;
514
515 imap = get_imap_session(session);
516
517 att_list = mailimap_status_att_list_new_empty();
518 if (att_list == NULL) {
519 res = MAIL_ERROR_MEMORY;
520 goto err;
521 }
522
523 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_MESSAGES);
524 switch (r) {
525 case MAILIMAP_NO_ERROR:
526 break;
527 default:
528 res = MAIL_ERROR_MEMORY;
529 goto free;
530 }
531
532 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_RECENT);
533 switch (r) {
534 case MAILIMAP_NO_ERROR:
535 break;
536 default:
537 res = MAIL_ERROR_MEMORY;
538 goto free;
539 }
540
541 r = mailimap_status_att_list_add(att_list, MAILIMAP_STATUS_ATT_UNSEEN);
542 switch (r) {
543 case MAILIMAP_NO_ERROR:
544 break;
545 default:
546 res = MAIL_ERROR_MEMORY;
547 goto free;
548 }
549
550 r = mailimap_status(imap, mb, att_list, &status);
551
552 switch (r) {
553 case MAILIMAP_NO_ERROR:
554 break;
555 default:
556 res = imap_error_to_mail_error(r);
557 goto free;
558 }
559
560 * result_messages = 0;
561 * result_recent = 0;
562 * result_unseen = 0;
563
564 for (cur = clist_begin(status->st_info_list);
565 cur != NULL ; cur = clist_next(cur)) {
566 struct mailimap_status_info * status_info;
567
568 status_info = clist_content(cur);
569 switch (status_info->st_att) {
570 case MAILIMAP_STATUS_ATT_MESSAGES:
571 * result_messages = status_info->st_value;
572 break;
573 case MAILIMAP_STATUS_ATT_RECENT:
574 * result_recent = status_info->st_value;
575 break;
576 case MAILIMAP_STATUS_ATT_UNSEEN:
577 * result_unseen = status_info->st_value;
578 break;
579 }
580 }
581
582 mailimap_mailbox_data_status_free(status);
583 mailimap_status_att_list_free(att_list);
584
585 return MAIL_NO_ERROR;
586
587 free:
588 mailimap_status_att_list_free(att_list);
589 err:
590 return res;
591}
592
593static int imapdriver_status_folder(mailsession * session, char * mb,
594 uint32_t * result_messages, uint32_t * result_recent,
595 uint32_t * result_unseen)
596{
597 int res;
598 int current_folder;
599 char * current_mb;
600
601 if (mb == NULL) {
602 mb = get_data(session)->imap_mailbox;
603 if (mb == NULL) {
604 res = MAIL_ERROR_BAD_STATE;
605 goto err;
606 }
607 }
608
609 current_mb = get_data(session)->imap_mailbox;
610 if (strcmp(mb, current_mb) == 0)
611 current_folder = 1;
612 else
613 current_folder = 0;
614
615 if (current_folder)
616 return status_selected_folder(session, mb, result_messages,
617 result_recent, result_unseen);
618 else
619 return status_unselected_folder(session, mb, result_messages,
620 result_recent, result_unseen);
621
622 err:
623 return res;
624}
625
626/* TODO : more efficient functions */
627
628static int imapdriver_messages_number(mailsession * session, char * mb,
629 uint32_t * result)
630{
631 uint32_t messages;
632 uint32_t recent;
633 uint32_t unseen;
634 int r;
635
636 r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen);
637 if (r != MAIL_NO_ERROR)
638 return r;
639
640 * result = messages;
641
642 return MAIL_NO_ERROR;
643}
644
645static int imapdriver_recent_number(mailsession * session, char * mb,
646 uint32_t * result)
647{
648 uint32_t messages;
649 uint32_t recent;
650 uint32_t unseen;
651 int r;
652
653 r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen);
654 if (r != MAIL_NO_ERROR)
655 return r;
656
657 * result = recent;
658
659 return MAIL_NO_ERROR;
660}
661
662static int imapdriver_unseen_number(mailsession * session, char * mb,
663 uint32_t * result)
664{
665 uint32_t messages;
666 uint32_t recent;
667 uint32_t unseen;
668 int r;
669
670 r = imapdriver_status_folder(session, mb, &messages, &recent, &unseen);
671 if (r != MAIL_NO_ERROR)
672 return r;
673
674 * result = unseen;
675
676 return MAIL_NO_ERROR;
677}
678
679enum {
680 IMAP_LIST, IMAP_LSUB
681};
682
683static int imapdriver_list_lsub_folders(mailsession * session, int type,
684 char * mb,
685 struct mail_list ** result)
686{
687 clist * imap_list;
688 struct mail_list * resp;
689 int r;
690 int res;
691
692 switch (type) {
693 case IMAP_LIST:
694 r = mailimap_list(get_imap_session(session), mb,
695 "*", &imap_list);
696 break;
697 case IMAP_LSUB:
698 r = mailimap_lsub(get_imap_session(session), mb,
699 "*", &imap_list);
700 break;
701 default:
702 res = MAIL_ERROR_LIST;
703 goto err;
704 }
705
706 switch (r) {
707 case MAILIMAP_NO_ERROR:
708 break;
709 default:
710 res = imap_error_to_mail_error(r);
711 goto err;
712 }
713
714 r = imap_list_to_list(imap_list, &resp);
715 if (r != MAIL_NO_ERROR) {
716 mailimap_list_result_free(imap_list);
717 res = r;
718 goto err;
719 }
720
721 mailimap_list_result_free(imap_list);
722
723 * result = resp;
724
725 return MAIL_NO_ERROR;
726
727 err:
728 return res;
729}
730
731static int imapdriver_list_folders(mailsession * session, char * mb,
732 struct mail_list ** result)
733{
734 return imapdriver_list_lsub_folders(session, IMAP_LIST, mb,
735 result);
736}
737
738static int imapdriver_lsub_folders(mailsession * session, char * mb,
739 struct mail_list ** result)
740{
741 return imapdriver_list_lsub_folders(session, IMAP_LSUB, mb,
742 result);
743}
744
745static int imapdriver_subscribe_folder(mailsession * session, char * mb)
746{
747 int r;
748
749 r = mailimap_subscribe(get_imap_session(session), mb);
750
751 return imap_error_to_mail_error(r);
752}
753
754static int imapdriver_unsubscribe_folder(mailsession * session, char * mb)
755{
756 int r;
757
758 r = mailimap_unsubscribe(get_imap_session(session), mb);
759
760 return imap_error_to_mail_error(r);
761}
762
763/* messages operations */
764
765static int imapdriver_append_message(mailsession * session,
766 char * message, size_t size)
767{
768 int r;
769
770 r = mailimap_append_simple(get_imap_session(session),
771 get_data(session)->imap_mailbox,
772 message, size);
773
774 return imap_error_to_mail_error(r);
775}
776
777static int imapdriver_append_message_flags(mailsession * session,
778 char * message, size_t size, struct mail_flags * flags)
779{
780 struct mailimap_flag_list * flag_list;
781 int r;
782
783 if (flags != NULL) {
784 r = imap_flags_to_imap_flags(flags, &flag_list);
785 if (r != MAIL_NO_ERROR)
786 return r;
787 }
788 else {
789 flag_list = NULL;
790 }
791
792 r = mailimap_append(get_imap_session(session),
793 get_data(session)->imap_mailbox,
794 flag_list, NULL, message, size);
795
796 if (flag_list != NULL)
797 mailimap_flag_list_free(flag_list);
798
799 return imap_error_to_mail_error(r);
800}
801
802static int imapdriver_copy_message(mailsession * session,
803 uint32_t num, char * mb)
804{
805 int r;
806 struct mailimap_set * set;
807 int res;
808
809 set = mailimap_set_new_single(num);
810 if (set == NULL) {
811 res = MAIL_ERROR_MEMORY;
812 goto err;
813 }
814
815 r = mailimap_uid_copy(get_imap_session(session), set, mb);
816
817 mailimap_set_free(set);
818
819 return imap_error_to_mail_error(r);
820
821 err:
822 return res;
823}
824
825static int imapdriver_get_messages_list(mailsession * session,
826 struct mailmessage_list ** result)
827{
828 return imap_get_messages_list(get_imap_session(session),
829 session, imap_message_driver, 1,
830 result);
831}
832
833
834
835#define IMAP_SET_MAX_COUNT 100
836
837static int
838imapdriver_get_envelopes_list(mailsession * session,
839 struct mailmessage_list * env_list)
840{
841 struct mailimap_set * set;
842 struct mailimap_fetch_att * fetch_att;
843 struct mailimap_fetch_type * fetch_type;
844 int res;
845 clist * fetch_result;
846 int r;
847 uint32_t exists;
848 clist * msg_list;
849 clistiter * set_iter;
850
851 if (get_imap_session(session)->imap_selection_info == NULL) {
852 res = MAIL_ERROR_BAD_STATE;
853 goto err;
854 }
855
856 imap_flags_store_process(get_imap_session(session),
857 get_data(session)->imap_flags_store);
858
859 exists = get_imap_session(session)->imap_selection_info->sel_exists;
860
861 if (exists == 0)
862 return MAIL_NO_ERROR;
863
864 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
865 if (fetch_type == NULL) {
866 res = MAIL_ERROR_MEMORY;
867 goto err;
868 }
869
870 fetch_att = mailimap_fetch_att_new_uid();
871 if (fetch_att == NULL) {
872 res = MAIL_ERROR_MEMORY;
873 goto free_fetch_type;
874 }
875
876 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
877 if (r != MAILIMAP_NO_ERROR) {
878 mailimap_fetch_att_free(fetch_att);
879 res = MAIL_ERROR_MEMORY;
880 goto free_fetch_type;
881 }
882
883 fetch_att = mailimap_fetch_att_new_flags();
884 if (fetch_att == NULL) {
885 res = MAIL_ERROR_MEMORY;
886 goto free_fetch_type;
887 }
888
889 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
890 if (r != MAILIMAP_NO_ERROR) {
891 mailimap_fetch_att_free(fetch_att);
892 res = MAIL_ERROR_MEMORY;
893 goto free_fetch_type;
894 }
895
896 r = imap_add_envelope_fetch_att(fetch_type);
897 if (r != MAIL_NO_ERROR) {
898 res = r;
899 goto free_fetch_type;
900 }
901
902 r = maildriver_env_list_to_msg_list(env_list, &msg_list);
903 if (r != MAIL_NO_ERROR) {
904 res = MAIL_ERROR_MEMORY;
905 goto free_fetch_type;
906 }
907
908 if (clist_begin(msg_list) == NULL) {
909 /* no need to fetch envelopes */
910
911 mailimap_fetch_type_free(fetch_type);
912 clist_free(msg_list);
913 return MAIL_NO_ERROR;
914 }
915
916 r = msg_list_to_imap_set(msg_list, &set);
917 if (r != MAIL_NO_ERROR) {
918 clist_foreach(msg_list, (clist_func) free, NULL);
919 clist_free(msg_list);
920 res = MAIL_ERROR_MEMORY;
921 goto free_fetch_type;
922 }
923 clist_foreach(msg_list, (clist_func) free, NULL);
924 clist_free(msg_list);
925
926 set_iter = clist_begin(set->set_list);
927 while (set_iter != NULL) {
928 struct mailimap_set * subset;
929 unsigned int count;
930
931 subset = mailimap_set_new_empty();
932 if (subset == NULL) {
933 res = MAIL_ERROR_MEMORY;
934 mailimap_fetch_type_free(fetch_type);
935 mailimap_set_free(set);
936 res = MAIL_ERROR_MEMORY;
937 goto err;
938 }
939
940 count = 0;
941 while (count < IMAP_SET_MAX_COUNT) {
942 struct mailimap_set_item * item;
943
944 item = clist_content(set_iter);
945 set_iter = clist_delete(set->set_list, set_iter);
946
947 r = mailimap_set_add(subset, item);
948 if (r != MAILIMAP_NO_ERROR) {
949 mailimap_set_item_free(item);
950 mailimap_set_free(subset);
951 mailimap_fetch_type_free(fetch_type);
952 mailimap_set_free(set);
953 res = MAIL_ERROR_MEMORY;
954 goto err;
955 }
956
957 count ++;
958
959 if (set_iter == NULL)
960 break;
961 }
962
963 r = mailimap_uid_fetch(get_imap_session(session), subset,
964 fetch_type, &fetch_result);
965
966 mailimap_set_free(subset);
967
968 switch (r) {
969 case MAILIMAP_NO_ERROR:
970 break;
971 default:
972 mailimap_fetch_type_free(fetch_type);
973 mailimap_set_free(set);
974 return imap_error_to_mail_error(r);
975 }
976
977 if (clist_begin(fetch_result) == NULL) {
978 res = MAIL_ERROR_FETCH;
979 goto err;
980 }
981
982 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
983 mailimap_fetch_list_free(fetch_result);
984
985 if (r != MAIL_NO_ERROR) {
986 mailimap_fetch_type_free(fetch_type);
987 mailimap_set_free(set);
988 res = MAIL_ERROR_MEMORY;
989 goto err;
990 }
991 }
992
993#if 0
994 r = mailimap_uid_fetch(get_imap_session(session), set,
995 fetch_type, &fetch_result);
996#endif
997
998 mailimap_fetch_type_free(fetch_type);
999 mailimap_set_free(set);
1000#if 0
1001 switch (r) {
1002 case MAILIMAP_NO_ERROR:
1003 break;
1004 default:
1005 return imap_error_to_mail_error(r);
1006 }
1007
1008 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
1009 mailimap_fetch_list_free(fetch_result);
1010
1011 if (r != MAIL_NO_ERROR) {
1012 res = MAIL_ERROR_MEMORY;
1013 goto err;
1014 }
1015#endif
1016
1017 return MAIL_NO_ERROR;
1018
1019 free_fetch_type:
1020 mailimap_fetch_type_free(fetch_type);
1021 err:
1022 return res;
1023}
1024
1025
1026#if 0
1027static int imapdriver_search_messages(mailsession * session, char * charset,
1028 struct mail_search_key * key,
1029 struct mail_search_result ** result)
1030{
1031 struct mailimap_search_key * imap_key;
1032 int r;
1033 clist * imap_result;
1034 clist * result_list;
1035 struct mail_search_result * search_result;
1036 clistiter * cur;
1037
1038 r = mail_search_to_imap_search(key, &imap_key);
1039 if (r != MAIL_NO_ERROR)
1040 return MAIL_ERROR_MEMORY;
1041
1042 r = mailimap_uid_search(get_imap_session(session), charset, imap_key,
1043 &imap_result);
1044
1045 mailimap_search_key_free(imap_key);
1046
1047 switch (r) {
1048 case MAILIMAP_NO_ERROR:
1049 break;
1050 default:
1051 return imap_error_to_mail_error(r);
1052 }
1053
1054 result_list = clist_new();
1055 if (result_list == NULL)
1056 return MAIL_ERROR_MEMORY;
1057
1058 for(cur = clist_begin(imap_result) ; cur != NULL ; cur = clist_next(cur)) {
1059 uint32_t val = * (uint32_t *) clist_content(cur);
1060 uint32_t * new;
1061
1062 new = malloc(sizeof(* new));
1063 if (new == NULL) {
1064 goto free_imap_result;
1065 }
1066
1067 * new = val;
1068
1069 r = clist_append(result_list, new);
1070 if (r != 0) {
1071 free(new);
1072 goto free_imap_result;
1073 }
1074 }
1075
1076 search_result = mail_search_result_new(result_list);
1077 if (search_result == NULL)
1078 goto free_imap_result;
1079
1080 mailimap_search_result_free(imap_result);
1081
1082 * result = search_result;
1083
1084 return MAIL_NO_ERROR;
1085
1086 free_imap_result:
1087 mailimap_search_result_free(imap_result);
1088 return MAIL_ERROR_MEMORY;
1089}
1090#endif
1091
1092static int imapdriver_starttls(mailsession * session)
1093{
1094 mailimap * imap;
1095 int r;
1096 struct mailimap_capability_data * cap_data;
1097 clistiter * cur;
1098 int starttls;
1099 int fd;
1100 mailstream_low * low;
1101 mailstream_low * new_low;
1102 int capability_available;
1103
1104 imap = get_imap_session(session);
1105
1106 capability_available = FALSE;
1107 if (imap->imap_connection_info != NULL)
1108 if (imap->imap_connection_info->imap_capability != NULL) {
1109 capability_available = TRUE;
1110 cap_data = imap->imap_connection_info->imap_capability;
1111 }
1112
1113 if (!capability_available) {
1114 r = mailimap_capability(imap, &cap_data);
1115 switch (r) {
1116 case MAILIMAP_NO_ERROR:
1117 break;
1118 default:
1119 return imap_error_to_mail_error(r);
1120 }
1121 }
1122
1123 starttls = FALSE;
1124 for(cur = clist_begin(cap_data->cap_list) ; cur != NULL ;
1125 cur = clist_next(cur)) {
1126 struct mailimap_capability * cap;
1127
1128 cap = clist_content(cur);
1129
1130 if (cap->cap_type == MAILIMAP_CAPABILITY_NAME)
1131 if (strcasecmp(cap->cap_data.cap_name, "STARTTLS") == 0) {
1132 starttls = TRUE;
1133 break;
1134 }
1135 }
1136
1137 if (!capability_available)
1138 mailimap_capability_data_free(cap_data);
1139
1140 if (!starttls)
1141 return MAIL_ERROR_NO_TLS;
1142
1143 r = mailimap_starttls(imap);
1144
1145 switch (r) {
1146 case MAILIMAP_NO_ERROR:
1147 break;
1148 default:
1149 return imap_error_to_mail_error(r);
1150 }
1151
1152 low = mailstream_get_low(imap->imap_stream);
1153 fd = mailstream_low_get_fd(low);
1154 if (fd == -1)
1155 return MAIL_ERROR_STREAM;
1156
1157 new_low = mailstream_low_ssl_open(fd);
1158 if (new_low == NULL)
1159 return MAIL_ERROR_STREAM;
1160
1161 mailstream_low_free(low);
1162 mailstream_set_low(imap->imap_stream, new_low);
1163
1164 return MAIL_NO_ERROR;
1165}
1166
1167static int imapdriver_get_message(mailsession * session,
1168 uint32_t num, mailmessage ** result)
1169{
1170 mailmessage * msg_info;
1171 int r;
1172
1173 msg_info = mailmessage_new();
1174 if (msg_info == NULL)
1175 return MAIL_ERROR_MEMORY;
1176
1177 r = mailmessage_init(msg_info, session, imap_message_driver, num, 0);
1178 if (r != MAIL_NO_ERROR) {
1179 mailmessage_free(msg_info);
1180 return r;
1181 }
1182
1183 * result = msg_info;
1184
1185 return MAIL_NO_ERROR;
1186}
1187
1188/* Retrieve a message by UID
1189
1190 libEtPan! uid format for IMAP is "UIDVALIDITY-UID"
1191 where UIDVALIDITY and UID are decimal representation of
1192 respectively uidvalidity and uid numbers.
1193
1194 Return value:
1195 MAIL_ERROR_INVAL if uid is NULL or has an incorrect format.
1196 MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found
1197 MAIL_NO_ERROR if message was found. Result is in result
1198*/
1199
1200static int imapdriver_get_message_by_uid(mailsession * session,
1201 const char * uid,
1202 mailmessage ** result)
1203{
1204 uint32_t uidvalidity;
1205 uint32_t num;
1206 char * p1, * p2;
1207 mailimap * imap;
1208
1209 if (uid == NULL)
1210 return MAIL_ERROR_INVAL;
1211
1212 uidvalidity = strtoul(uid, &p1, 10);
1213 if (p1 == uid || * p1 != '-')
1214 return MAIL_ERROR_INVAL;
1215
1216 p1++;
1217 num = strtoul(p1, &p2, 10);
1218 if (p2 == p1 || * p2 != '\0')
1219 return MAIL_ERROR_INVAL;
1220
1221 imap = get_imap_session(session);
1222 if (imap->imap_selection_info->sel_uidvalidity != uidvalidity)
1223 return MAIL_ERROR_MSG_NOT_FOUND;
1224
1225 return imapdriver_get_message(session, num, result);
1226}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver.h b/libetpan/src/driver/implementation/imap/imapdriver.h
new file mode 100644
index 0000000..cbc0c51
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_H
37
38#define IMAPDRIVER_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/imapdriver_types.h>
45
46extern mailsession_driver * imap_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached.c b/libetpan/src/driver/implementation/imap/imapdriver_cached.c
new file mode 100644
index 0000000..806b282
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached.c
@@ -0,0 +1,1370 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_cached.h"
37
38#include "libetpan-config.h"
39
40#include <stdio.h>
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <fcntl.h>
44#include <string.h>
45#include <unistd.h>
46#include <stdlib.h>
47
48#include "mail.h"
49#include "imapdriver_tools.h"
50#include "mail_cache_db.h"
51#include "mailmessage.h"
52#include "imapdriver_cached_message.h"
53#include "maildriver.h"
54#include "imapdriver_types.h"
55#include "generic_cache.h"
56#include "imfcache.h"
57#include "maildriver_tools.h"
58#include "imapdriver.h"
59
60static int imapdriver_cached_initialize(mailsession * session);
61static void imapdriver_cached_uninitialize(mailsession * session);
62
63static int imapdriver_cached_parameters(mailsession * session,
64 int id, void * value);
65
66static int imapdriver_cached_connect_stream(mailsession * session,
67 mailstream * s);
68
69static int imapdriver_cached_starttls(mailsession * session);
70
71static int imapdriver_cached_login(mailsession * session,
72 char * userid, char * password);
73static int imapdriver_cached_logout(mailsession * session);
74static int imapdriver_cached_noop(mailsession * session);
75static int imapdriver_cached_build_folder_name(mailsession * session,
76 char * mb,
77 char * name, char ** result);
78static int imapdriver_cached_create_folder(mailsession * session, char * mb);
79static int imapdriver_cached_delete_folder(mailsession * session, char * mb);
80static int imapdriver_cached_rename_folder(mailsession * session, char * mb,
81 char * new_name);
82static int imapdriver_cached_check_folder(mailsession * session);
83static int imapdriver_cached_examine_folder(mailsession * session,
84 char * mb);
85static int imapdriver_cached_select_folder(mailsession * session, char * mb);
86static int imapdriver_cached_expunge_folder(mailsession * session);
87static int imapdriver_cached_status_folder(mailsession * session, char * mb,
88 uint32_t * result_messages,
89 uint32_t * result_recent,
90 uint32_t * result_unseen);
91static int imapdriver_cached_messages_number(mailsession * session,
92 char * mb,
93 uint32_t * result);
94static int imapdriver_cached_recent_number(mailsession * session, char * mb,
95 uint32_t * result);
96static int imapdriver_cached_unseen_number(mailsession * session, char * mb,
97 uint32_t * result);
98static int imapdriver_cached_list_folders(mailsession * session, char * mb,
99 struct mail_list ** result);
100static int imapdriver_cached_lsub_folders(mailsession * session, char * mb,
101 struct mail_list ** result);
102static int imapdriver_cached_subscribe_folder(mailsession * session,
103 char * mb);
104static int imapdriver_cached_unsubscribe_folder(mailsession * session,
105 char * mb);
106static int imapdriver_cached_append_message(mailsession * session,
107 char * message, size_t size);
108static int imapdriver_cached_append_message_flags(mailsession * session,
109 char * message, size_t size, struct mail_flags * flags);
110static int imapdriver_cached_copy_message(mailsession * session,
111 uint32_t num, char * mb);
112
113static int imapdriver_cached_get_messages_list(mailsession * session,
114 struct mailmessage_list **
115 result);
116static int
117imapdriver_cached_get_envelopes_list(mailsession * session,
118 struct mailmessage_list * env_list);
119static int imapdriver_cached_remove_message(mailsession * session,
120 uint32_t num);
121
122#if 0
123static int imapdriver_cached_search_messages(mailsession * session,
124 char * charset,
125 struct mail_search_key * key,
126 struct mail_search_result **
127 result);
128#endif
129
130static int imapdriver_cached_get_message(mailsession * session,
131 uint32_t num, mailmessage ** result);
132
133static int imapdriver_cached_get_message_by_uid(mailsession * session,
134 const char * uid,
135 mailmessage ** result);
136
137static mailsession_driver local_imap_cached_session_driver = {
138 .sess_name = "imap-cached",
139
140 .sess_initialize = imapdriver_cached_initialize,
141 .sess_uninitialize = imapdriver_cached_uninitialize,
142
143 .sess_parameters = imapdriver_cached_parameters,
144
145 .sess_connect_stream = imapdriver_cached_connect_stream,
146 .sess_connect_path = NULL,
147 .sess_starttls = imapdriver_cached_starttls,
148 .sess_login = imapdriver_cached_login,
149 .sess_logout = imapdriver_cached_logout,
150 .sess_noop = imapdriver_cached_noop,
151
152 .sess_build_folder_name = imapdriver_cached_build_folder_name,
153 .sess_create_folder = imapdriver_cached_create_folder,
154 .sess_delete_folder = imapdriver_cached_delete_folder,
155 .sess_rename_folder = imapdriver_cached_rename_folder,
156 .sess_check_folder = imapdriver_cached_check_folder,
157 .sess_examine_folder = imapdriver_cached_examine_folder,
158 .sess_select_folder = imapdriver_cached_select_folder,
159 .sess_expunge_folder = imapdriver_cached_expunge_folder,
160 .sess_status_folder = imapdriver_cached_status_folder,
161 .sess_messages_number = imapdriver_cached_messages_number,
162 .sess_recent_number = imapdriver_cached_recent_number,
163 .sess_unseen_number = imapdriver_cached_unseen_number,
164 .sess_list_folders = imapdriver_cached_list_folders,
165 .sess_lsub_folders = imapdriver_cached_lsub_folders,
166 .sess_subscribe_folder = imapdriver_cached_subscribe_folder,
167 .sess_unsubscribe_folder = imapdriver_cached_unsubscribe_folder,
168
169 .sess_append_message = imapdriver_cached_append_message,
170 .sess_append_message_flags = imapdriver_cached_append_message_flags,
171 .sess_copy_message = imapdriver_cached_copy_message,
172 .sess_move_message = NULL,
173
174 .sess_get_messages_list = imapdriver_cached_get_messages_list,
175 .sess_get_envelopes_list = imapdriver_cached_get_envelopes_list,
176 .sess_remove_message = imapdriver_cached_remove_message,
177#if 0
178 .sess_search_messages = imapdriver_cached_search_messages,
179#endif
180
181 .sess_get_message = imapdriver_cached_get_message,
182 .sess_get_message_by_uid = imapdriver_cached_get_message_by_uid,
183};
184
185mailsession_driver * imap_cached_session_driver =
186&local_imap_cached_session_driver;
187
188#define CACHE_MESSAGE_LIST
189
190static inline struct imap_cached_session_state_data *
191get_cached_data(mailsession * session)
192{
193 return session->sess_data;
194}
195
196static inline mailsession * get_ancestor(mailsession * s)
197{
198 return get_cached_data(s)->imap_ancestor;
199}
200
201static inline
202struct imap_session_state_data * get_ancestor_data(mailsession * s)
203{
204 return get_ancestor(s)->sess_data;
205}
206
207static inline mailimap * get_imap_session(mailsession * session)
208{
209 return get_ancestor_data(session)->imap_session;
210}
211
212static int imapdriver_cached_initialize(mailsession * session)
213{
214 struct imap_cached_session_state_data * data;
215
216 data = malloc(sizeof(* data));
217 if (data == NULL)
218 goto err;
219
220 data->imap_ancestor = mailsession_new(imap_session_driver);
221 if (data->imap_ancestor == NULL)
222 goto free_data;
223 data->imap_quoted_mb = NULL;
224 data->imap_cache_directory[0] = '\0';
225 data->imap_uid_list = carray_new(128);
226 if (data->imap_uid_list == NULL)
227 goto free_session;
228
229 session->sess_data = data;
230
231 return MAIL_NO_ERROR;
232
233 free_session:
234 mailsession_free(data->imap_ancestor);
235 free_data:
236 free(data);
237 err:
238 return MAIL_ERROR_MEMORY;
239}
240
241static void
242free_quoted_mb(struct imap_cached_session_state_data * imap_cached_data)
243{
244 if (imap_cached_data->imap_quoted_mb != NULL) {
245 free(imap_cached_data->imap_quoted_mb);
246 imap_cached_data->imap_quoted_mb = NULL;
247 }
248}
249
250struct uid_cache_item {
251 uint32_t uid;
252 uint32_t size;
253};
254
255static int update_uid_cache(mailsession * session,
256 struct mailmessage_list * env_list)
257{
258 unsigned int i;
259 int r;
260 struct imap_cached_session_state_data * data;
261 int res;
262
263 data = get_cached_data(session);
264
265 /* free all UID cache */
266 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
267 struct uid_cache_item * cache_item;
268
269 cache_item = carray_get(data->imap_uid_list, i);
270 free(cache_item);
271 }
272
273 /* build UID cache */
274 r = carray_set_size(data->imap_uid_list,
275 carray_count(env_list->msg_tab));
276 if (r < 0) {
277 res = MAIL_ERROR_MEMORY;
278 goto err;
279 }
280
281 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
282 struct uid_cache_item * cache_item;
283 mailmessage * msg;
284
285 cache_item = malloc(sizeof(* cache_item));
286 if (cache_item == NULL) {
287 res = MAIL_ERROR_MEMORY;
288 goto err;
289 }
290 msg = carray_get(env_list->msg_tab, i);
291 cache_item->uid = msg->msg_index;
292 cache_item->size = msg->msg_size;
293
294 carray_set(data->imap_uid_list, i, cache_item);
295 }
296
297 return MAIL_NO_ERROR;
298
299 err:
300 return res;
301}
302
303static void check_for_uid_cache(mailsession * session)
304{
305#if 0
306 mailsession * imap;
307#endif
308 mailimap * imap;
309#if 0
310 struct imap_session_state_data * imap_data;
311#endif
312 clist * list;
313 clistiter * cur;
314 struct imap_cached_session_state_data * data;
315 unsigned int i;
316 unsigned dest;
317
318 data = get_cached_data(session);
319#if 0
320 imap = get_ancestor(session);
321
322 imap_data = imap->data;
323#endif
324
325 imap = get_imap_session(session);
326
327 if (imap->imap_response_info == NULL)
328 return;
329
330 list = imap->imap_response_info->rsp_expunged;
331 if (list == NULL)
332 return;
333
334 dest = 0;
335 i = 0;
336 /* remove expunged */
337 for(cur = clist_begin(list) ; cur != NULL ; cur = clist_next(cur)) {
338 uint32_t expunged;
339
340 expunged = * (uint32_t *) clist_content(cur);
341
342 while (i < carray_count(data->imap_uid_list)) {
343 struct uid_cache_item * cache_item;
344
345 if (dest + 1 == expunged) {
346 cache_item = carray_get(data->imap_uid_list, i);
347 free(cache_item);
348 i ++;
349 break;
350 }
351 else {
352 cache_item = carray_get(data->imap_uid_list, i);
353 carray_set(data->imap_uid_list, dest, cache_item);
354 i ++;
355 dest ++;
356 }
357 }
358 }
359 /* complete list */
360 while (i < carray_count(data->imap_uid_list)) {
361 struct uid_cache_item * cache_item;
362
363 cache_item = carray_get(data->imap_uid_list, i);
364 carray_set(data->imap_uid_list, dest, cache_item);
365 i ++;
366 dest ++;
367 }
368 carray_set_size(data->imap_uid_list, dest);
369}
370
371static void imapdriver_cached_uninitialize(mailsession * session)
372{
373 struct imap_cached_session_state_data * data;
374 unsigned int i;
375
376 data = get_cached_data(session);
377
378 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
379 struct uid_cache_item * cache_item;
380
381 cache_item = carray_get(data->imap_uid_list, i);
382 free(cache_item);
383 }
384 carray_free(data->imap_uid_list);
385 free_quoted_mb(data);
386 mailsession_free(data->imap_ancestor);
387 free(data);
388
389 session->sess_data = NULL;
390}
391
392
393static int imapdriver_cached_parameters(mailsession * session,
394 int id, void * value)
395{
396 struct imap_cached_session_state_data * data;
397 int r;
398
399 data = get_cached_data(session);
400
401 switch (id) {
402 case IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY:
403 strncpy(data->imap_cache_directory, value, PATH_MAX);
404 data->imap_cache_directory[PATH_MAX - 1] = '\0';
405
406 r = generic_cache_create_dir(data->imap_cache_directory);
407 if (r != MAIL_NO_ERROR)
408 return r;
409
410 return MAIL_NO_ERROR;
411 }
412
413 return MAIL_ERROR_INVAL;
414}
415
416
417static int imapdriver_cached_connect_stream(mailsession * session,
418 mailstream * s)
419{
420 int r;
421
422 check_for_uid_cache(session);
423
424 r = mailsession_connect_stream(get_ancestor(session), s);
425
426 check_for_uid_cache(session);
427
428 return r;
429}
430
431static int imapdriver_cached_starttls(mailsession * session)
432{
433 int r;
434
435 r = mailsession_starttls(get_ancestor(session));
436
437 check_for_uid_cache(session);
438
439 return r;
440}
441
442static int imapdriver_cached_login(mailsession * session,
443 char * userid, char * password)
444{
445 int r;
446
447 r = mailsession_login(get_ancestor(session), userid, password);
448
449 check_for_uid_cache(session);
450
451 return r;
452}
453
454static int imapdriver_cached_logout(mailsession * session)
455{
456 int r;
457
458 r = mailsession_logout(get_ancestor(session));
459
460 check_for_uid_cache(session);
461
462 if (r == MAIL_NO_ERROR) {
463 struct imap_cached_session_state_data * imap_cached_data;
464
465 imap_cached_data = get_cached_data(session);
466
467 free_quoted_mb(imap_cached_data);
468 }
469
470 return r;
471}
472
473static int imapdriver_cached_noop(mailsession * session)
474{
475 int r;
476
477 r = mailsession_noop(get_ancestor(session));
478
479 check_for_uid_cache(session);
480
481 return r;
482}
483
484static int imapdriver_cached_build_folder_name(mailsession * session,
485 char * mb,
486 char * name, char ** result)
487{
488 int r;
489
490 r = mailsession_build_folder_name(get_ancestor(session), mb,
491 name, result);
492
493 check_for_uid_cache(session);
494
495 return r;
496}
497
498static int imapdriver_cached_create_folder(mailsession * session, char * mb)
499{
500 int r;
501
502 r = mailsession_create_folder(get_ancestor(session), mb);
503
504 check_for_uid_cache(session);
505
506 return r;
507}
508
509static int imapdriver_cached_delete_folder(mailsession * session, char * mb)
510{
511 int r;
512
513 r = mailsession_delete_folder(get_ancestor(session), mb);
514
515 check_for_uid_cache(session);
516
517 return r;
518}
519
520static int imapdriver_cached_rename_folder(mailsession * session, char * mb,
521 char * new_name)
522{
523 int r;
524
525 r = mailsession_rename_folder(get_ancestor(session), mb, new_name);
526
527 check_for_uid_cache(session);
528
529 return r;
530}
531
532static int imapdriver_cached_check_folder(mailsession * session)
533{
534 int r;
535
536 r = mailsession_check_folder(get_ancestor(session));
537
538 check_for_uid_cache(session);
539
540 return r;
541}
542
543static int imapdriver_cached_examine_folder(mailsession * session,
544 char * mb)
545{
546 int r;
547
548 r = mailsession_examine_folder(get_ancestor(session), mb);
549
550 check_for_uid_cache(session);
551
552 return r;
553}
554
555static int get_cache_folder(mailsession * session, char ** result)
556{
557#if 0
558 mailsession * imap_session;
559#endif
560 mailimap * imap;
561 char * mb;
562 char * cache_dir;
563 char * dirname;
564 char * quoted_mb;
565 int res;
566 int r;
567 char key[PATH_MAX];
568#if 0
569 struct imap_session_state_data * imap_data;
570 struct imap_cached_session_state_data * cached_data;
571#endif
572
573#if 0
574 imap_session = get_ancestor(session);
575 imap_data = imap_session->data;
576 imap = imap_data->session;
577#endif
578 imap = get_imap_session(session);
579
580 mb = get_ancestor_data(session)->imap_mailbox;
581
582 cache_dir = get_cached_data(session)->imap_cache_directory;
583
584 if (imap->imap_state != MAILIMAP_STATE_SELECTED)
585 return MAIL_ERROR_BAD_STATE;
586
587 if (imap->imap_selection_info == NULL)
588 return MAIL_ERROR_BAD_STATE;
589
590 quoted_mb = maildriver_quote_mailbox(mb);
591 if (quoted_mb == NULL) {
592 res = MAIL_ERROR_MEMORY;
593 goto err;
594 }
595
596 snprintf(key, PATH_MAX, "%s/%s", cache_dir, quoted_mb);
597
598 dirname = strdup(key);
599 if (dirname == NULL) {
600 res = MAIL_ERROR_MEMORY;
601 goto free_mb;
602 }
603
604 r = generic_cache_create_dir(dirname);
605 if (r != MAIL_NO_ERROR) {
606 res = r;
607 goto free_dirname;
608 }
609
610 free(quoted_mb);
611
612 * result = dirname;
613
614 return MAIL_NO_ERROR;
615
616 free_dirname:
617 free(dirname);
618 free_mb:
619 free(quoted_mb);
620 err:
621 return res;
622}
623
624static int imapdriver_cached_select_folder(mailsession * session, char * mb)
625{
626 int r;
627 char * quoted_mb;
628 struct imap_cached_session_state_data * data;
629 mailsession * imap;
630 char * old_mb;
631
632 imap = get_ancestor(session);
633
634 old_mb = get_ancestor_data(session)->imap_mailbox;
635 if (old_mb != NULL)
636 if (strcmp(mb, old_mb) == 0)
637 return MAIL_NO_ERROR;
638
639 r = mailsession_select_folder(get_ancestor(session), mb);
640 if (r != MAIL_NO_ERROR)
641 return r;
642
643 check_for_uid_cache(session);
644
645 r = get_cache_folder(session, &quoted_mb);
646 if (r != MAIL_NO_ERROR)
647 return r;
648
649 data = get_cached_data(session);
650 if (data->imap_quoted_mb != NULL)
651 free(data->imap_quoted_mb);
652 data->imap_quoted_mb = quoted_mb;
653
654 /* clear UID cache */
655 carray_set_size(data->imap_uid_list, 0);
656
657 return MAIL_NO_ERROR;
658}
659
660static int imapdriver_cached_expunge_folder(mailsession * session)
661{
662 int r;
663
664 r = mailsession_expunge_folder(get_ancestor(session));
665
666 check_for_uid_cache(session);
667
668 return r;
669}
670
671static int imapdriver_cached_status_folder(mailsession * session, char * mb,
672 uint32_t * result_messages, uint32_t * result_recent,
673 uint32_t * result_unseen)
674{
675 int r;
676
677 r = mailsession_status_folder(get_ancestor(session), mb, result_messages,
678 result_recent, result_unseen);
679
680 check_for_uid_cache(session);
681
682 return r;
683}
684
685static int imapdriver_cached_messages_number(mailsession * session,
686 char * mb,
687 uint32_t * result)
688{
689 int r;
690
691 r = mailsession_messages_number(get_ancestor(session), mb, result);
692
693 check_for_uid_cache(session);
694
695 return r;
696}
697
698static int imapdriver_cached_recent_number(mailsession * session, char * mb,
699 uint32_t * result)
700{
701 int r;
702
703 r = mailsession_recent_number(get_ancestor(session), mb, result);
704
705 check_for_uid_cache(session);
706
707 return r;
708}
709
710static int imapdriver_cached_unseen_number(mailsession * session, char * mb,
711 uint32_t * result)
712{
713 int r;
714
715 r = mailsession_unseen_number(get_ancestor(session), mb, result);
716
717 check_for_uid_cache(session);
718
719 return r;
720}
721
722static int imapdriver_cached_list_folders(mailsession * session, char * mb,
723 struct mail_list ** result)
724{
725 int r;
726
727 r = mailsession_list_folders(get_ancestor(session), mb, result);
728
729 check_for_uid_cache(session);
730
731 return r;
732}
733
734static int imapdriver_cached_lsub_folders(mailsession * session, char * mb,
735 struct mail_list ** result)
736{
737 int r;
738
739 r = mailsession_lsub_folders(get_ancestor(session), mb, result);
740
741 check_for_uid_cache(session);
742
743 return r;
744}
745
746static int imapdriver_cached_subscribe_folder(mailsession * session,
747 char * mb)
748{
749 int r;
750
751 r = mailsession_subscribe_folder(get_ancestor(session), mb);
752
753 check_for_uid_cache(session);
754
755 return r;
756}
757
758static int imapdriver_cached_unsubscribe_folder(mailsession * session,
759 char * mb)
760{
761 int r;
762
763 r = mailsession_unsubscribe_folder(get_ancestor(session), mb);
764
765 check_for_uid_cache(session);
766
767 return r;
768}
769
770static int imapdriver_cached_append_message(mailsession * session,
771 char * message, size_t size)
772{
773 int r;
774
775 r = mailsession_append_message(get_ancestor(session), message, size);
776
777 check_for_uid_cache(session);
778
779 return r;
780}
781
782static int imapdriver_cached_append_message_flags(mailsession * session,
783 char * message, size_t size, struct mail_flags * flags)
784{
785 int r;
786
787 r = mailsession_append_message_flags(get_ancestor(session),
788 message, size, flags);
789
790 check_for_uid_cache(session);
791
792 return r;
793}
794
795static int imapdriver_cached_copy_message(mailsession * session,
796 uint32_t num, char * mb)
797{
798 int r;
799
800 r = mailsession_copy_message(get_ancestor(session), num, mb);
801
802 check_for_uid_cache(session);
803
804 return r;
805}
806
807static int cmp_uid(uint32_t ** pa, uint32_t ** pb)
808{
809 uint32_t * a;
810 uint32_t * b;
811
812 a = * pa;
813 b = * pb;
814
815 return * a - * b;
816}
817
818
819static int imapdriver_cached_get_messages_list(mailsession * session,
820 struct mailmessage_list **
821 result)
822{
823#if 0
824 mailsession * imap_session;
825#endif
826 mailimap * imap;
827 uint32_t uid_max;
828 struct imap_cached_session_state_data * data;
829 struct mailmessage_list * env_list;
830 unsigned i;
831 int r;
832 int res;
833 carray * tab;
834
835#if 0
836 data = session->data;
837 imap_session = get_ancestor(session);
838 imap = ((struct imap_session_state_data *) (imap_session->data))->session;
839#endif
840 data = get_cached_data(session);
841 imap = get_imap_session(session);
842
843 uid_max = 0;
844
845#ifdef CACHE_MESSAGE_LIST
846 /* get UID max */
847 uid_max = 0;
848 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
849 struct uid_cache_item * cache_item;
850
851 cache_item = carray_get(data->imap_uid_list, i);
852 if (cache_item->uid > uid_max)
853 uid_max = cache_item->uid;
854 }
855#endif
856
857 r = imap_get_messages_list(imap, session, imap_cached_message_driver,
858 uid_max + 1, &env_list);
859
860 check_for_uid_cache(session);
861
862 if (r != MAIL_NO_ERROR) {
863 res = r;
864 goto err;
865 }
866
867#ifdef CACHE_MESSAGE_LIST
868 /* remove unsollicited message */
869 i = 0;
870 while (i < carray_count(env_list->msg_tab)) {
871 mailmessage * msg;
872
873 msg = carray_get(env_list->msg_tab, i);
874 if (msg->msg_index < uid_max + 1) {
875 mailmessage * msg;
876
877 msg = carray_get(env_list->msg_tab, i);
878 mailmessage_free(msg);
879 carray_delete(env_list->msg_tab, i);
880 }
881 else {
882 i ++;
883 }
884 }
885
886 tab = carray_new(carray_count(env_list->msg_tab) +
887 carray_count(data->imap_uid_list));
888 if (tab == NULL) {
889 res = MAIL_ERROR_MEMORY;
890 goto free;
891 }
892 carray_set_size(tab,
893 carray_count(env_list->msg_tab) + carray_count(data->imap_uid_list));
894
895 /* sort cached data before adding them to the list */
896 qsort(carray_data(data->imap_uid_list), carray_count(data->imap_uid_list),
897 sizeof(* carray_data(data->imap_uid_list)),
898 (int (*)(const void *, const void *)) cmp_uid);
899
900 /* adds cached UID */
901 for(i = 0 ; i < carray_count(data->imap_uid_list) ; i ++) {
902 struct uid_cache_item * cache_item;
903 mailmessage * msg;
904
905 cache_item = carray_get(data->imap_uid_list, i);
906
907 msg = mailmessage_new();
908 if (msg == NULL) {
909 res = MAIL_ERROR_MEMORY;
910 goto free;
911 }
912
913 r = mailmessage_init(msg, session, imap_cached_message_driver,
914 cache_item->uid, cache_item->size);
915 if (r != MAIL_NO_ERROR) {
916 mailmessage_free(msg);
917 res = r;
918 goto free;
919 }
920
921 carray_set(tab, i, msg);
922 }
923
924 /* adds new elements */
925 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
926 mailmessage * msg;
927
928 msg = carray_get(env_list->msg_tab, i);
929 carray_set(tab, carray_count(data->imap_uid_list) + i, msg);
930 }
931
932 /* replace list of messages in env_list */
933 carray_free(env_list->msg_tab);
934 env_list->msg_tab = tab;
935
936 r = update_uid_cache(session, env_list);
937 if (r != MAIL_NO_ERROR) {
938 res = r;
939 goto free;
940 }
941#endif
942
943 * result = env_list;
944
945 return MAIL_NO_ERROR;
946
947 free:
948 mailmessage_list_free(env_list);
949 err:
950 return res;
951}
952
953#define IMAP_SET_MAX_COUNT 100
954
955static int get_flags_list(mailsession * session,
956 struct mailmessage_list * env_list)
957{
958 struct mailimap_set * set;
959 struct mailimap_fetch_att * fetch_att;
960 struct mailimap_fetch_type * fetch_type;
961 int res;
962 clist * fetch_result;
963 int r;
964 clist * msg_list;
965#if 0
966 struct imap_session_state_data * data;
967#endif
968 unsigned i;
969 unsigned dest;
970 clistiter * set_iter;
971
972#if 0
973 data = session->data;
974#endif
975
976 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
977 if (fetch_type == NULL) {
978 res = MAIL_ERROR_MEMORY;
979 goto err;
980 }
981
982 fetch_att = mailimap_fetch_att_new_uid();
983 if (fetch_att == NULL) {
984 res = MAIL_ERROR_MEMORY;
985 goto free_fetch_type;
986 }
987
988 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
989 if (r != MAILIMAP_NO_ERROR) {
990 mailimap_fetch_att_free(fetch_att);
991 res = MAIL_ERROR_MEMORY;
992 goto free_fetch_type;
993 }
994
995 fetch_att = mailimap_fetch_att_new_flags();
996 if (fetch_att == NULL) {
997 res = MAIL_ERROR_MEMORY;
998 goto free_fetch_type;
999 }
1000
1001 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1002 if (r != MAILIMAP_NO_ERROR) {
1003 mailimap_fetch_att_free(fetch_att);
1004 res = MAIL_ERROR_MEMORY;
1005 goto free_fetch_type;
1006 }
1007
1008 r = maildriver_env_list_to_msg_list_no_flags(env_list, &msg_list);
1009 if (r != MAIL_NO_ERROR) {
1010 res = MAIL_ERROR_MEMORY;
1011 goto free_fetch_type;
1012 }
1013
1014 if (clist_begin(msg_list) == NULL) {
1015 /* no need to fetch envelopes */
1016
1017 clist_free(msg_list);
1018 mailimap_fetch_type_free(fetch_type);
1019 return MAIL_NO_ERROR;
1020 }
1021
1022 r = msg_list_to_imap_set(msg_list, &set);
1023 if (r != MAIL_NO_ERROR) {
1024 clist_foreach(msg_list, (clist_func) free, NULL);
1025 clist_free(msg_list);
1026 res = MAIL_ERROR_MEMORY;
1027 goto free_fetch_type;
1028 }
1029 clist_foreach(msg_list, (clist_func) free, NULL);
1030 clist_free(msg_list);
1031
1032 set_iter = clist_begin(set->set_list);
1033 while (set_iter != NULL) {
1034 struct mailimap_set * subset;
1035 unsigned int count;
1036
1037 subset = mailimap_set_new_empty();
1038 if (subset == NULL) {
1039 res = MAIL_ERROR_MEMORY;
1040 mailimap_fetch_type_free(fetch_type);
1041 mailimap_set_free(set);
1042 res = MAIL_ERROR_MEMORY;
1043 goto err;
1044 }
1045
1046 count = 0;
1047 while (count < IMAP_SET_MAX_COUNT) {
1048 struct mailimap_set_item * item;
1049
1050 item = clist_content(set_iter);
1051 set_iter = clist_delete(set->set_list, set_iter);
1052
1053 r = mailimap_set_add(subset, item);
1054 if (r != MAILIMAP_NO_ERROR) {
1055 mailimap_set_item_free(item);
1056 mailimap_set_free(subset);
1057 mailimap_fetch_type_free(fetch_type);
1058 mailimap_set_free(set);
1059 res = MAIL_ERROR_MEMORY;
1060 goto err;
1061 }
1062
1063 count ++;
1064
1065 if (set_iter == NULL)
1066 break;
1067 }
1068
1069 r = mailimap_uid_fetch(get_imap_session(session), subset,
1070 fetch_type, &fetch_result);
1071
1072 mailimap_set_free(subset);
1073
1074 switch (r) {
1075 case MAILIMAP_NO_ERROR:
1076 break;
1077 default:
1078 mailimap_fetch_type_free(fetch_type);
1079 mailimap_set_free(set);
1080 return imap_error_to_mail_error(r);
1081 }
1082
1083 if (clist_begin(fetch_result) == NULL) {
1084 res = MAIL_ERROR_FETCH;
1085 goto err;
1086 }
1087
1088 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
1089 mailimap_fetch_list_free(fetch_result);
1090
1091 if (r != MAIL_NO_ERROR) {
1092 mailimap_fetch_type_free(fetch_type);
1093 mailimap_set_free(set);
1094 res = MAIL_ERROR_MEMORY;
1095 goto err;
1096 }
1097 }
1098
1099#if 0
1100 r = mailimap_uid_fetch(get_imap_session(session), set,
1101 fetch_type, &fetch_result);
1102#endif
1103
1104 mailimap_fetch_type_free(fetch_type);
1105 mailimap_set_free(set);
1106
1107#if 0
1108 switch (r) {
1109 case MAILIMAP_NO_ERROR:
1110 break;
1111 default:
1112 return imap_error_to_mail_error(r);
1113 }
1114
1115 r = imap_fetch_result_to_envelop_list(fetch_result, env_list);
1116 mailimap_fetch_list_free(fetch_result);
1117
1118 if (r != MAIL_NO_ERROR) {
1119 res = MAIL_ERROR_MEMORY;
1120 goto err;
1121 }
1122#endif
1123
1124 /* remove messages that don't have flags */
1125 i = 0;
1126 dest = 0;
1127 while (i < carray_count(env_list->msg_tab)) {
1128 mailmessage * msg;
1129
1130 msg = carray_get(env_list->msg_tab, i);
1131 if (msg->msg_flags != NULL) {
1132 carray_set(env_list->msg_tab, dest, msg);
1133 dest ++;
1134 }
1135 else {
1136 mailmessage_free(msg);
1137 }
1138 i ++;
1139 }
1140 carray_set_size(env_list->msg_tab, dest);
1141
1142 return MAIL_NO_ERROR;
1143
1144 free_fetch_type:
1145 mailimap_fetch_type_free(fetch_type);
1146 err:
1147 return res;
1148}
1149
1150
1151#define ENV_NAME "env.db"
1152
1153static void get_uid_from_filename(char * filename)
1154{
1155 char * p;
1156
1157 p = strstr(filename, "-part");
1158 if (p != NULL)
1159 * p = 0;
1160 p = strstr(filename, "-envelope");
1161 if (p != NULL)
1162 * p = 0;
1163 p = strstr(filename, "-rfc822");
1164 if (p != NULL)
1165 * p = 0;
1166}
1167
1168static int
1169imapdriver_cached_get_envelopes_list(mailsession * session,
1170 struct mailmessage_list * env_list)
1171{
1172 int r;
1173 int res;
1174 uint32_t i;
1175 struct imap_cached_session_state_data * data;
1176 MMAPString * mmapstr;
1177 struct mail_cache_db * cache_db;
1178 char filename[PATH_MAX];
1179
1180 data = get_cached_data(session);
1181 if (data->imap_quoted_mb == NULL) {
1182 res = MAIL_ERROR_BAD_STATE;
1183 goto err;
1184 }
1185
1186 mmapstr = mmap_string_new("");
1187 if (mmapstr == NULL) {
1188 res = MAIL_ERROR_MEMORY;
1189 goto err;
1190 }
1191
1192 snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME);
1193
1194 r = mail_cache_db_open_lock(filename, &cache_db);
1195 if (r < 0) {
1196 res = MAIL_ERROR_MEMORY;
1197 goto free_mmapstr;
1198 }
1199
1200 /* fill with cached */
1201
1202 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1203 mailmessage * msg;
1204 struct mailimf_fields * fields;
1205
1206 msg = carray_get(env_list->msg_tab, i);
1207
1208 if (msg->msg_fields == NULL) {
1209 r = imapdriver_get_cached_envelope(cache_db, mmapstr,
1210 session, msg, &fields);
1211 if (r == MAIL_NO_ERROR) {
1212 msg->msg_cached = TRUE;
1213 msg->msg_fields = fields;
1214 }
1215 }
1216 }
1217
1218 mail_cache_db_close_unlock(filename, cache_db);
1219
1220 r = mailsession_get_envelopes_list(get_ancestor(session), env_list);
1221
1222 check_for_uid_cache(session);
1223
1224 if (r != MAIL_NO_ERROR) {
1225 res = r;
1226 goto free_mmapstr;
1227 }
1228
1229 r = get_flags_list(session, env_list);
1230
1231 if (r != MAIL_NO_ERROR) {
1232 res = r;
1233 goto free_mmapstr;
1234 }
1235
1236#ifdef CACHE_MESSAGE_LIST
1237 r = update_uid_cache(session, env_list);
1238 if (r != MAIL_NO_ERROR) {
1239 res = r;
1240 goto free_mmapstr;
1241 }
1242#endif
1243
1244 /* must write cache */
1245
1246 r = mail_cache_db_open_lock(filename, &cache_db);
1247 if (r < 0) {
1248 res = MAIL_ERROR_MEMORY;
1249 goto free_mmapstr;
1250 }
1251
1252 for(i = 0 ; i < carray_count(env_list->msg_tab) ; i ++) {
1253 mailmessage * msg;
1254
1255 msg = carray_get(env_list->msg_tab, i);
1256
1257 if (msg->msg_fields != NULL) {
1258 if (!msg->msg_cached) {
1259 r = imapdriver_write_cached_envelope(cache_db, mmapstr,
1260 session, msg, msg->msg_fields);
1261 }
1262 }
1263 }
1264
1265 /* flush cache */
1266
1267 maildriver_cache_clean_up(cache_db, NULL, env_list);
1268
1269 mail_cache_db_close_unlock(filename, cache_db);
1270 mmap_string_free(mmapstr);
1271
1272 /* remove cache files */
1273
1274 maildriver_message_cache_clean_up(data->imap_quoted_mb, env_list,
1275 get_uid_from_filename);
1276
1277 return MAIL_NO_ERROR;
1278
1279 free_mmapstr:
1280 mmap_string_free(mmapstr);
1281 err:
1282 return res;
1283}
1284
1285static int imapdriver_cached_remove_message(mailsession * session,
1286 uint32_t num)
1287{
1288 int r;
1289
1290 r = mailsession_remove_message(get_ancestor(session), num);
1291
1292 check_for_uid_cache(session);
1293
1294 return r;
1295}
1296
1297#if 0
1298static int imapdriver_cached_search_messages(mailsession * session,
1299 char * charset,
1300 struct mail_search_key * key,
1301 struct mail_search_result **
1302 result)
1303{
1304 int r;
1305
1306 r = mailsession_search_messages(get_ancestor(session), charset, key, result);
1307
1308 check_for_uid_cache(session);
1309
1310 return r;
1311}
1312#endif
1313
1314static int imapdriver_cached_get_message(mailsession * session,
1315 uint32_t num, mailmessage ** result)
1316{
1317 mailmessage * msg_info;
1318 int r;
1319
1320 msg_info = mailmessage_new();
1321 if (msg_info == NULL)
1322 return MAIL_ERROR_MEMORY;
1323
1324 r = mailmessage_init(msg_info, session, imap_cached_message_driver, num, 0);
1325 if (r != MAIL_NO_ERROR) {
1326 mailmessage_free(msg_info);
1327 return r;
1328 }
1329
1330 * result = msg_info;
1331
1332 return MAIL_NO_ERROR;
1333}
1334
1335/* Retrieve a message by UID
1336 * libEtPan! uid format for IMAP is "UIDVALIDITY-UID"
1337 * where UIDVALIDITY and UID are decimal representation of
1338 * respectively uidvalidity and uid numbers.
1339 * Return value:
1340 * MAIL_ERROR_INVAL if uid is NULL or has an incorrect format.
1341 * MAIL_ERROR_MSG_NOT_FOUND if uidvalidity has changed or uid was not found
1342 * MAIL_NO_ERROR if message was found. Result is in result
1343 */
1344static int imapdriver_cached_get_message_by_uid(mailsession * session,
1345 const char * uid,
1346 mailmessage ** result)
1347{
1348 uint32_t uidvalidity;
1349 uint32_t num;
1350 char * p1, * p2;
1351 mailimap *imap;
1352
1353 if (uid == NULL)
1354 return MAIL_ERROR_INVAL;
1355
1356 uidvalidity = strtoul(uid, &p1, 10);
1357 if (p1 == uid || * p1 != '-')
1358 return MAIL_ERROR_INVAL;
1359
1360 p1++;
1361 num = strtoul(p1, &p2, 10);
1362 if (p2 == p1 || * p2 != '\0')
1363 return MAIL_ERROR_INVAL;
1364
1365 imap = get_imap_session(session);
1366 if (imap->imap_selection_info->sel_uidvalidity != uidvalidity)
1367 return MAIL_ERROR_MSG_NOT_FOUND;
1368
1369 return imapdriver_cached_get_message(session, num, result);
1370}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached.h b/libetpan/src/driver/implementation/imap/imapdriver_cached.h
new file mode 100644
index 0000000..c324f5e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_CACHED_H
37
38#define IMAPDRIVER_CACHED_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailsession_driver * imap_cached_session_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c
new file mode 100644
index 0000000..34e1ca3
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.c
@@ -0,0 +1,664 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_cached_message.h"
37
38#include "imapdriver_tools.h"
39#include "imapdriver_message.h"
40#include "imapdriver_cached.h"
41#include "imapdriver_types.h"
42#include "imapdriver.h"
43#include "mailmessage.h"
44#include "generic_cache.h"
45#include "mail_cache_db.h"
46
47#include <string.h>
48#include <stdlib.h>
49
50static int imap_initialize(mailmessage * msg_info);
51
52static void imap_uninitialize(mailmessage * msg_info);
53
54static void imap_flush(mailmessage * msg_info);
55
56static void imap_check(mailmessage * msg_info);
57
58static void imap_fetch_result_free(mailmessage * msg_info,
59 char * msg);
60
61static int imap_fetch(mailmessage * msg_info,
62 char ** result,
63 size_t * result_len);
64
65static int imap_fetch_header(mailmessage * msg_info,
66 char ** result,
67 size_t * result_len);
68
69static int imap_fetch_body(mailmessage * msg_info,
70 char ** result, size_t * result_len);
71
72static int imap_fetch_size(mailmessage * msg_info,
73 size_t * result);
74
75static int imap_get_bodystructure(mailmessage * msg_info,
76 struct mailmime ** result);
77
78static int imap_fetch_section(mailmessage * msg_info,
79 struct mailmime * mime,
80 char ** result, size_t * result_len);
81
82static int imap_fetch_section_header(mailmessage * msg_info,
83 struct mailmime * mime,
84 char ** result,
85 size_t * result_len);
86
87static int imap_fetch_section_mime(mailmessage * msg_info,
88 struct mailmime * mime,
89 char ** result,
90 size_t * result_len);
91
92static int imap_fetch_section_body(mailmessage * msg_info,
93 struct mailmime * mime,
94 char ** result,
95 size_t * result_len);
96
97
98static int imap_fetch_envelope(mailmessage * msg_info,
99 struct mailimf_fields ** result);
100
101static int imap_get_flags(mailmessage * msg_info,
102 struct mail_flags ** result);
103
104static mailmessage_driver local_imap_cached_message_driver = {
105 .msg_name = "imap-cached",
106
107 .msg_initialize = imap_initialize,
108 .msg_uninitialize = imap_uninitialize,
109
110 .msg_flush = imap_flush,
111 .msg_check = imap_check,
112
113 .msg_fetch_result_free = imap_fetch_result_free,
114
115 .msg_fetch = imap_fetch,
116 .msg_fetch_header = imap_fetch_header,
117 .msg_fetch_body = imap_fetch_body,
118 .msg_fetch_size = imap_fetch_size,
119 .msg_get_bodystructure = imap_get_bodystructure,
120 .msg_fetch_section = imap_fetch_section,
121 .msg_fetch_section_header = imap_fetch_section_header,
122 .msg_fetch_section_mime = imap_fetch_section_mime,
123 .msg_fetch_section_body = imap_fetch_section_body,
124 .msg_fetch_envelope = imap_fetch_envelope,
125
126 .msg_get_flags = imap_get_flags,
127};
128
129mailmessage_driver * imap_cached_message_driver =
130&local_imap_cached_message_driver;
131
132static inline struct imap_cached_session_state_data *
133get_cached_session_data(mailmessage * msg)
134{
135 return msg->msg_session->sess_data;
136}
137
138static inline mailmessage * get_ancestor(mailmessage * msg_info)
139{
140 return msg_info->msg_data;
141}
142
143static inline struct imap_cached_session_state_data *
144cached_session_get_data(mailsession * s)
145{
146 return s->sess_data;
147}
148
149static inline mailsession * cached_session_get_ancestor(mailsession * s)
150{
151 return cached_session_get_data(s)->imap_ancestor;
152}
153
154static inline struct imap_session_state_data *
155cached_session_get_ancestor_data(mailsession * s)
156{
157 return cached_session_get_ancestor(s)->sess_data;
158}
159
160static inline mailimap *
161cached_session_get_imap_session(mailsession * session)
162{
163 return cached_session_get_ancestor_data(session)->imap_session;
164}
165
166static inline mailimap * get_imap_session(mailmessage * msg)
167{
168 return cached_session_get_imap_session(msg->msg_session);
169}
170
171static inline mailsession * get_ancestor_session(mailmessage * msg_info)
172{
173 return cached_session_get_ancestor(msg_info->msg_session);
174}
175
176
177static void generate_key_from_mime_section(char * key, size_t size,
178 struct mailmime * mime)
179{
180 clistiter * cur;
181 MMAPString * gstr;
182 struct mailmime_section * part;
183 int r;
184
185 snprintf(key, size, "unvalid");
186
187 r = mailmime_get_section_id(mime, &part);
188 if (r != MAILIMF_NO_ERROR)
189 goto err;
190
191 gstr = mmap_string_new("part");
192 if (gstr == NULL)
193 goto free_section;
194
195 for(cur = clist_begin(part->sec_list) ;
196 cur != NULL ; cur = clist_next(cur)) {
197 char s[20];
198
199 snprintf(s, 20, ".%u", * (uint32_t *) clist_content(cur));
200 if (mmap_string_append(gstr, s) == NULL)
201 goto free_str;
202 }
203
204 snprintf(key, size, "%s", gstr->str);
205
206 mmap_string_free(gstr);
207 mailmime_section_free(part);
208
209 return;
210
211 free_str:
212 mmap_string_free(gstr);
213 free_section:
214 mailmime_section_free(part);
215 err:;
216}
217
218static void generate_key_from_section(char * key, size_t size,
219 mailmessage * msg_info,
220 struct mailmime * mime, int type)
221{
222 char section_str[PATH_MAX];
223
224 generate_key_from_mime_section(section_str, PATH_MAX, mime);
225
226 switch (type) {
227 case IMAP_SECTION_MESSAGE:
228 snprintf(key, size, "%s-%s", msg_info->msg_uid, section_str);
229 break;
230 case IMAP_SECTION_HEADER:
231 snprintf(key, size, "%s-%s-header", msg_info->msg_uid, section_str);
232 break;
233 case IMAP_SECTION_MIME:
234 snprintf(key, size, "%s-%s-mime", msg_info->msg_uid, section_str);
235 break;
236 case IMAP_SECTION_BODY:
237 snprintf(key, size, "%s-%s-text", msg_info->msg_uid, section_str);
238 break;
239 }
240}
241
242static void generate_key_from_message(char * key, size_t size,
243 mailmessage * msg_info,
244 int type)
245{
246 switch (type) {
247 case MAILIMAP_MSG_ATT_RFC822:
248 snprintf(key, size, "%s-rfc822", msg_info->msg_uid);
249 break;
250 case MAILIMAP_MSG_ATT_RFC822_HEADER:
251 snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid);
252 break;
253 case MAILIMAP_MSG_ATT_RFC822_TEXT:
254 snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid);
255 break;
256 case MAILIMAP_MSG_ATT_ENVELOPE:
257 snprintf(key, size, "%s-envelope", msg_info->msg_uid);
258 break;
259 }
260}
261
262static void build_cache_name(char * filename, size_t size,
263 mailmessage * msg, char * key)
264{
265 char * quoted_mb;
266
267 quoted_mb = get_cached_session_data(msg)->imap_quoted_mb;
268
269 snprintf(filename, size, "%s/%s", quoted_mb, key);
270}
271
272static int imap_initialize(mailmessage * msg_info)
273{
274 mailmessage * ancestor;
275 int r;
276 char key[PATH_MAX];
277 char * uid;
278 mailimap * imap;
279
280 ancestor = mailmessage_new();
281 if (ancestor == NULL)
282 return MAIL_ERROR_MEMORY;
283
284 r = mailmessage_init(ancestor, get_ancestor_session(msg_info),
285 imap_message_driver,
286 msg_info->msg_index, 0);
287 if (r != MAIL_NO_ERROR) {
288 mailmessage_free(ancestor);
289 return r;
290 }
291
292 imap = get_imap_session(msg_info);
293
294 snprintf(key, PATH_MAX, "%u-%u",
295 imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index);
296 uid = strdup(key);
297 if (uid == NULL) {
298 mailmessage_free(ancestor);
299 return MAIL_ERROR_MEMORY;
300 }
301
302 msg_info->msg_data = ancestor;
303 msg_info->msg_uid = uid;
304
305 return MAIL_NO_ERROR;
306}
307
308static void imap_uninitialize(mailmessage * msg_info)
309{
310 mailmessage_free(get_ancestor(msg_info));
311 msg_info->msg_data = NULL;
312}
313
314static void imap_flush(mailmessage * msg_info)
315{
316 if (msg_info->msg_mime != NULL) {
317 mailmime_free(msg_info->msg_mime);
318 msg_info->msg_mime = NULL;
319 }
320}
321
322static void imap_check(mailmessage * msg_info)
323{
324 get_ancestor(msg_info)->msg_flags = msg_info->msg_flags;
325 mailmessage_check(get_ancestor(msg_info));
326 get_ancestor(msg_info)->msg_flags = NULL;
327}
328
329static void imap_fetch_result_free(mailmessage * msg_info,
330 char * msg)
331{
332 mailmessage_fetch_result_free(get_ancestor(msg_info), msg);
333}
334
335static int imap_fetch(mailmessage * msg_info,
336 char ** result,
337 size_t * result_len)
338{
339 char key[PATH_MAX];
340 char filename[PATH_MAX];
341 int r;
342 char * str;
343 size_t len;
344
345 generate_key_from_message(key, PATH_MAX,
346 msg_info, MAILIMAP_MSG_ATT_RFC822);
347
348 build_cache_name(filename, PATH_MAX, msg_info, key);
349
350 r = generic_cache_read(filename, &str, &len);
351 if (r == MAIL_NO_ERROR) {
352 * result = str;
353 * result_len = len;
354
355 return MAIL_NO_ERROR;
356 }
357
358 r = mailmessage_fetch(get_ancestor(msg_info),
359 result, result_len);
360 if (r == MAIL_NO_ERROR)
361 generic_cache_store(filename, * result, strlen(* result));
362
363 return r;
364}
365
366static int imap_fetch_header(mailmessage * msg_info,
367 char ** result,
368 size_t * result_len)
369{
370 char key[PATH_MAX];
371 char filename[PATH_MAX];
372 int r;
373 char * str;
374 size_t len;
375
376 generate_key_from_message(key, PATH_MAX,
377 msg_info, MAILIMAP_MSG_ATT_RFC822_HEADER);
378
379 build_cache_name(filename, PATH_MAX, msg_info, key);
380
381 r = generic_cache_read(filename, &str, &len);
382 if (r == MAIL_NO_ERROR) {
383 * result = str;
384 * result_len = len;
385
386 return MAIL_NO_ERROR;
387 }
388
389 r = mailmessage_fetch_header(get_ancestor(msg_info), result,
390 result_len);
391 if (r == MAIL_NO_ERROR)
392 generic_cache_store(filename, * result, * result_len);
393
394 return r;
395}
396
397static int imap_fetch_body(mailmessage * msg_info,
398 char ** result, size_t * result_len)
399{
400 char key[PATH_MAX];
401 char filename[PATH_MAX];
402 int r;
403 char * str;
404 size_t len;
405
406 generate_key_from_message(key, PATH_MAX,
407 msg_info, MAILIMAP_MSG_ATT_RFC822_TEXT);
408
409 build_cache_name(filename, PATH_MAX, msg_info, key);
410
411 r = generic_cache_read(filename, &str, &len);
412 if (r == MAIL_NO_ERROR) {
413 * result = str;
414 * result_len = len;
415 return MAIL_NO_ERROR;
416 }
417
418 r = mailmessage_fetch_body(get_ancestor(msg_info), result,
419 result_len);
420 if (r == MAIL_NO_ERROR)
421 generic_cache_store(filename, * result, * result_len);
422
423 return r;
424}
425
426static int imap_fetch_size(mailmessage * msg_info,
427 size_t * result)
428{
429 return mailmessage_fetch_size(get_ancestor(msg_info), result);
430}
431
432static int imap_get_bodystructure(mailmessage * msg_info,
433 struct mailmime ** result)
434{
435 int r;
436
437 if (msg_info->msg_mime != NULL) {
438 * result = msg_info->msg_mime;
439
440 return MAIL_NO_ERROR;
441 }
442
443 r = mailmessage_get_bodystructure(get_ancestor(msg_info),
444 result);
445 if (r == MAIL_NO_ERROR) {
446 msg_info->msg_mime = get_ancestor(msg_info)->msg_mime;
447 get_ancestor(msg_info)->msg_mime = NULL;
448 }
449
450 return r;
451}
452
453static int imap_fetch_section(mailmessage * msg_info,
454 struct mailmime * mime,
455 char ** result, size_t * result_len)
456{
457 char key[PATH_MAX];
458 char filename[PATH_MAX];
459 int r;
460 char * str;
461 size_t len;
462
463 generate_key_from_section(key, PATH_MAX,
464 msg_info, mime, IMAP_SECTION_MESSAGE);
465
466 build_cache_name(filename, PATH_MAX, msg_info, key);
467
468 r = generic_cache_read(filename, &str, &len);
469 if (r == MAIL_NO_ERROR) {
470 * result = str;
471 * result_len = len;
472
473 return MAIL_NO_ERROR;
474 }
475
476 r = mailmessage_fetch_section(get_ancestor(msg_info),
477 mime, result, result_len);
478 if (r == MAIL_NO_ERROR)
479 generic_cache_store(filename, * result, * result_len);
480
481 return r;
482}
483
484static int imap_fetch_section_header(mailmessage * msg_info,
485 struct mailmime * mime,
486 char ** result,
487 size_t * result_len)
488{
489 char key[PATH_MAX];
490 char filename[PATH_MAX];
491 int r;
492 char * str;
493 size_t len;
494
495 generate_key_from_section(key, PATH_MAX,
496 msg_info, mime, IMAP_SECTION_HEADER);
497
498 build_cache_name(filename, PATH_MAX, msg_info, key);
499
500 r = generic_cache_read(filename, &str, &len);
501 if (r == MAIL_NO_ERROR) {
502 * result = str;
503 * result_len = len;
504
505 return MAIL_NO_ERROR;
506 }
507
508 r = mailmessage_fetch_section_header(get_ancestor(msg_info),
509 mime, result, result_len);
510 if (r == MAIL_NO_ERROR)
511 generic_cache_store(filename, * result, * result_len);
512
513 return r;
514}
515
516static int imap_fetch_section_mime(mailmessage * msg_info,
517 struct mailmime * mime,
518 char ** result,
519 size_t * result_len)
520{
521 char key[PATH_MAX];
522 char filename[PATH_MAX];
523 int r;
524 char * str;
525 size_t len;
526
527 generate_key_from_section(key, PATH_MAX,
528 msg_info, mime, IMAP_SECTION_MIME);
529
530 build_cache_name(filename, PATH_MAX, msg_info, key);
531
532 r = generic_cache_read(filename, &str, &len);
533 if (r == MAIL_NO_ERROR) {
534 * result = str;
535 * result_len = len;
536
537 return MAIL_NO_ERROR;
538 }
539
540 r = mailmessage_fetch_section_mime(get_ancestor(msg_info),
541 mime, result, result_len);
542 if (r == MAIL_NO_ERROR)
543 generic_cache_store(filename, * result, * result_len);
544
545 return r;
546}
547
548static int imap_fetch_section_body(mailmessage * msg_info,
549 struct mailmime * mime,
550 char ** result,
551 size_t * result_len)
552{
553 char key[PATH_MAX];
554 char filename[PATH_MAX];
555 int r;
556 char * str;
557 size_t len;
558
559 generate_key_from_section(key, PATH_MAX,
560 msg_info, mime, IMAP_SECTION_BODY);
561
562 build_cache_name(filename, PATH_MAX, msg_info, key);
563
564 r = generic_cache_read(filename, &str, &len);
565 if (r == MAIL_NO_ERROR) {
566
567 * result = str;
568 * result_len = len;
569
570 return MAIL_NO_ERROR;
571 }
572
573 r = mailmessage_fetch_section_body(get_ancestor(msg_info),
574 mime, result, result_len);
575 if (r == MAIL_NO_ERROR)
576 generic_cache_store(filename, * result, * result_len);
577
578 return r;
579}
580
581static int imap_get_flags(mailmessage * msg_info,
582 struct mail_flags ** result)
583{
584 int r;
585 struct mail_flags * flags;
586
587 if (msg_info->msg_flags != NULL) {
588 * result = msg_info->msg_flags;
589 return MAIL_NO_ERROR;
590 }
591
592 r = mailmessage_get_flags(get_ancestor(msg_info), &flags);
593 if (r != MAIL_NO_ERROR)
594 return r;
595
596 get_ancestor(msg_info)->msg_flags = NULL;
597 msg_info->msg_flags = flags;
598 * result = flags;
599
600 return MAIL_NO_ERROR;
601}
602
603#define ENV_NAME "env.db"
604
605static int imap_fetch_envelope(mailmessage * msg_info,
606 struct mailimf_fields ** result)
607{
608 struct mailimf_fields * fields;
609 int r;
610 struct mail_cache_db * cache_db;
611 MMAPString * mmapstr;
612 char filename[PATH_MAX];
613 struct imap_cached_session_state_data * data;
614 int res;
615
616 data = get_cached_session_data(msg_info);
617 if (data->imap_quoted_mb == NULL) {
618 res = MAIL_ERROR_BAD_STATE;
619 goto err;
620 }
621
622 snprintf(filename, PATH_MAX, "%s/%s", data->imap_quoted_mb, ENV_NAME);
623
624 r = mail_cache_db_open_lock(filename, &cache_db);
625 if (r < 0) {
626 res = MAIL_ERROR_MEMORY;
627 goto err;
628 }
629
630 mmapstr = mmap_string_new("");
631 if (mmapstr == NULL) {
632 res = MAIL_ERROR_MEMORY;
633 goto close_db;
634 }
635
636 r = imapdriver_get_cached_envelope(cache_db, mmapstr,
637 msg_info->msg_session, msg_info, &fields);
638
639 if ((r != MAIL_ERROR_CACHE_MISS) && (r != MAIL_NO_ERROR)) {
640 res = r;
641 goto close_db;
642 }
643
644 r = mailmessage_fetch_envelope(get_ancestor(msg_info), &fields);
645 if (r != MAIL_NO_ERROR) {
646 res = r;
647 goto close_db;
648 }
649
650 r = imapdriver_write_cached_envelope(cache_db, mmapstr,
651 msg_info->msg_session, msg_info, fields);
652
653 * result = fields;
654
655 mmap_string_free(mmapstr);
656 mail_cache_db_close_unlock(filename, cache_db);
657
658 return MAIL_NO_ERROR;
659
660 close_db:
661 mail_cache_db_close_unlock(filename, cache_db);
662 err:
663 return res;
664}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h
new file mode 100644
index 0000000..bf43311
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_cached_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_CACHED_MESSAGE_H
37
38#define IMAPDRIVER_CACHED_MESSAGE_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * imap_cached_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_message.c b/libetpan/src/driver/implementation/imap/imapdriver_message.c
new file mode 100644
index 0000000..42e645d
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_message.c
@@ -0,0 +1,1239 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_message.h"
37
38#include "imapdriver_tools.h"
39#include "imapdriver.h"
40#include "imapdriver_types.h"
41#include "mailimap.h"
42#include "maildriver_tools.h"
43#include "generic_cache.h"
44
45#include <stdlib.h>
46#include <string.h>
47
48static int imap_initialize(mailmessage * msg_info);
49
50static void imap_fetch_result_free(mailmessage * msg_info,
51 char * msg);
52
53static int imap_fetch(mailmessage * msg_info,
54 char ** result,
55 size_t * result_len);
56
57static int imap_fetch_header(mailmessage * msg_info,
58 char ** result,
59 size_t * result_len);
60
61static int imap_fetch_body(mailmessage * msg_info,
62 char ** result, size_t * result_len);
63
64static int imap_fetch_size(mailmessage * msg_info,
65 size_t * result);
66
67static int imap_get_bodystructure(mailmessage * msg_info,
68 struct mailmime ** result);
69
70static int imap_fetch_section(mailmessage * msg_info,
71 struct mailmime * mime,
72 char ** result, size_t * result_len);
73
74static int imap_fetch_section_header(mailmessage * msg_info,
75 struct mailmime * mime,
76 char ** result,
77 size_t * result_len);
78
79static int imap_fetch_section_mime(mailmessage * msg_info,
80 struct mailmime * mime,
81 char ** result,
82 size_t * result_len);
83
84static int imap_fetch_section_body(mailmessage * msg_info,
85 struct mailmime * mime,
86 char ** result,
87 size_t * result_len);
88
89static int imap_fetch_envelope(mailmessage * msg_info,
90 struct mailimf_fields ** result);
91
92static int imap_get_flags(mailmessage * msg_info,
93 struct mail_flags ** result);
94
95static void imap_flush(mailmessage * msg_info);
96
97static void imap_check(mailmessage * msg_info);
98
99static mailmessage_driver local_imap_message_driver = {
100 .msg_name = "imap",
101
102 .msg_initialize = imap_initialize,
103 .msg_uninitialize = NULL,
104
105 .msg_flush = imap_flush,
106 .msg_check = imap_check,
107
108 .msg_fetch_result_free = imap_fetch_result_free,
109
110 .msg_fetch = imap_fetch,
111 .msg_fetch_header = imap_fetch_header,
112 .msg_fetch_body = imap_fetch_body,
113 .msg_fetch_size = imap_fetch_size,
114 .msg_get_bodystructure = imap_get_bodystructure,
115 .msg_fetch_section = imap_fetch_section,
116 .msg_fetch_section_header = imap_fetch_section_header,
117 .msg_fetch_section_mime = imap_fetch_section_mime,
118 .msg_fetch_section_body = imap_fetch_section_body,
119 .msg_fetch_envelope = imap_fetch_envelope,
120
121 .msg_get_flags = imap_get_flags,
122};
123
124mailmessage_driver * imap_message_driver = &local_imap_message_driver;
125
126static inline struct imap_session_state_data *
127get_session_data(mailmessage * msg)
128{
129 return msg->msg_session->sess_data;
130}
131
132static inline mailimap * get_imap_session(mailmessage * msg)
133{
134 return get_session_data(msg)->imap_session;
135}
136
137
138
139static int imap_initialize(mailmessage * msg_info)
140{
141 char key[PATH_MAX];
142 char * uid;
143 mailimap * imap;
144
145 imap = get_imap_session(msg_info);
146
147 snprintf(key, PATH_MAX, "%u-%u",
148 imap->imap_selection_info->sel_uidvalidity, msg_info->msg_index);
149
150 uid = strdup(key);
151 if (uid == NULL) {
152 return MAIL_ERROR_MEMORY;
153 }
154
155 msg_info->msg_uid = uid;
156
157 return MAIL_NO_ERROR;
158}
159
160
161static void imap_fetch_result_free(mailmessage * msg_info,
162 char * msg)
163{
164 if (msg != NULL) {
165 if (mmap_string_unref(msg) != 0)
166 free(msg);
167 }
168}
169
170
171static void imap_flush(mailmessage * msg_info)
172{
173 if (msg_info->msg_mime != NULL) {
174 mailmime_free(msg_info->msg_mime);
175 msg_info->msg_mime = NULL;
176 }
177}
178
179static void imap_check(mailmessage * msg_info)
180{
181 int r;
182
183 if (msg_info->msg_flags != NULL) {
184 r = mail_flags_store_set(get_session_data(msg_info)->imap_flags_store,
185 msg_info);
186 /* ignore errors */
187 }
188}
189
190static int imap_fetch(mailmessage * msg_info,
191 char ** result,
192 size_t * result_len)
193{
194 int r;
195 struct mailimap_set * set;
196 struct mailimap_fetch_att * fetch_att;
197 struct mailimap_fetch_type * fetch_type;
198 clist * fetch_result;
199 struct mailimap_msg_att * msg_att;
200 struct mailimap_msg_att_item * msg_att_item;
201 char * text;
202 size_t text_length;
203 int res;
204 clistiter * cur;
205 struct mailimap_section * section;
206
207 set = mailimap_set_new_single(msg_info->msg_index);
208 if (set == NULL) {
209 res = MAIL_ERROR_MEMORY;
210 goto err;
211 }
212
213#if 0
214 fetch_att = mailimap_fetch_att_new_rfc822();
215 if (fetch_att == NULL) {
216 res = MAIL_ERROR_MEMORY;
217 goto free_set;
218 }
219
220 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
221 if (fetch_type == NULL) {
222 res = MAIL_ERROR_MEMORY;
223 goto free_fetch_att;
224 }
225
226 r = mailimap_uid_fetch(get_imap_session(msg_info->session), set,
227 fetch_type, &fetch_result);
228
229 mailimap_fetch_type_free(fetch_type);
230#endif
231
232 section = mailimap_section_new(NULL);
233 if (section == NULL) {
234 res = MAIL_ERROR_MEMORY;
235 goto free_set;
236 }
237
238 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
239 if (fetch_att == NULL) {
240 mailimap_section_free(section);
241 res = MAIL_ERROR_MEMORY;
242 goto free_set;
243 }
244
245 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
246 if (fetch_type == NULL) {
247 res = MAIL_ERROR_MEMORY;
248 goto free_fetch_att;
249 }
250
251 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
252 fetch_type, &fetch_result);
253
254 mailimap_fetch_type_free(fetch_type);
255 mailimap_set_free(set);
256
257 switch (r) {
258 case MAILIMAP_NO_ERROR:
259 break;
260 default:
261 return imap_error_to_mail_error(r);
262 }
263
264 if (clist_begin(fetch_result) == NULL) {
265 mailimap_fetch_list_free(fetch_result);
266 return MAIL_ERROR_FETCH;
267 }
268
269 msg_att = clist_begin(fetch_result)->data;
270
271 text = NULL;
272 text_length = 0;
273
274 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
275 cur = clist_next(cur)) {
276 msg_att_item = clist_content(cur);
277
278 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
279#if 0
280 if (msg_att_item->msg_att_static->type == MAILIMAP_MSG_ATT_RFC822) {
281 text = msg_att_item->msg_att_static->rfc822;
282 msg_att_item->msg_att_static->rfc822 = NULL;
283 text_length = msg_att_item->msg_att_static->length;
284 }
285#endif
286 if (msg_att_item->att_data.att_static->att_type ==
287 MAILIMAP_MSG_ATT_BODY_SECTION) {
288 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
289 /* detach */
290 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
291 text_length =
292 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
293 }
294 }
295 }
296
297 mailimap_fetch_list_free(fetch_result);
298
299 if (text == NULL)
300 return MAIL_ERROR_FETCH;
301
302 * result = text;
303 * result_len = text_length;
304
305 return MAIL_NO_ERROR;
306
307 free_fetch_att:
308 mailimap_fetch_att_free(fetch_att);
309 free_set:
310 mailimap_set_free(set);
311 err:
312 return res;
313}
314
315static int imap_fetch_header(mailmessage * msg_info,
316 char ** result,
317 size_t * result_len)
318{
319 int r;
320 struct mailimap_set * set;
321 struct mailimap_fetch_att * fetch_att;
322 struct mailimap_fetch_type * fetch_type;
323 clist * fetch_result;
324 struct mailimap_msg_att * msg_att;
325 struct mailimap_msg_att_item * msg_att_item;
326 char * text;
327 size_t text_length;
328 int res;
329 clistiter * cur;
330 struct mailimap_section * section;
331
332 set = mailimap_set_new_single(msg_info->msg_index);
333 if (set == NULL) {
334 res = MAIL_ERROR_MEMORY;
335 goto err;
336 }
337
338#if 0
339 fetch_att = mailimap_fetch_att_new_rfc822_header();
340 if (fetch_att == NULL) {
341 res = MAIL_ERROR_MEMORY;
342 goto free_set;
343 }
344
345 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
346 if (fetch_type == NULL) {
347 res = MAIL_ERROR_MEMORY;
348 goto free_fetch_att;
349 }
350
351 r = mailimap_uid_fetch(get_imap_session(msg_info->session),
352 set, fetch_type, &fetch_result);
353
354 mailimap_fetch_type_free(fetch_type);
355#endif
356
357 section = mailimap_section_new_header();
358 if (section == NULL) {
359 res = MAIL_ERROR_MEMORY;
360 goto free_set;
361 }
362
363 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
364 if (fetch_att == NULL) {
365 mailimap_section_free(section);
366 res = MAIL_ERROR_MEMORY;
367 goto free_set;
368 }
369
370 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
371 if (fetch_type == NULL) {
372 res = MAIL_ERROR_MEMORY;
373 goto free_fetch_att;
374 }
375
376 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
377 fetch_type, &fetch_result);
378
379 mailimap_fetch_type_free(fetch_type);
380 mailimap_set_free(set);
381
382 switch (r) {
383 case MAILIMAP_NO_ERROR:
384 break;
385 default:
386 return imap_error_to_mail_error(r);
387 }
388
389 if (clist_begin(fetch_result) == NULL) {
390 mailimap_fetch_list_free(fetch_result);
391 return MAIL_ERROR_FETCH;
392 }
393
394 msg_att = clist_begin(fetch_result)->data;
395
396 text = NULL;
397 text_length = 0;
398
399 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
400 cur = clist_next(cur)) {
401 msg_att_item = clist_content(cur);
402
403 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
404#if 0
405 if (msg_att_item->msg_att_static->type ==
406 MAILIMAP_MSG_ATT_RFC822_HEADER) {
407 text = msg_att_item->msg_att_static->rfc822_header;
408 msg_att_item->msg_att_static->rfc822_header = NULL;
409 text_length = msg_att_item->msg_att_static->length;
410 }
411#endif
412 if (msg_att_item->att_data.att_static->att_type ==
413 MAILIMAP_MSG_ATT_BODY_SECTION) {
414 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
415 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
416 text_length =
417 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
418 }
419 }
420 }
421
422 mailimap_fetch_list_free(fetch_result);
423
424 if (text == NULL)
425 return MAIL_ERROR_FETCH;
426
427 * result = text;
428 * result_len = text_length;
429
430 return MAIL_NO_ERROR;
431
432 free_fetch_att:
433 mailimap_fetch_att_free(fetch_att);
434 free_set:
435 mailimap_set_free(set);
436 err:
437 return res;
438}
439
440static int imap_fetch_body(mailmessage * msg_info,
441 char ** result, size_t * result_len)
442{
443 int r;
444 struct mailimap_set * set;
445 struct mailimap_fetch_att * fetch_att;
446 struct mailimap_fetch_type * fetch_type;
447 clist * fetch_result;
448 struct mailimap_msg_att * msg_att;
449 struct mailimap_msg_att_item * msg_att_item;
450 char * text;
451 size_t text_length;
452 int res;
453 clistiter * cur;
454 struct mailimap_section * section;
455
456 set = mailimap_set_new_single(msg_info->msg_index);
457 if (set == NULL) {
458 res = MAIL_ERROR_MEMORY;
459 goto err;
460 }
461
462#if 0
463 fetch_att = mailimap_fetch_att_new_rfc822_text();
464 if (fetch_att == NULL) {
465 res = MAIL_ERROR_MEMORY;
466 goto free_set;
467 }
468
469 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
470 if (fetch_type == NULL) {
471 res = MAIL_ERROR_MEMORY;
472 goto free_fetch_att;
473 }
474
475 r = mailimap_uid_fetch(get_imap_session(msg_info->session), set,
476 fetch_type, &fetch_result);
477
478 mailimap_fetch_type_free(fetch_type);
479#endif
480 section = mailimap_section_new_text();
481 if (section == NULL) {
482 res = MAIL_ERROR_MEMORY;
483 goto free_set;
484 }
485
486 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
487 if (fetch_att == NULL) {
488 mailimap_section_free(section);
489 res = MAIL_ERROR_MEMORY;
490 goto free_set;
491 }
492
493 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
494 if (fetch_type == NULL) {
495 res = MAIL_ERROR_MEMORY;
496 goto free_fetch_att;
497 }
498
499 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
500 fetch_type, &fetch_result);
501
502 mailimap_fetch_type_free(fetch_type);
503 mailimap_set_free(set);
504
505 switch (r) {
506 case MAILIMAP_NO_ERROR:
507 break;
508 default:
509 return imap_error_to_mail_error(r);
510 }
511
512 cur = clist_begin(fetch_result);
513 if (cur == NULL) {
514 mailimap_fetch_list_free(fetch_result);
515 return MAIL_ERROR_FETCH;
516 }
517
518 msg_att = clist_content(cur);
519
520 text = NULL;
521 text_length = 0;
522
523 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
524 cur = clist_next(cur)) {
525 msg_att_item = clist_content(cur);
526
527 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
528#if 0
529 if (msg_att_item->msg_att_static->type ==
530 MAILIMAP_MSG_ATT_RFC822_TEXT) {
531 text = msg_att_item->msg_att_static->rfc822_text;
532 msg_att_item->msg_att_static->rfc822_text = NULL;
533 text_length = msg_att_item->msg_att_static->length;
534 }
535#endif
536 if (msg_att_item->att_data.att_static->att_type ==
537 MAILIMAP_MSG_ATT_BODY_SECTION) {
538 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
539 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
540 text_length =
541 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
542 }
543 }
544 }
545
546 mailimap_fetch_list_free(fetch_result);
547
548 if (text == NULL)
549 return MAIL_ERROR_FETCH;
550
551 * result = text;
552 * result_len = text_length;
553
554 return MAIL_NO_ERROR;
555
556 free_fetch_att:
557 mailimap_fetch_att_free(fetch_att);
558 free_set:
559 mailimap_set_free(set);
560 err:
561 return res;
562}
563
564static int imap_fetch_size(mailmessage * msg_info,
565 size_t * result)
566{
567 int r;
568 struct mailimap_set * set;
569 struct mailimap_fetch_att * fetch_att;
570 struct mailimap_fetch_type * fetch_type;
571 clist * fetch_result;
572 struct mailimap_msg_att * msg_att;
573 struct mailimap_msg_att_item * msg_att_item;
574 size_t size;
575 int res;
576 clistiter * cur;
577
578 set = mailimap_set_new_single(msg_info->msg_index);
579 if (set == NULL) {
580 res = MAIL_ERROR_MEMORY;
581 goto err;
582 }
583
584 fetch_att = mailimap_fetch_att_new_rfc822_size();
585 if (fetch_att == NULL) {
586 res = MAIL_ERROR_MEMORY;
587 goto free_set;
588 }
589
590 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
591 if (fetch_type == NULL) {
592 res = MAIL_ERROR_MEMORY;
593 goto free_fetch_att;
594 }
595
596 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
597 fetch_type, &fetch_result);
598
599 mailimap_fetch_type_free(fetch_type);
600 mailimap_set_free(set);
601
602 switch (r) {
603 case MAILIMAP_ERROR_BAD_STATE:
604 return MAIL_ERROR_BAD_STATE;
605 case MAILIMAP_ERROR_STREAM:
606 return MAIL_ERROR_STREAM;
607 case MAILIMAP_NO_ERROR:
608 break;
609 default:
610 return MAIL_ERROR_FETCH;
611 }
612
613 if (clist_begin(fetch_result) == NULL) {
614 mailimap_fetch_list_free(fetch_result);
615 return MAIL_ERROR_FETCH;
616 }
617
618 msg_att = clist_begin(fetch_result)->data;
619
620 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
621 cur = clist_next(cur)) {
622 msg_att_item = clist_content(cur);
623
624 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
625
626 if (msg_att_item->att_data.att_static->att_type ==
627 MAILIMAP_MSG_ATT_RFC822_SIZE) {
628 size = msg_att_item->att_data.att_static->att_data.att_rfc822_size;
629
630 * result = size;
631
632 mailimap_fetch_list_free(fetch_result);
633 return MAIL_NO_ERROR;
634 }
635 }
636 }
637
638 mailimap_fetch_list_free(fetch_result);
639
640 return MAIL_ERROR_FETCH;
641
642 free_fetch_att:
643 mailimap_fetch_att_free(fetch_att);
644 free_set:
645 mailimap_set_free(set);
646 err:
647 return res;
648}
649
650static int imap_get_bodystructure(mailmessage * msg_info,
651 struct mailmime ** result)
652{
653 int r;
654 struct mailimap_set * set;
655 struct mailimap_fetch_att * fetch_att;
656 struct mailimap_fetch_type * fetch_type;
657 clist * fetch_result;
658 struct mailimap_msg_att * msg_att;
659 struct mailimap_body * imap_body;
660 struct mailmime * body;
661 int res;
662 struct mailimf_fields * fields;
663 struct mailmime * new_body;
664 struct mailmime_content * content_message;
665 struct mailimap_envelope * envelope;
666 uint32_t uid;
667 char * references;
668 size_t ref_size;
669 clistiter * cur;
670
671 if (msg_info->msg_mime != NULL) {
672 * result = msg_info->msg_mime;
673
674 return MAIL_NO_ERROR;
675 }
676
677 set = mailimap_set_new_single(msg_info->msg_index);
678 if (set == NULL) {
679 res = MAIL_ERROR_MEMORY;
680 goto err;
681 }
682
683 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
684 if (fetch_type == NULL) {
685 res = MAIL_ERROR_MEMORY;
686 goto free_set;
687 }
688
689 fetch_att = mailimap_fetch_att_new_uid();
690 if (fetch_att == NULL) {
691 res = MAIL_ERROR_MEMORY;
692 goto free_fetch_type;
693 }
694
695 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
696 if (r != MAILIMAP_NO_ERROR) {
697 mailimap_fetch_att_free(fetch_att);
698 res = MAIL_ERROR_MEMORY;
699 goto free_fetch_type;
700 }
701
702 fetch_att = mailimap_fetch_att_new_bodystructure();
703 if (fetch_att == NULL) {
704 res = MAIL_ERROR_MEMORY;
705 goto free_fetch_type;
706 }
707
708 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
709 if (r != MAILIMAP_NO_ERROR) {
710 mailimap_fetch_att_free(fetch_att);
711 res = MAIL_ERROR_MEMORY;
712 goto free_fetch_type;
713 }
714
715 r = imap_add_envelope_fetch_att(fetch_type);
716 if (r != MAIL_NO_ERROR) {
717 res = r;
718 goto free_fetch_type;
719 }
720
721
722 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
723 fetch_type, &fetch_result);
724
725 mailimap_fetch_type_free(fetch_type);
726 mailimap_set_free(set);
727
728 switch (r) {
729 case MAILIMAP_NO_ERROR:
730 break;
731 default:
732 return imap_error_to_mail_error(r);
733 }
734
735 cur = clist_begin(fetch_result);
736 if (cur == NULL) {
737 mailimap_fetch_list_free(fetch_result);
738 return MAIL_ERROR_FETCH;
739 }
740
741 msg_att = clist_content(cur);
742
743 uid = 0;
744 references = NULL;
745 ref_size = 0;
746 imap_body = NULL;
747 envelope = NULL;
748
749 r = imap_get_msg_att_info(msg_att,
750 &uid, &envelope, &references, &ref_size, NULL, &imap_body);
751 if (r != MAIL_NO_ERROR) {
752 mailimap_fetch_list_free(fetch_result);
753 res = r;
754 goto err;
755 }
756
757 if (uid != msg_info->msg_index) {
758 mailimap_fetch_list_free(fetch_result);
759 res = MAIL_ERROR_MSG_NOT_FOUND;
760 goto err;
761 }
762
763 if (imap_body == NULL) {
764 mailimap_fetch_list_free(fetch_result);
765 res = MAIL_ERROR_FETCH;
766 goto err;
767 }
768
769 r = imap_body_to_body(imap_body, &body);
770 if (r != MAIL_NO_ERROR) {
771 mailimap_fetch_list_free(fetch_result);
772 res = r;
773 goto err;
774 }
775
776 fields = NULL;
777 if (envelope != NULL) {
778 r = imap_env_to_fields(envelope, references, ref_size, &fields);
779 if (r != MAIL_NO_ERROR) {
780 mailmime_free(body);
781 mailimap_fetch_list_free(fetch_result);
782 res = r;
783 goto err;
784 }
785 }
786
787 content_message = mailmime_get_content_message();
788 if (content_message == NULL) {
789 if (fields != NULL)
790 mailimf_fields_free(fields);
791 mailmime_free(body);
792 mailimap_fetch_list_free(fetch_result);
793 res = MAIL_ERROR_MEMORY;
794 goto err;
795 }
796
797 new_body = mailmime_new(MAILMIME_MESSAGE, NULL,
798 0, NULL, content_message,
799 NULL, NULL, NULL, NULL, fields, body);
800
801 if (new_body == NULL) {
802 mailmime_content_free(content_message);
803 if (fields != NULL)
804 mailimf_fields_free(fields);
805 mailmime_free(body);
806 mailimap_fetch_list_free(fetch_result);
807 res = MAIL_ERROR_MEMORY;
808 goto err;
809 }
810 msg_info->msg_mime = new_body;
811
812 mailimap_fetch_list_free(fetch_result);
813
814 * result = new_body;
815
816 return MAIL_NO_ERROR;
817
818 free_fetch_type:
819 mailimap_fetch_type_free(fetch_type);
820 free_set:
821 mailimap_set_free(set);
822 err:
823 return res;
824}
825
826static int
827fetch_imap(mailmessage * msg,
828 struct mailimap_fetch_type * fetch_type,
829 char ** result, size_t * result_len)
830{
831 int r;
832 struct mailimap_msg_att * msg_att;
833 struct mailimap_msg_att_item * msg_att_item;
834 clist * fetch_result;
835 struct mailimap_set * set;
836 char * text;
837 size_t text_length;
838 clistiter * cur;
839
840 set = mailimap_set_new_single(msg->msg_index);
841 if (set == NULL)
842 return MAIL_ERROR_MEMORY;
843
844 r = mailimap_uid_fetch(get_imap_session(msg), set,
845 fetch_type, &fetch_result);
846
847 mailimap_set_free(set);
848
849 switch (r) {
850 case MAILIMAP_NO_ERROR:
851 break;
852 default:
853 return imap_error_to_mail_error(r);
854 }
855
856 if (clist_begin(fetch_result) == NULL) {
857 mailimap_fetch_list_free(fetch_result);
858 return MAIL_ERROR_FETCH;
859 }
860
861 msg_att = clist_begin(fetch_result)->data;
862
863 text = NULL;
864 text_length = 0;
865
866 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
867 cur = clist_next(cur)) {
868 msg_att_item = clist_content(cur);
869
870 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
871
872 if (msg_att_item->att_data.att_static->att_type ==
873 MAILIMAP_MSG_ATT_BODY_SECTION) {
874 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
875 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
876 text_length =
877 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
878 }
879 }
880 }
881
882 mailimap_fetch_list_free(fetch_result);
883
884 if (text == NULL)
885 return MAIL_ERROR_FETCH;
886
887 * result = text;
888 * result_len = text_length;
889
890 return MAIL_NO_ERROR;
891}
892
893
894static int imap_fetch_section(mailmessage * msg_info,
895 struct mailmime * mime,
896 char ** result, size_t * result_len)
897{
898 struct mailimap_section * section;
899 struct mailimap_fetch_att * fetch_att;
900 int r;
901 struct mailimap_fetch_type * fetch_type;
902 char * text;
903 size_t text_length;
904 struct mailmime_section * part;
905
906 if (mime->mm_parent == NULL)
907 return imap_fetch(msg_info, result, result_len);
908
909 r = mailmime_get_section_id(mime, &part);
910 if (r != MAILIMF_NO_ERROR)
911 return maildriver_imf_error_to_mail_error(r);
912
913 r = section_to_imap_section(part, IMAP_SECTION_MESSAGE, &section);
914 mailmime_section_free(part);
915 if (r != MAIL_NO_ERROR)
916 return r;
917
918 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
919 if (fetch_att == NULL) {
920 mailimap_section_free(section);
921 return MAIL_ERROR_MEMORY;
922 }
923
924 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
925 if (fetch_type == NULL) {
926 mailimap_fetch_att_free(fetch_att);
927 return MAIL_ERROR_MEMORY;
928 }
929
930 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
931
932 mailimap_fetch_type_free(fetch_type);
933
934 if (r != MAIL_NO_ERROR)
935 return r;
936
937 * result = text;
938 * result_len = text_length;
939
940 return MAIL_NO_ERROR;
941}
942
943static int imap_fetch_section_header(mailmessage * msg_info,
944 struct mailmime * mime,
945 char ** result,
946 size_t * result_len)
947{
948 struct mailimap_section * section;
949 struct mailimap_fetch_att * fetch_att;
950 int r;
951 struct mailimap_fetch_type * fetch_type;
952 char * text;
953 size_t text_length;
954 struct mailmime_section * part;
955
956 if (mime->mm_parent == NULL)
957 return imap_fetch_header(msg_info, result, result_len);
958
959 r = mailmime_get_section_id(mime, &part);
960 if (r != MAILIMF_NO_ERROR)
961 return maildriver_imf_error_to_mail_error(r);
962
963 r = section_to_imap_section(part, IMAP_SECTION_HEADER, &section);
964 mailmime_section_free(part);
965 if (r != MAIL_NO_ERROR)
966 return r;
967
968 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
969 if (fetch_att == NULL) {
970 mailimap_section_free(section);
971 return MAIL_ERROR_MEMORY;
972 }
973
974 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
975 if (fetch_type == NULL) {
976 mailimap_fetch_att_free(fetch_att);
977 return MAIL_ERROR_MEMORY;
978 }
979
980 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
981 mailimap_fetch_type_free(fetch_type);
982
983 if (r != MAIL_NO_ERROR)
984 return r;
985
986 * result = text;
987 * result_len = text_length;
988
989 return MAIL_NO_ERROR;
990}
991
992static int imap_fetch_section_mime(mailmessage * msg_info,
993 struct mailmime * mime,
994 char ** result,
995 size_t * result_len)
996{
997 struct mailimap_section * section;
998 struct mailimap_fetch_att * fetch_att;
999 int r;
1000 struct mailimap_fetch_type * fetch_type;
1001 char * text;
1002 size_t text_length;
1003 struct mailmime_section * part;
1004
1005 if (mime->mm_parent == NULL)
1006 return MAIL_ERROR_INVAL;
1007
1008 if (mime->mm_parent->mm_parent == NULL)
1009 return imap_fetch_header(msg_info, result, result_len);
1010
1011 r = mailmime_get_section_id(mime, &part);
1012 if (r != MAILIMF_NO_ERROR)
1013 return maildriver_imf_error_to_mail_error(r);
1014
1015 r = section_to_imap_section(part, IMAP_SECTION_MIME, &section);
1016 mailmime_section_free(part);
1017 if (r != MAIL_NO_ERROR)
1018 return MAIL_ERROR_MEMORY;
1019
1020 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1021 if (fetch_att == NULL) {
1022 mailimap_section_free(section);
1023 return MAIL_ERROR_MEMORY;
1024 }
1025
1026 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1027 if (fetch_type == NULL) {
1028 mailimap_fetch_att_free(fetch_att);
1029 return MAIL_ERROR_MEMORY;
1030 }
1031
1032 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
1033
1034 mailimap_fetch_type_free(fetch_type);
1035
1036 if (r != MAIL_NO_ERROR)
1037 return r;
1038
1039 * result = text;
1040 * result_len = text_length;
1041
1042 return MAIL_NO_ERROR;
1043}
1044
1045static int imap_fetch_section_body(mailmessage * msg_info,
1046 struct mailmime * mime,
1047 char ** result,
1048 size_t * result_len)
1049{
1050 struct mailimap_section * section;
1051 struct mailimap_fetch_att * fetch_att;
1052 int r;
1053 struct mailimap_fetch_type * fetch_type;
1054 char * text;
1055 size_t text_length;
1056 struct mailmime_section * part;
1057
1058 if (mime->mm_parent == NULL)
1059 return imap_fetch_body(msg_info, result, result_len);
1060
1061 if (mime->mm_parent->mm_parent == NULL)
1062 return imap_fetch_body(msg_info, result, result_len);
1063
1064 r = mailmime_get_section_id(mime, &part);
1065 if (r != MAILIMF_NO_ERROR)
1066 return maildriver_imf_error_to_mail_error(r);
1067
1068 r = section_to_imap_section(part, IMAP_SECTION_BODY, &section);
1069 mailmime_section_free(part);
1070 if (r != MAIL_NO_ERROR)
1071 return MAIL_ERROR_MEMORY;
1072
1073 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1074 if (fetch_att == NULL) {
1075 mailimap_section_free(section);
1076 return MAIL_ERROR_MEMORY;
1077 }
1078
1079 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1080 if (fetch_type == NULL) {
1081 mailimap_fetch_att_free(fetch_att);
1082 return MAIL_ERROR_MEMORY;
1083 }
1084
1085 r = fetch_imap(msg_info, fetch_type, &text, &text_length);
1086
1087 mailimap_fetch_type_free(fetch_type);
1088
1089 if (r != MAIL_NO_ERROR)
1090 return r;
1091
1092 * result = text;
1093 * result_len = text_length;
1094
1095 return MAIL_NO_ERROR;
1096}
1097
1098static int imap_get_flags(mailmessage * msg_info,
1099 struct mail_flags ** result)
1100{
1101 int r;
1102 struct mail_flags * flags;
1103
1104 if (msg_info->msg_flags != NULL) {
1105 * result = msg_info->msg_flags;
1106 return MAIL_NO_ERROR;
1107 }
1108
1109 flags = mail_flags_store_get(get_session_data(msg_info)->imap_flags_store,
1110 msg_info->msg_index);
1111
1112 if (flags == NULL) {
1113 r = imap_fetch_flags(get_imap_session(msg_info),
1114 msg_info->msg_index, &flags);
1115 if (r != MAIL_NO_ERROR)
1116 return r;
1117 }
1118
1119 msg_info->msg_flags = flags;
1120
1121 * result = flags;
1122
1123 return MAIL_NO_ERROR;
1124}
1125
1126static int imap_fetch_envelope(mailmessage * msg_info,
1127 struct mailimf_fields ** result)
1128{
1129 int r;
1130 struct mailimap_set * set;
1131 struct mailimap_fetch_att * fetch_att;
1132 struct mailimap_fetch_type * fetch_type;
1133 clist * fetch_result;
1134 struct mailimap_msg_att * msg_att;
1135 int res;
1136 struct mailimf_fields * fields;
1137 struct mailimap_envelope * envelope;
1138 uint32_t uid;
1139 char * references;
1140 size_t ref_size;
1141
1142 set = mailimap_set_new_single(msg_info->msg_index);
1143 if (set == NULL) {
1144 res = MAIL_ERROR_MEMORY;
1145 goto err;
1146 }
1147
1148 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
1149 if (fetch_type == NULL) {
1150 res = MAIL_ERROR_MEMORY;
1151 goto free_set;
1152 }
1153
1154 fetch_att = mailimap_fetch_att_new_uid();
1155 if (fetch_att == NULL) {
1156 res = MAIL_ERROR_MEMORY;
1157 goto free_fetch_type;
1158 }
1159
1160 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1161 if (r != MAILIMAP_NO_ERROR) {
1162 mailimap_fetch_att_free(fetch_att);
1163 res = MAIL_ERROR_MEMORY;
1164 goto free_fetch_type;
1165 }
1166
1167 r = imap_add_envelope_fetch_att(fetch_type);
1168 if (r != MAIL_NO_ERROR) {
1169 res = r;
1170 goto free_fetch_type;
1171 }
1172
1173 r = mailimap_uid_fetch(get_imap_session(msg_info), set,
1174 fetch_type, &fetch_result);
1175
1176 mailimap_fetch_type_free(fetch_type);
1177 mailimap_set_free(set);
1178
1179 switch (r) {
1180 case MAILIMAP_NO_ERROR:
1181 break;
1182 default:
1183 return imap_error_to_mail_error(r);
1184 }
1185
1186 if (clist_begin(fetch_result) == NULL) {
1187 mailimap_fetch_list_free(fetch_result);
1188 return MAIL_ERROR_FETCH;
1189 }
1190
1191 msg_att = clist_begin(fetch_result)->data;
1192
1193 uid = 0;
1194 references = NULL;
1195 ref_size = 0;
1196 envelope = NULL;
1197
1198 r = imap_get_msg_att_info(msg_att,
1199 &uid,
1200 &envelope,
1201 &references,
1202 &ref_size,
1203 NULL,
1204 NULL);
1205 if (r != MAIL_NO_ERROR) {
1206 mailimap_fetch_list_free(fetch_result);
1207 res = r;
1208 goto err;
1209 }
1210
1211 if (uid != msg_info->msg_index) {
1212 mailimap_fetch_list_free(fetch_result);
1213 res = MAIL_ERROR_MSG_NOT_FOUND;
1214 goto err;
1215 }
1216
1217 fields = NULL;
1218 if (envelope != NULL) {
1219 r = imap_env_to_fields(envelope, references, ref_size, &fields);
1220 if (r != MAIL_NO_ERROR) {
1221 mailimap_fetch_list_free(fetch_result);
1222 res = r;
1223 goto err;
1224 }
1225 }
1226
1227 mailimap_fetch_list_free(fetch_result);
1228
1229 * result = fields;
1230
1231 return MAIL_NO_ERROR;
1232
1233 free_fetch_type:
1234 mailimap_fetch_type_free(fetch_type);
1235 free_set:
1236 mailimap_set_free(set);
1237 err:
1238 return res;
1239}
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_message.h b/libetpan/src/driver/implementation/imap/imapdriver_message.h
new file mode 100644
index 0000000..74fc2e6
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_message.h
@@ -0,0 +1,52 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_MESSAGE_H
37
38#define IMAPDRIVER_MESSAGE_H
39
40#include <libetpan/imapdriver_types.h>
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46extern mailmessage_driver * imap_message_driver;
47
48#ifdef __cplusplus
49}
50#endif
51
52#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_tools.c b/libetpan/src/driver/implementation/imap/imapdriver_tools.c
new file mode 100644
index 0000000..6051281
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_tools.c
@@ -0,0 +1,3623 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapdriver_tools.h"
37
38#include "maildriver.h"
39
40#include <stdlib.h>
41#include <string.h>
42
43#include "mail.h"
44#include "imapdriver_types.h"
45#include "maildriver_tools.h"
46#include "generic_cache.h"
47#include "mailmessage.h"
48#include "mail_cache_db.h"
49
50
51
52static inline struct imap_session_state_data *
53session_get_data(mailsession * session)
54{
55 return session->sess_data;
56}
57
58static inline struct imap_cached_session_state_data *
59cached_session_get_data(mailsession * session)
60{
61 return session->sess_data;
62}
63
64static inline mailsession *
65cached_session_get_ancestor(mailsession * session)
66{
67 return cached_session_get_data(session)->imap_ancestor;
68}
69
70static inline struct imap_session_state_data *
71cached_session_get_ancestor_data(mailsession * session)
72{
73 return session_get_data(cached_session_get_ancestor(session));
74}
75
76static inline mailimap *
77cached_session_get_imap_session(mailsession * session)
78{
79 return cached_session_get_ancestor_data(session)->imap_session;
80}
81
82static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn,
83 struct mail_flags ** result);
84
85
86int imap_error_to_mail_error(int error)
87{
88 switch (error) {
89 case MAILIMAP_NO_ERROR:
90 return MAIL_NO_ERROR;
91
92 case MAILIMAP_NO_ERROR_AUTHENTICATED:
93 return MAIL_NO_ERROR_AUTHENTICATED;
94
95 case MAILIMAP_NO_ERROR_NON_AUTHENTICATED:
96 return MAIL_NO_ERROR_NON_AUTHENTICATED;
97
98 case MAILIMAP_ERROR_BAD_STATE:
99 return MAIL_ERROR_BAD_STATE;
100
101 case MAILIMAP_ERROR_STREAM:
102 return MAIL_ERROR_STREAM;
103
104 case MAILIMAP_ERROR_PARSE:
105 return MAIL_ERROR_PARSE;
106
107 case MAILIMAP_ERROR_CONNECTION_REFUSED:
108 return MAIL_ERROR_CONNECT;
109
110 case MAILIMAP_ERROR_MEMORY:
111 return MAIL_ERROR_MEMORY;
112
113 case MAILIMAP_ERROR_FATAL:
114 return MAIL_ERROR_FATAL;
115
116 case MAILIMAP_ERROR_PROTOCOL:
117 return MAIL_ERROR_PROTOCOL;
118
119 case MAILIMAP_ERROR_DONT_ACCEPT_CONNECTION:
120 return MAIL_ERROR_CONNECT;
121
122 case MAILIMAP_ERROR_APPEND:
123 return MAIL_ERROR_APPEND;
124
125 case MAILIMAP_ERROR_NOOP:
126 return MAIL_ERROR_NOOP;
127
128 case MAILIMAP_ERROR_LOGOUT:
129 return MAIL_ERROR_LOGOUT;
130
131 case MAILIMAP_ERROR_CAPABILITY:
132 return MAIL_ERROR_CAPABILITY;
133
134 case MAILIMAP_ERROR_CHECK:
135 return MAIL_ERROR_CHECK;
136
137 case MAILIMAP_ERROR_CLOSE:
138 return MAIL_ERROR_CLOSE;
139
140 case MAILIMAP_ERROR_EXPUNGE:
141 return MAIL_ERROR_EXPUNGE;
142
143 case MAILIMAP_ERROR_COPY:
144 case MAILIMAP_ERROR_UID_COPY:
145 return MAIL_ERROR_COPY;
146
147 case MAILIMAP_ERROR_CREATE:
148 return MAIL_ERROR_CREATE;
149
150 case MAILIMAP_ERROR_DELETE:
151 return MAIL_ERROR_DELETE;
152
153 case MAILIMAP_ERROR_EXAMINE:
154 return MAIL_ERROR_EXAMINE;
155
156 case MAILIMAP_ERROR_FETCH:
157 case MAILIMAP_ERROR_UID_FETCH:
158 return MAIL_ERROR_FETCH;
159
160 case MAILIMAP_ERROR_LIST:
161 return MAIL_ERROR_LIST;
162
163 case MAILIMAP_ERROR_LOGIN:
164 return MAIL_ERROR_LOGIN;
165
166 case MAILIMAP_ERROR_LSUB:
167 return MAIL_ERROR_LSUB;
168
169 case MAILIMAP_ERROR_RENAME:
170 return MAIL_ERROR_RENAME;
171
172 case MAILIMAP_ERROR_SEARCH:
173 case MAILIMAP_ERROR_UID_SEARCH:
174 return MAIL_ERROR_SEARCH;
175
176 case MAILIMAP_ERROR_SELECT:
177 return MAIL_ERROR_SELECT;
178
179 case MAILIMAP_ERROR_STATUS:
180 return MAIL_ERROR_STATUS;
181
182 case MAILIMAP_ERROR_STORE:
183 case MAILIMAP_ERROR_UID_STORE:
184 return MAIL_ERROR_STORE;
185
186 case MAILIMAP_ERROR_SUBSCRIBE:
187 return MAIL_ERROR_SUBSCRIBE;
188
189 case MAILIMAP_ERROR_UNSUBSCRIBE:
190 return MAIL_ERROR_UNSUBSCRIBE;
191
192 case MAILIMAP_ERROR_STARTTLS:
193 return MAIL_ERROR_STARTTLS;
194
195 case MAILIMAP_ERROR_INVAL:
196 return MAIL_ERROR_INVAL;
197
198 default:
199 return MAIL_ERROR_INVAL;
200 }
201}
202
203
204
205
206
207static int
208imap_body_parameter_to_content(struct mailimap_body_fld_param *
209 body_parameter,
210 char * subtype,
211 struct mailmime_type * mime_type,
212 struct mailmime_content ** result);
213
214static int
215imap_body_type_text_to_content_type(char * subtype,
216 struct mailimap_body_fld_param *
217 body_parameter,
218 struct mailmime_content ** result);
219
220
221int imap_list_to_list(clist * imap_list, struct mail_list ** result)
222{
223 clistiter * cur;
224 clist * list;
225 struct mail_list * resp;
226 int r;
227 int res;
228
229 list = clist_new();
230 if (list == NULL) {
231 res = MAIL_ERROR_MEMORY;
232 goto err;
233 }
234
235 for(cur = clist_begin(imap_list) ; cur != NULL ; cur = clist_next(cur)) {
236 struct mailimap_mailbox_list * mb_list;
237 char * new_mb;
238
239 mb_list = clist_content(cur);
240
241 new_mb = strdup(mb_list->mb_name);
242 if (new_mb == NULL) {
243 res = MAIL_ERROR_MEMORY;
244 goto free_list;
245 }
246
247 r = clist_append(list, new_mb);
248 if (r != 0) {
249 free(new_mb);
250 res = MAIL_ERROR_MEMORY;
251 goto free_list;
252 }
253 }
254
255 resp = mail_list_new(list);
256 if (resp == NULL) {
257 res = MAIL_ERROR_MEMORY;
258 goto free_list;
259 }
260
261 * result = resp;
262
263 return MAIL_NO_ERROR;
264
265 free_list:
266 clist_foreach(list, (clist_func) free, NULL);
267 clist_free(list);
268 err:
269 return res;
270}
271
272int
273section_to_imap_section(struct mailmime_section * section, int type,
274 struct mailimap_section ** result)
275{
276 struct mailimap_section_part * section_part;
277 struct mailimap_section * imap_section;
278 clist * list;
279 clistiter * cur;
280 int r;
281 int res;
282
283 list = clist_new();
284 if (list == NULL) {
285 res = MAIL_ERROR_MEMORY;
286 goto err;
287 }
288
289 for(cur = clist_begin(section->sec_list) ; cur != NULL ;
290 cur = clist_next(cur)) {
291 uint32_t value;
292 uint32_t * id;
293
294 value = * (uint32_t *) clist_content(cur);
295 id = malloc(sizeof(* id));
296 if (id == NULL) {
297 res = MAIL_ERROR_MEMORY;
298 goto free_list;
299 }
300 * id = value;
301 r = clist_append(list, id);
302 if (r != 0) {
303 res = MAIL_ERROR_MEMORY;
304 free(id);
305 goto free_list;
306 }
307 }
308
309 section_part = mailimap_section_part_new(list);
310 if (section_part == NULL) {
311 res = MAIL_ERROR_MEMORY;
312 goto free_list;
313 }
314
315 imap_section = NULL;
316
317 switch (type) {
318 case IMAP_SECTION_MESSAGE:
319 imap_section = mailimap_section_new_part(section_part);
320 break;
321 case IMAP_SECTION_HEADER:
322 imap_section = mailimap_section_new_part_header(section_part);
323 break;
324 case IMAP_SECTION_MIME:
325 imap_section = mailimap_section_new_part_mime(section_part);
326 break;
327 case IMAP_SECTION_BODY:
328 imap_section = mailimap_section_new_part_text(section_part);
329 break;
330 }
331
332 if (imap_section == NULL) {
333 res = MAIL_ERROR_MEMORY;
334 goto free_part;
335 }
336
337 * result = imap_section;
338
339 return MAIL_NO_ERROR;
340
341 free_part:
342 mailimap_section_part_free(section_part);
343 free_list:
344 if (list != NULL) {
345 clist_foreach(list, (clist_func) free, NULL);
346 clist_free(list);
347 }
348 err:
349 return res;
350}
351
352
353
354static int
355imap_body_media_basic_to_content_type(struct mailimap_media_basic *
356 media_basic,
357 struct mailimap_body_fld_param *
358 body_parameter,
359 struct mailmime_content ** result)
360{
361 struct mailmime_content * content;
362 struct mailmime_type * mime_type;
363 struct mailmime_discrete_type * discrete_type;
364 struct mailmime_composite_type * composite_type;
365 char * discrete_type_extension;
366 int discrete_type_type;
367 int composite_type_type;
368 int mime_type_type;
369 char * subtype;
370 int r;
371 int res;
372
373 discrete_type = NULL;
374 composite_type = NULL;
375 discrete_type_extension = NULL;
376 subtype = NULL;
377 discrete_type_type = 0;
378 composite_type_type = 0;
379 mime_type_type = 0;
380
381 switch (media_basic->med_type) {
382 case MAILIMAP_MEDIA_BASIC_APPLICATION:
383 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
384 discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION;
385 break;
386
387 case MAILIMAP_MEDIA_BASIC_AUDIO:
388 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
389 discrete_type_type = MAILMIME_DISCRETE_TYPE_APPLICATION;
390 break;
391
392 case MAILIMAP_MEDIA_BASIC_IMAGE:
393 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
394 discrete_type_type = MAILMIME_DISCRETE_TYPE_IMAGE;
395 break;
396
397 case MAILIMAP_MEDIA_BASIC_MESSAGE:
398 mime_type_type = MAILMIME_TYPE_COMPOSITE_TYPE;
399 composite_type_type = MAILMIME_COMPOSITE_TYPE_MESSAGE;
400 break;
401
402 case MAILIMAP_MEDIA_BASIC_VIDEO:
403 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
404 discrete_type_type = MAILMIME_DISCRETE_TYPE_VIDEO;
405 break;
406
407 case MAILIMAP_MEDIA_BASIC_OTHER:
408 mime_type_type = MAILMIME_TYPE_DISCRETE_TYPE;
409 discrete_type_type = MAILMIME_DISCRETE_TYPE_EXTENSION;
410 discrete_type_extension = media_basic->med_basic_type;
411 if (discrete_type_extension == NULL) {
412 res = MAIL_ERROR_INVAL;
413 goto err;
414 }
415
416 break;
417
418 default:
419 res = MAIL_ERROR_INVAL;
420 goto err;
421 }
422
423 switch (mime_type_type) {
424 case MAILMIME_TYPE_DISCRETE_TYPE:
425 if (discrete_type_extension != NULL) {
426 discrete_type_extension = strdup(discrete_type_extension);
427 if (discrete_type_extension == NULL) {
428 res = MAIL_ERROR_MEMORY;
429 goto err;
430 }
431 }
432
433 discrete_type = mailmime_discrete_type_new(discrete_type_type,
434 discrete_type_extension);
435 if (discrete_type == NULL) {
436 if (discrete_type_extension != NULL)
437 free(discrete_type_extension);
438 res = MAIL_ERROR_MEMORY;
439 goto err;
440 }
441
442 break;
443
444 case MAILMIME_TYPE_COMPOSITE_TYPE:
445 composite_type = mailmime_composite_type_new(composite_type_type,
446 NULL);
447 if (composite_type == NULL) {
448 res = MAIL_ERROR_MEMORY;
449 goto err;
450 }
451
452 break;
453
454 default:
455 res = MAIL_ERROR_INVAL;
456 goto err;
457 }
458
459 mime_type = mailmime_type_new(mime_type_type, discrete_type, composite_type);
460 if (mime_type == NULL) {
461 res = MAIL_ERROR_MEMORY;
462 goto free;
463 }
464
465 r = imap_body_parameter_to_content(body_parameter, media_basic->med_subtype,
466 mime_type, &content);
467 if (r != MAIL_NO_ERROR) {
468 res = r;
469 goto free_type;
470 }
471
472 * result = content;
473
474 return MAIL_NO_ERROR;
475
476 free_type:
477 mailmime_type_free(mime_type);
478 free:
479 if (discrete_type != NULL)
480 mailmime_discrete_type_free(discrete_type);
481 if (composite_type != NULL)
482 mailmime_composite_type_free(composite_type);
483 err:
484 return res;
485}
486
487static int
488imap_disposition_to_mime_disposition(struct mailimap_body_fld_dsp * imap_dsp,
489 struct mailmime_disposition ** result)
490{
491 size_t cur_token;
492 int r;
493 struct mailmime_disposition_type * dsp_type;
494 struct mailmime_disposition * dsp;
495 clist * parameters;
496 int res;
497
498 cur_token = 0;
499 r = mailmime_disposition_type_parse(imap_dsp->dsp_type,
500 strlen(imap_dsp->dsp_type), &cur_token, &dsp_type);
501 if (r != MAILIMF_NO_ERROR) {
502 res = MAILIMF_ERROR_PARSE;
503 goto err;
504 }
505
506 parameters = clist_new();
507 if (parameters == NULL) {
508 res = MAIL_ERROR_MEMORY;
509 goto err;
510 }
511
512 if (imap_dsp->dsp_attributes != NULL) {
513 clistiter * cur;
514
515 for(cur = clist_begin(imap_dsp->dsp_attributes->pa_list) ; cur != NULL ;
516 cur = clist_next(cur)) {
517 struct mailimap_single_body_fld_param * imap_param;
518 struct mailmime_disposition_parm * dsp_param;
519 struct mailmime_parameter * param;
520 char * filename;
521 char * creation_date;
522 char * modification_date;
523 char * read_date;
524 size_t size;
525 int type;
526
527 imap_param = clist_content(cur);
528
529 filename = NULL;
530 creation_date = NULL;
531 modification_date = NULL;
532 read_date = NULL;
533 size = 0;
534 param = NULL;
535
536 type = mailmime_disposition_guess_type(imap_param->pa_name,
537 strlen(imap_param->pa_name), 0);
538
539 switch (type) {
540 case MAILMIME_DISPOSITION_PARM_FILENAME:
541 if (strcasecmp(imap_param->pa_name, "filename") != 0) {
542 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
543 break;
544 }
545 filename = strdup(imap_param->pa_value);
546 if (filename == NULL) {
547 res = MAIL_ERROR_MEMORY;
548 goto free_dsp_type;
549 }
550 break;
551
552 case MAILMIME_DISPOSITION_PARM_CREATION_DATE:
553 if (strcasecmp(imap_param->pa_name, "creation-date") != 0) {
554 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
555 break;
556 }
557 creation_date = strdup(imap_param->pa_value);
558 if (creation_date == NULL) {
559 res = MAIL_ERROR_MEMORY;
560 goto free_dsp_type;
561 }
562 break;
563
564 case MAILMIME_DISPOSITION_PARM_MODIFICATION_DATE:
565 if (strcasecmp(imap_param->pa_name, "modification-date") != 0) {
566 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
567 break;
568 }
569 modification_date = strdup(imap_param->pa_value);
570 if (modification_date == NULL) {
571 res = MAIL_ERROR_MEMORY;
572 goto free_dsp_type;
573 }
574 break;
575
576 case MAILMIME_DISPOSITION_PARM_READ_DATE:
577 if (strcasecmp(imap_param->pa_name, "read-date") != 0) {
578 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
579 break;
580 }
581 read_date = strdup(imap_param->pa_value);
582 if (read_date == NULL) {
583 res = MAIL_ERROR_MEMORY;
584 goto free_dsp_type;
585 }
586 break;
587
588 case MAILMIME_DISPOSITION_PARM_SIZE:
589 if (strcasecmp(imap_param->pa_name, "size") != 0) {
590 type = MAILMIME_DISPOSITION_PARM_PARAMETER;
591 break;
592 }
593 size = strtoul(imap_param->pa_value, NULL, 10);
594 break;
595 }
596
597 if (type == MAILMIME_DISPOSITION_PARM_PARAMETER) {
598 char * name;
599 char * value;
600
601 name = strdup(imap_param->pa_name);
602 if (name == NULL) {
603 res = MAIL_ERROR_MEMORY;
604 goto free_dsp_type;
605 }
606
607 value = strdup(imap_param->pa_value);
608 if (value == NULL) {
609 res = MAIL_ERROR_MEMORY;
610 free(name);
611 goto free_dsp_type;
612 }
613
614 param = mailmime_parameter_new(name, value);
615 if (param == NULL) {
616 free(value);
617 free(name);
618 res = MAIL_ERROR_MEMORY;
619 goto free_dsp_type;
620 }
621
622 }
623
624 dsp_param = mailmime_disposition_parm_new(type, filename,
625 creation_date,
626 modification_date,
627 read_date,
628 size, param);
629 if (dsp_param == NULL) {
630 if (filename != NULL)
631 free(filename);
632 if (creation_date != NULL)
633 free(creation_date);
634 if (modification_date != NULL)
635 free(modification_date);
636 if (read_date != NULL)
637 free(read_date);
638 if (param != NULL)
639 mailmime_parameter_free(param);
640 res = MAIL_ERROR_MEMORY;
641 goto free_list;
642 }
643
644 r = clist_append(parameters, dsp_param);
645 if (r != 0) {
646 mailmime_disposition_parm_free(dsp_param);
647 res = MAIL_ERROR_MEMORY;
648 goto free_list;
649 }
650 }
651 }
652
653 dsp = mailmime_disposition_new(dsp_type, parameters);
654 if (dsp == NULL) {
655 res = MAIL_ERROR_MEMORY;
656 goto free_list;
657 }
658
659 * result = dsp;
660
661 return MAIL_NO_ERROR;
662
663 free_list:
664 clist_foreach(parameters,
665 (clist_func) mailmime_disposition_parm_free, NULL);
666 clist_free(parameters);
667 free_dsp_type:
668 mailmime_disposition_type_free(dsp_type);
669 err:
670 return res;
671}
672
673static int
674imap_language_to_mime_language(struct mailimap_body_fld_lang * imap_lang,
675 struct mailmime_language ** result)
676{
677 clist * list;
678 clistiter * cur;
679 int res;
680 char * single;
681 int r;
682 struct mailmime_language * lang;
683
684 list = clist_new();
685 if (list == NULL) {
686 res = MAIL_ERROR_MEMORY;
687 goto err;
688 }
689
690 switch (imap_lang->lg_type) {
691 case MAILIMAP_BODY_FLD_LANG_SINGLE:
692 if (imap_lang->lg_data.lg_single != NULL) {
693 single = strdup(imap_lang->lg_data.lg_single);
694 if (single == NULL) {
695 res = MAIL_ERROR_MEMORY;
696 goto free;
697 }
698 r = clist_append(list, single);
699 if (r < 0) {
700 free(single);
701 res = MAIL_ERROR_MEMORY;
702 goto free;
703 }
704 }
705
706 break;
707
708 case MAILIMAP_BODY_FLD_LANG_LIST:
709 for(cur = clist_begin(imap_lang->lg_data.lg_list) ;
710 cur != NULL ; cur = clist_next(cur)) {
711 single = strdup(clist_content(cur));
712 if (single == NULL) {
713 res = MAIL_ERROR_MEMORY;
714 goto free;
715 }
716 r = clist_append(list, single);
717 if (r < 0) {
718 free(single);
719 res = MAIL_ERROR_MEMORY;
720 goto free;
721 }
722 }
723 }
724
725 lang = mailmime_language_new(list);
726 if (lang == NULL) {
727 res = MAIL_ERROR_MEMORY;
728 goto free;
729 }
730
731 * result = lang;
732
733 return MAIL_NO_ERROR;
734
735 free:
736 clist_foreach(list, (clist_func) free, NULL);
737 clist_free(list);
738 err:
739 return res;
740}
741
742static int
743imap_body_fields_to_mime_fields(struct mailimap_body_fields * body_fields,
744 struct mailimap_body_fld_dsp * imap_dsp,
745 struct mailimap_body_fld_lang * imap_lang,
746 struct mailmime_fields ** result,
747 uint32_t * pbody_size)
748{
749 struct mailmime_field * mime_field;
750 struct mailmime_fields * mime_fields;
751 clist * list;
752 char * id;
753 struct mailmime_mechanism * encoding;
754 char * description;
755 struct mailmime_disposition * dsp;
756 struct mailmime_language * lang;
757 int type;
758 int r;
759 int res;
760
761 list = clist_new();
762 if (list == NULL) {
763 res = MAIL_ERROR_MEMORY;
764 goto err;
765 }
766
767 if (body_fields != NULL) {
768
769 if (pbody_size != NULL)
770 * pbody_size = body_fields->bd_size;
771
772 if (body_fields->bd_id != NULL) {
773 type = MAILMIME_FIELD_ID;
774 id = strdup(body_fields->bd_id);
775 if (id == NULL) {
776 res = MAIL_ERROR_MEMORY;
777 goto free_list;
778 }
779
780 mime_field = mailmime_field_new(type, NULL,
781 NULL, id, NULL, 0, NULL, NULL);
782 if (mime_field == NULL) {
783 free(id);
784 res = MAIL_ERROR_MEMORY;
785 goto free_list;
786 }
787
788 r = clist_append(list, mime_field);
789 if (r != 0) {
790 mailmime_field_free(mime_field);
791 res = MAIL_ERROR_MEMORY;
792 goto free_list;
793 }
794 }
795
796 if (body_fields->bd_description != NULL) {
797 type = MAILMIME_FIELD_DESCRIPTION;
798 description = strdup(body_fields->bd_description);
799 if (description == NULL) {
800 res = MAIL_ERROR_MEMORY;
801 goto free_list;
802 }
803
804 mime_field = mailmime_field_new(type, NULL,
805 NULL, NULL, description, 0, NULL, NULL);
806 if (mime_field == NULL) {
807 free(description);
808 res = MAIL_ERROR_MEMORY;
809 goto free_list;
810 }
811
812 r = clist_append(list, mime_field);
813 if (r != 0) {
814 mailmime_field_free(mime_field);
815 res = MAIL_ERROR_MEMORY;
816 goto free_list;
817 }
818 }
819
820 if (body_fields->bd_encoding != NULL) {
821 char * encoding_value;
822 int encoding_type;
823
824 type = MAILMIME_FIELD_TRANSFER_ENCODING;
825
826 encoding_value = NULL;
827 switch (body_fields->bd_encoding->enc_type) {
828 case MAILIMAP_BODY_FLD_ENC_7BIT:
829 encoding_type = MAILMIME_MECHANISM_7BIT;
830 break;
831 case MAILIMAP_BODY_FLD_ENC_8BIT:
832 encoding_type = MAILMIME_MECHANISM_8BIT;
833 break;
834 case MAILIMAP_BODY_FLD_ENC_BINARY:
835 encoding_type = MAILMIME_MECHANISM_BINARY;
836 break;
837 case MAILIMAP_BODY_FLD_ENC_BASE64:
838 encoding_type = MAILMIME_MECHANISM_BASE64;
839 break;
840 case MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE:
841 encoding_type = MAILMIME_MECHANISM_QUOTED_PRINTABLE;
842 break;
843 case MAILIMAP_BODY_FLD_ENC_OTHER:
844 encoding_type = MAILMIME_MECHANISM_TOKEN;
845 encoding_value = strdup(body_fields->bd_encoding->enc_value);
846 if (encoding_value == NULL) {
847 res = MAIL_ERROR_MEMORY;
848 goto free_list;
849 }
850 break;
851 default:
852 res = MAIL_ERROR_INVAL;
853 goto free_list;
854 }
855
856 encoding = mailmime_mechanism_new(encoding_type, encoding_value);
857 if (encoding == NULL) {
858 if (encoding_value != NULL)
859 free(encoding_value);
860 res = MAIL_ERROR_MEMORY;
861 goto free_list;
862 }
863
864 mime_field = mailmime_field_new(type, NULL,
865 encoding, NULL, NULL, 0, NULL, NULL);
866 if (mime_field == NULL) {
867 mailmime_mechanism_free(encoding);
868 res = MAIL_ERROR_MEMORY;
869 goto free_list;
870 }
871
872 r = clist_append(list, mime_field);
873 if (r != 0) {
874 mailmime_field_free(mime_field);
875 res = MAIL_ERROR_MEMORY;
876 goto free_list;
877 }
878 }
879 }
880
881 if (imap_dsp != NULL) {
882 r = imap_disposition_to_mime_disposition(imap_dsp, &dsp);
883 if (r != MAIL_ERROR_PARSE) {
884 if (r != MAIL_NO_ERROR) {
885 res = MAIL_ERROR_MEMORY;
886 goto free_list;
887 }
888
889 type = MAILMIME_FIELD_DISPOSITION;
890
891 mime_field = mailmime_field_new(type, NULL,
892 NULL, NULL, NULL, 0, dsp, NULL);
893 if (mime_field == NULL) {
894 mailmime_disposition_free(dsp);
895 res = MAIL_ERROR_MEMORY;
896 goto free_list;
897 }
898
899 r = clist_append(list, mime_field);
900 if (r != 0) {
901 mailmime_field_free(mime_field);
902 res = MAIL_ERROR_MEMORY;
903 goto free_list;
904 }
905 }
906 }
907
908 if (imap_lang != NULL) {
909 r = imap_language_to_mime_language(imap_lang, &lang);
910 if (r != MAIL_NO_ERROR) {
911 res = MAIL_ERROR_MEMORY;
912 goto free_list;
913 }
914
915 type = MAILMIME_FIELD_LANGUAGE;
916
917 mime_field = mailmime_field_new(type, NULL,
918 NULL, NULL, NULL, 0, NULL, lang);
919 if (mime_field == NULL) {
920 mailmime_language_free(lang);
921 res = MAIL_ERROR_MEMORY;
922 goto free_list;
923 }
924
925 r = clist_append(list, mime_field);
926 if (r != 0) {
927 mailmime_field_free(mime_field);
928 res = MAIL_ERROR_MEMORY;
929 goto free_list;
930 }
931 }
932
933 mime_fields = mailmime_fields_new(list);
934 if (mime_fields == NULL) {
935 res = MAIL_ERROR_MEMORY;
936 goto free_list;
937 }
938
939 * result = mime_fields;
940
941 return MAIL_NO_ERROR;
942
943 free_list:
944 clist_foreach(list, (clist_func) mailmime_fields_free, NULL);
945 clist_free(list);
946 err:
947 return res;
948}
949
950static int
951imap_body_type_basic_to_body(struct mailimap_body_type_basic *
952 imap_type_basic,
953 struct mailimap_body_ext_1part *
954 body_ext_1part,
955 struct mailmime ** result)
956{
957 struct mailmime_content * content;
958 struct mailmime_fields * mime_fields;
959 struct mailmime * body;
960 int r;
961 int res;
962 uint32_t mime_size;
963
964 r = imap_body_media_basic_to_content_type(imap_type_basic->bd_media_basic,
965 imap_type_basic->bd_fields->bd_parameter, &content);
966 if (r != MAIL_NO_ERROR) {
967 res = r;
968 goto err;
969 }
970
971 if (body_ext_1part != NULL)
972 r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields,
973 body_ext_1part->bd_disposition,
974 body_ext_1part->bd_language,
975 &mime_fields, &mime_size);
976 else
977 r = imap_body_fields_to_mime_fields(imap_type_basic->bd_fields,
978 NULL, NULL,
979 &mime_fields, &mime_size);
980 if (r != MAIL_NO_ERROR) {
981 res = r;
982 goto free_content;
983 }
984
985 body = mailmime_new(MAILMIME_SINGLE, NULL,
986 mime_size, mime_fields, content,
987 NULL, NULL, NULL, NULL, NULL, NULL);
988
989 if (body == NULL) {
990 res = MAIL_ERROR_MEMORY;
991 goto free_fields;
992 }
993
994 * result = body;
995
996 return MAIL_NO_ERROR;
997
998 free_fields:
999 mailmime_fields_free(mime_fields);
1000 free_content:
1001 mailmime_content_free(content);
1002 err:
1003 return res;
1004}
1005
1006static int
1007imap_body_type_text_to_body(struct mailimap_body_type_text *
1008 imap_type_text,
1009 struct mailimap_body_ext_1part *
1010 body_ext_1part,
1011 struct mailmime ** result)
1012{
1013 struct mailmime_content * content;
1014 struct mailmime_fields * mime_fields;
1015 struct mailmime * body;
1016 int r;
1017 int res;
1018 uint32_t mime_size;
1019
1020 r = imap_body_type_text_to_content_type(imap_type_text->bd_media_text,
1021 imap_type_text->bd_fields->bd_parameter,
1022 &content);
1023 if (r != MAIL_NO_ERROR) {
1024 res = r;
1025 goto err;
1026 }
1027
1028 if (body_ext_1part == NULL) {
1029 r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields,
1030 NULL, NULL,
1031 &mime_fields, &mime_size);
1032 }
1033 else {
1034 r = imap_body_fields_to_mime_fields(imap_type_text->bd_fields,
1035 body_ext_1part->bd_disposition,
1036 body_ext_1part->bd_language,
1037 &mime_fields, &mime_size);
1038 }
1039 if (r != MAIL_NO_ERROR) {
1040 res = r;
1041 goto free_content;
1042 }
1043
1044 body = mailmime_new(MAILMIME_SINGLE, NULL,
1045 mime_size, mime_fields, content,
1046 NULL, NULL, NULL, NULL, NULL, NULL);
1047
1048 if (body == NULL) {
1049 res = MAIL_ERROR_MEMORY;
1050 goto free_fields;
1051 }
1052
1053 * result = body;
1054
1055 return MAIL_NO_ERROR;
1056
1057 free_fields:
1058 mailmime_fields_free(mime_fields);
1059 free_content:
1060 mailmime_content_free(content);
1061 err:
1062 return res;
1063}
1064
1065static int
1066imap_body_parameter_to_content(struct mailimap_body_fld_param *
1067 body_parameter,
1068 char * subtype,
1069 struct mailmime_type * mime_type,
1070 struct mailmime_content ** result)
1071{
1072 clist * parameters;
1073 char * new_subtype;
1074 struct mailmime_content * content;
1075 int r;
1076 int res;
1077
1078 new_subtype = strdup(subtype);
1079 if (new_subtype == NULL) {
1080 res = MAIL_ERROR_MEMORY;
1081 goto err;
1082 }
1083
1084 parameters = clist_new();
1085 if (parameters == NULL) {
1086 res = MAIL_ERROR_MEMORY;
1087 goto free_subtype;
1088 }
1089
1090 if (body_parameter != NULL) {
1091 clistiter * cur;
1092
1093 for(cur = clist_begin(body_parameter->pa_list) ; cur != NULL ;
1094 cur = clist_next(cur)) {
1095 struct mailimap_single_body_fld_param * imap_param;
1096 struct mailmime_parameter * param;
1097 char * name;
1098 char * value;
1099
1100 imap_param = clist_content(cur);
1101 name = strdup(imap_param->pa_name);
1102 if (name == NULL) {
1103 res = MAIL_ERROR_MEMORY;
1104 goto free_parameters;
1105 }
1106
1107 value = strdup(imap_param->pa_value);
1108 if (value == NULL) {
1109 free(name);
1110 res = MAIL_ERROR_MEMORY;
1111 goto free_parameters;
1112 }
1113
1114 param = mailmime_parameter_new(name, value);
1115 if (param == NULL) {
1116 free(value);
1117 free(name);
1118 res = MAIL_ERROR_MEMORY;
1119 goto free_parameters;
1120 }
1121
1122 r = clist_append(parameters, param);
1123 if (r != 0) {
1124 mailmime_parameter_free(param);
1125 res = MAIL_ERROR_MEMORY;
1126 goto free_parameters;
1127 }
1128 }
1129 }
1130
1131 content = mailmime_content_new(mime_type, new_subtype, parameters);
1132 if (content == NULL) {
1133 res = MAIL_ERROR_MEMORY;
1134 goto free_parameters;
1135 }
1136
1137 * result = content;
1138
1139 return MAIL_NO_ERROR;
1140
1141 free_parameters:
1142 clist_foreach(parameters, (clist_func) mailmime_parameter_free, NULL);
1143 clist_free(parameters);
1144 free_subtype:
1145 free(new_subtype);
1146 err:
1147 return res;
1148}
1149
1150static int
1151imap_body_type_text_to_content_type(char * subtype,
1152 struct mailimap_body_fld_param *
1153 body_parameter,
1154 struct mailmime_content ** result)
1155{
1156 struct mailmime_content * content;
1157 struct mailmime_type * mime_type;
1158 struct mailmime_discrete_type * discrete_type;
1159 int r;
1160 int res;
1161
1162 discrete_type = NULL;
1163
1164 discrete_type = mailmime_discrete_type_new(MAILMIME_DISCRETE_TYPE_TEXT,
1165 NULL);
1166 if (discrete_type == NULL) {
1167 res = MAIL_ERROR_MEMORY;
1168 goto err;
1169 }
1170
1171 mime_type = mailmime_type_new(MAILMIME_TYPE_DISCRETE_TYPE,
1172 discrete_type, NULL);
1173 if (mime_type == NULL) {
1174 mailmime_discrete_type_free(discrete_type);
1175 res = MAIL_ERROR_MEMORY;
1176 goto err;
1177 }
1178
1179 r = imap_body_parameter_to_content(body_parameter, subtype,
1180 mime_type, &content);
1181 if (r != MAIL_NO_ERROR) {
1182 res = r;
1183 goto free_type;
1184 }
1185
1186 * result = content;
1187
1188 return MAIL_NO_ERROR;
1189
1190 free_type:
1191 mailmime_type_free(mime_type);
1192 err:
1193 return res;
1194}
1195
1196
1197static int
1198imap_body_type_msg_to_body(struct mailimap_body_type_msg *
1199 imap_type_msg,
1200 struct mailimap_body_ext_1part *
1201 body_ext_1part,
1202 struct mailmime ** result)
1203{
1204 struct mailmime * body;
1205 struct mailmime * msg_body;
1206 struct mailmime_fields * mime_fields;
1207 struct mailmime_composite_type * composite_type;
1208 struct mailmime_type * mime_type;
1209 struct mailmime_content * content_type;
1210 struct mailimf_fields * fields;
1211 int r;
1212 int res;
1213 uint32_t mime_size;
1214
1215 r = imap_body_fields_to_mime_fields(imap_type_msg->bd_fields,
1216 body_ext_1part->bd_disposition, body_ext_1part->bd_language,
1217 &mime_fields, &mime_size);
1218 if (r != MAIL_NO_ERROR) {
1219 res = r;
1220 goto err;
1221 }
1222
1223 r = imap_env_to_fields(imap_type_msg->bd_envelope, NULL, 0, &fields);
1224 if (r != MAIL_NO_ERROR) {
1225 res = r;
1226 goto free_mime_fields;
1227 }
1228
1229 r = imap_body_to_body(imap_type_msg->bd_body, &msg_body);
1230 if (r != MAIL_NO_ERROR) {
1231 res = r;
1232 goto free_fields;
1233 }
1234
1235 composite_type =
1236 mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MESSAGE,
1237 NULL);
1238 if (composite_type == NULL) {
1239 res = MAIL_ERROR_MEMORY;
1240 goto free_fields;
1241 }
1242
1243 mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE,
1244 NULL, composite_type);
1245 if (mime_type == NULL) {
1246 mailmime_composite_type_free(composite_type);
1247 res = MAIL_ERROR_MEMORY;
1248 goto free_fields;
1249 }
1250
1251 r = imap_body_parameter_to_content(imap_type_msg->bd_fields->bd_parameter,
1252 "rfc822", mime_type, &content_type);
1253 if (r != MAIL_NO_ERROR) {
1254 mailmime_type_free(mime_type);
1255 res = MAIL_ERROR_MEMORY;
1256 goto free_fields;
1257 }
1258
1259 body = mailmime_new(MAILMIME_MESSAGE, NULL,
1260 mime_size, mime_fields, content_type,
1261 NULL, NULL, NULL, NULL, fields, msg_body);
1262
1263 if (body == NULL) {
1264 res = MAIL_ERROR_MEMORY;
1265 goto free_content;
1266 }
1267
1268 * result = body;
1269
1270 return MAIL_NO_ERROR;
1271
1272 free_content:
1273 mailmime_content_free(content_type);
1274 free_fields:
1275 mailimf_fields_free(fields);
1276 free_mime_fields:
1277 mailmime_fields_free(mime_fields);
1278 err:
1279 return res;
1280}
1281
1282
1283static int
1284imap_body_type_1part_to_body(struct mailimap_body_type_1part *
1285 type_1part,
1286 struct mailmime ** result)
1287{
1288 struct mailmime * body;
1289 int r;
1290 int res;
1291
1292 switch (type_1part->bd_type) {
1293 case MAILIMAP_BODY_TYPE_1PART_BASIC:
1294 r = imap_body_type_basic_to_body(type_1part->bd_data.bd_type_basic,
1295 type_1part->bd_ext_1part,
1296 &body);
1297 if (r != MAIL_NO_ERROR) {
1298 res = r;
1299 goto err;
1300 }
1301
1302 break;
1303 case MAILIMAP_BODY_TYPE_1PART_MSG:
1304 r = imap_body_type_msg_to_body(type_1part->bd_data.bd_type_msg,
1305 type_1part->bd_ext_1part,
1306 &body);
1307 if (r != MAIL_NO_ERROR) {
1308 res = r;
1309 goto err;
1310 }
1311
1312 break;
1313 case MAILIMAP_BODY_TYPE_1PART_TEXT:
1314 r = imap_body_type_text_to_body(type_1part->bd_data.bd_type_text,
1315 type_1part->bd_ext_1part,
1316 &body);
1317 if (r != MAIL_NO_ERROR) {
1318 res = r;
1319 goto err;
1320 }
1321
1322 break;
1323 }
1324
1325 * result = body;
1326
1327 return MAIL_NO_ERROR;
1328
1329 err:
1330 return res;
1331}
1332
1333static int
1334imap_body_type_mpart_to_body(struct mailimap_body_type_mpart *
1335 type_mpart,
1336 struct mailmime ** result)
1337{
1338 struct mailmime_fields * mime_fields;
1339 struct mailmime_composite_type * composite_type;
1340 struct mailmime_type * mime_type;
1341 struct mailmime_content * content_type;
1342 struct mailmime * body;
1343 clistiter * cur;
1344 clist * list;
1345 int r;
1346 int res;
1347 uint32_t mime_size;
1348
1349 r = imap_body_fields_to_mime_fields(NULL,
1350 type_mpart->bd_ext_mpart->bd_disposition,
1351 type_mpart->bd_ext_mpart->bd_language,
1352 &mime_fields, &mime_size);
1353 if (r != MAIL_NO_ERROR) {
1354 res = r;
1355 goto err;
1356 }
1357
1358 composite_type =
1359 mailmime_composite_type_new(MAILMIME_COMPOSITE_TYPE_MULTIPART,
1360 NULL);
1361 if (composite_type == NULL) {
1362 res = MAIL_ERROR_MEMORY;
1363 goto free_fields;
1364 }
1365
1366 mime_type = mailmime_type_new(MAILMIME_TYPE_COMPOSITE_TYPE,
1367 NULL, composite_type);
1368 if (mime_type == NULL) {
1369 mailmime_composite_type_free(composite_type);
1370 res = MAIL_ERROR_MEMORY;
1371 goto free_fields;
1372 }
1373
1374 r = imap_body_parameter_to_content(type_mpart->bd_ext_mpart->bd_parameter,
1375 type_mpart->bd_media_subtype,
1376 mime_type, &content_type);
1377 if (r != MAIL_NO_ERROR) {
1378 mailmime_type_free(mime_type);
1379 res = r;
1380 goto free_fields;
1381 }
1382
1383 list = clist_new();
1384 if (list == NULL) {
1385 res = MAIL_ERROR_MEMORY;
1386 goto free_content;
1387 }
1388
1389 for(cur = clist_begin(type_mpart->bd_list) ; cur != NULL ;
1390 cur = clist_next(cur)) {
1391 struct mailimap_body * imap_body;
1392 struct mailmime * sub_body;
1393
1394 imap_body = clist_content(cur);
1395
1396 r = imap_body_to_body(imap_body, &sub_body);
1397 if (r != MAIL_NO_ERROR) {
1398 res = r;
1399 goto free_list;
1400 }
1401
1402 r = clist_append(list, sub_body);
1403 if (r != 0) {
1404 mailmime_free(sub_body);
1405 res = r;
1406 goto free_list;
1407 }
1408 }
1409
1410 body = mailmime_new(MAILMIME_MULTIPLE, NULL,
1411 mime_size, mime_fields, content_type,
1412 NULL, NULL, NULL, list, NULL, NULL);
1413
1414 if (body == NULL) {
1415 res = MAIL_ERROR_MEMORY;
1416 goto err;
1417 }
1418
1419 * result = body;
1420
1421 return MAIL_NO_ERROR;
1422
1423 free_list:
1424 clist_foreach(list, (clist_func) mailmime_free, NULL);
1425 clist_free(list);
1426 free_content:
1427 mailmime_content_free(content_type);
1428 free_fields:
1429 mailmime_fields_free(mime_fields);
1430 err:
1431 return res;
1432}
1433
1434
1435int imap_body_to_body(struct mailimap_body * imap_body,
1436 struct mailmime ** result)
1437{
1438 struct mailmime * body;
1439 int r;
1440 int res;
1441
1442 switch (imap_body->bd_type) {
1443 case MAILIMAP_BODY_1PART:
1444 r = imap_body_type_1part_to_body(imap_body->bd_data.bd_body_1part, &body);
1445 if (r != MAIL_NO_ERROR) {
1446 res = r;
1447 goto err;
1448 }
1449 break;
1450 case MAILIMAP_BODY_MPART:
1451 r = imap_body_type_mpart_to_body(imap_body->bd_data.bd_body_mpart, &body);
1452 if (r != MAIL_NO_ERROR) {
1453 res = r;
1454 goto err;
1455 }
1456 break;
1457 default:
1458 return MAIL_ERROR_INVAL;
1459 }
1460
1461 * result = body;
1462
1463 return MAIL_NO_ERROR;
1464
1465 err:
1466 return res;
1467}
1468
1469int imap_address_to_mailbox(struct mailimap_address * imap_addr,
1470 struct mailimf_mailbox ** result)
1471{
1472 char * dsp_name;
1473 char * addr;
1474 struct mailimf_mailbox * mb;
1475 int res;
1476
1477 if (imap_addr->ad_personal_name == NULL)
1478 dsp_name = NULL;
1479 else {
1480 dsp_name = strdup(imap_addr->ad_personal_name);
1481 if (dsp_name == NULL) {
1482 res = MAIL_ERROR_MEMORY;
1483 goto err;
1484 }
1485 }
1486
1487 if (imap_addr->ad_host_name == NULL) {
1488 addr = strdup(imap_addr->ad_mailbox_name);
1489 if (addr == NULL) {
1490 res = MAIL_ERROR_MEMORY;
1491 goto free_name;
1492 }
1493 }
1494 else {
1495 addr = malloc(strlen(imap_addr->ad_mailbox_name) +
1496 strlen(imap_addr->ad_host_name) + 2);
1497 if (addr == NULL) {
1498 res = MAIL_ERROR_MEMORY;
1499 goto free_name;
1500 }
1501 strcpy(addr, imap_addr->ad_mailbox_name);
1502 strcat(addr, "@");
1503 strcat(addr, imap_addr->ad_host_name);
1504 }
1505
1506 mb = mailimf_mailbox_new(dsp_name, addr);
1507 if (mb == NULL) {
1508 res = MAIL_ERROR_MEMORY;
1509 goto free_addr;
1510 }
1511
1512 * result = mb;
1513
1514 return MAIL_NO_ERROR;
1515
1516 free_addr:
1517 free(addr);
1518 free_name:
1519 free(dsp_name);
1520 err:
1521 return res;
1522}
1523
1524int imap_address_to_address(struct mailimap_address * imap_addr,
1525 struct mailimf_address ** result)
1526{
1527 struct mailimf_address * addr;
1528 struct mailimf_mailbox * mb;
1529 int r;
1530 int res;
1531
1532 r = imap_address_to_mailbox(imap_addr, &mb);
1533 if (r != MAIL_NO_ERROR) {
1534 res = r;
1535 goto err;
1536 }
1537
1538 addr = mailimf_address_new(MAILIMF_ADDRESS_MAILBOX, mb, NULL);
1539 if (addr == NULL) {
1540 res = MAIL_ERROR_MEMORY;
1541 goto free_mb;
1542 }
1543
1544 * result = addr;
1545
1546 return MAIL_NO_ERROR;
1547
1548 free_mb:
1549 mailimf_mailbox_free(mb);
1550 err:
1551 return res;
1552}
1553
1554int
1555imap_mailbox_list_to_mailbox_list(clist * imap_mailbox_list,
1556 struct mailimf_mailbox_list ** result)
1557{
1558 clistiter * cur;
1559 clist * list;
1560 struct mailimf_mailbox_list * mb_list;
1561 int r;
1562 int res;
1563
1564 list = clist_new();
1565 if (list == NULL) {
1566 res = MAIL_ERROR_MEMORY;
1567 goto err;
1568 }
1569
1570 for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ;
1571 cur = clist_next(cur)) {
1572 struct mailimap_address * imap_addr;
1573 struct mailimf_mailbox * mb;
1574
1575 imap_addr = clist_content(cur);
1576
1577 if (imap_addr->ad_mailbox_name == NULL)
1578 continue;
1579
1580 r = imap_address_to_mailbox(imap_addr, &mb);
1581 if (r != MAIL_NO_ERROR) {
1582 res = r;
1583 goto free_list;
1584 }
1585
1586 r = clist_append(list, mb);
1587 if (r != 0) {
1588 mailimf_mailbox_free(mb);
1589 res = MAIL_ERROR_MEMORY;
1590 goto free_list;
1591 }
1592 }
1593
1594 mb_list = mailimf_mailbox_list_new(list);
1595 if (mb_list == NULL) {
1596 res = MAIL_ERROR_MEMORY;
1597 goto free_list;
1598 }
1599
1600 * result = mb_list;
1601
1602 return MAIL_NO_ERROR;
1603
1604 free_list:
1605 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
1606 clist_free(list);
1607 err:
1608 return MAIL_ERROR_MEMORY;
1609}
1610
1611
1612
1613/*
1614 at exit, imap_mb_list will fall on the last element of the group,
1615 where mailbox name will be NIL, so that imap_mailbox_list_to_address_list
1616 can continue
1617*/
1618
1619static int imap_mailbox_list_to_group(clist * imap_mb_list, clistiter ** iter,
1620 struct mailimf_group ** result)
1621{
1622 clistiter * imap_mailbox_listiter;
1623 clist * list;
1624 struct mailimf_group * group;
1625 struct mailimap_address * imap_addr;
1626 char * group_name;
1627 clistiter * cur;
1628 struct mailimf_mailbox_list * mb_list;
1629 int r;
1630 int res;
1631
1632 imap_mailbox_listiter = * iter;
1633
1634 imap_addr = clist_content(imap_mailbox_listiter);
1635 if (imap_addr->ad_mailbox_name == NULL) {
1636 res = MAIL_ERROR_INVAL;
1637 goto err;
1638 }
1639
1640 group_name = strdup(imap_addr->ad_mailbox_name);
1641 if (group_name == NULL) {
1642 res = MAIL_ERROR_MEMORY;
1643 goto err;
1644 }
1645
1646 list = clist_new();
1647 if (list == NULL) {
1648 res = MAIL_ERROR_MEMORY;
1649 goto free_group_name;
1650 }
1651
1652 for(cur = clist_next(imap_mailbox_listiter) ; cur != NULL ;
1653 cur = clist_next(cur)) {
1654 struct mailimf_mailbox * mb;
1655
1656 imap_addr = clist_content(cur);
1657
1658 if (imap_addr->ad_mailbox_name == NULL) {
1659 break;
1660 }
1661
1662 r = imap_address_to_mailbox(imap_addr, &mb);
1663 if (r != MAIL_NO_ERROR) {
1664 res = r;
1665 goto free_list;
1666 }
1667
1668 r = clist_append(list, mb);
1669 if (r != 0) {
1670 mailimf_mailbox_free(mb);
1671 res = MAIL_ERROR_MEMORY;
1672 goto free_list;
1673 }
1674 }
1675
1676 mb_list = mailimf_mailbox_list_new(list);
1677 if (mb_list == NULL) {
1678 res = MAIL_ERROR_MEMORY;
1679 goto free_list;
1680 }
1681
1682 group = mailimf_group_new(group_name, mb_list);
1683 if (group == NULL) {
1684 mailimf_mailbox_list_free(mb_list);
1685 res = MAIL_ERROR_MEMORY;
1686 goto free_group_name;
1687 }
1688
1689 * result = group;
1690 * iter = cur;
1691
1692 return MAIL_NO_ERROR;
1693
1694 free_list:
1695 clist_foreach(list, (clist_func) mailimf_mailbox_free, NULL);
1696 clist_free(list);
1697 free_group_name:
1698 free(group_name);
1699 err:
1700 return res;
1701}
1702
1703int
1704imap_mailbox_list_to_address_list(clist * imap_mailbox_list,
1705 struct mailimf_address_list ** result)
1706{
1707 clistiter * cur;
1708 clist * list;
1709 struct mailimf_address_list * addr_list;
1710 int r;
1711 int res;
1712
1713 list = clist_new();
1714 if (list == NULL) {
1715 res = MAIL_ERROR_MEMORY;
1716 goto err;
1717 }
1718
1719 for(cur = clist_begin(imap_mailbox_list) ; cur != NULL ;
1720 cur = clist_next(cur)) {
1721 struct mailimap_address * imap_addr;
1722 struct mailimf_address * addr;
1723
1724 imap_addr = clist_content(cur);
1725
1726 if (imap_addr->ad_mailbox_name == NULL)
1727 continue;
1728
1729 if ((imap_addr->ad_host_name == NULL) &&
1730 (imap_addr->ad_mailbox_name != NULL)) {
1731 struct mailimf_group * group;
1732
1733 r = imap_mailbox_list_to_group(imap_mailbox_list, &cur, &group);
1734 if (r != MAIL_NO_ERROR) {
1735 res = r;
1736 goto free_list;
1737 }
1738
1739 addr = mailimf_address_new(MAILIMF_ADDRESS_GROUP, NULL, group);
1740 if (addr == NULL) {
1741 mailimf_group_free(group);
1742 res = MAIL_ERROR_MEMORY;
1743 goto free_list;
1744 }
1745 }
1746 else {
1747 r = imap_address_to_address(imap_addr, &addr);
1748 if (r != MAIL_NO_ERROR) {
1749 res = r;
1750 goto free_list;
1751 }
1752 }
1753
1754 r = clist_append(list, addr);
1755 if (r != 0) {
1756 mailimf_address_free(addr);
1757 res = MAIL_ERROR_MEMORY;
1758 goto free_list;
1759 }
1760 }
1761
1762 addr_list = mailimf_address_list_new(list);
1763 if (addr_list == NULL) {
1764 res = MAIL_ERROR_MEMORY;
1765 goto free_list;
1766 }
1767
1768 * result = addr_list;
1769
1770 return MAIL_NO_ERROR;
1771
1772 free_list:
1773 clist_foreach(list, (clist_func) mailimf_address_free, NULL);
1774 clist_free(list);
1775 err:
1776 return res;
1777}
1778
1779
1780int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type)
1781{
1782 struct mailimap_fetch_att * fetch_att;
1783 int res;
1784 int r;
1785 char * header;
1786 clist * hdrlist;
1787 struct mailimap_header_list * imap_hdrlist;
1788 struct mailimap_section * section;
1789
1790 fetch_att = mailimap_fetch_att_new_envelope();
1791 if (fetch_att == NULL) {
1792 res = MAIL_ERROR_MEMORY;
1793 goto err;
1794 }
1795
1796 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1797 if (r != MAILIMAP_NO_ERROR) {
1798 mailimap_fetch_att_free(fetch_att);
1799 res = MAIL_ERROR_MEMORY;
1800 goto err;
1801 }
1802
1803 header = strdup("References");
1804 if (header == NULL) {
1805 mailimap_fetch_att_free(fetch_att);
1806 res = MAIL_ERROR_MEMORY;
1807 goto err;
1808 }
1809
1810 hdrlist = clist_new();
1811 if (hdrlist == NULL) {
1812 free(header);
1813 mailimap_fetch_att_free(fetch_att);
1814 res = MAIL_ERROR_MEMORY;
1815 goto err;
1816 }
1817
1818 r = clist_append(hdrlist, header);
1819 if (r < 0) {
1820 free(header);
1821 clist_foreach(hdrlist, (clist_func) free, NULL);
1822 clist_free(hdrlist);
1823 mailimap_fetch_att_free(fetch_att);
1824 res = MAIL_ERROR_MEMORY;
1825 goto err;
1826 }
1827
1828 imap_hdrlist = mailimap_header_list_new(hdrlist);
1829 if (imap_hdrlist == 0) {
1830 clist_foreach(hdrlist, (clist_func) free, NULL);
1831 clist_free(hdrlist);
1832 mailimap_fetch_att_free(fetch_att);
1833 res = MAIL_ERROR_MEMORY;
1834 goto err;
1835 }
1836
1837 section = mailimap_section_new_header_fields(imap_hdrlist);
1838 if (section == NULL) {
1839 mailimap_header_list_free(imap_hdrlist);
1840 mailimap_fetch_att_free(fetch_att);
1841 res = MAIL_ERROR_MEMORY;
1842 goto err;
1843 }
1844
1845 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1846 if (fetch_att == NULL) {
1847 mailimap_section_free(section);
1848 res = MAIL_ERROR_MEMORY;
1849 goto err;
1850 }
1851
1852 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1853 if (r != MAILIMAP_NO_ERROR) {
1854 mailimap_fetch_att_free(fetch_att);
1855 res = MAIL_ERROR_MEMORY;
1856 goto err;
1857 }
1858
1859 return MAIL_NO_ERROR;
1860
1861 err:
1862 return res;
1863}
1864
1865
1866int imap_env_to_fields(struct mailimap_envelope * env,
1867 char * ref_str, size_t ref_size,
1868 struct mailimf_fields ** result)
1869{
1870 clist * list;
1871 struct mailimf_field * field;
1872 int r;
1873 struct mailimf_fields * fields;
1874 int res;
1875
1876 list = clist_new();
1877 if (list == NULL) {
1878 res = MAIL_ERROR_MEMORY;
1879 goto err;
1880 }
1881
1882 if (env->env_date != NULL) {
1883 size_t cur_token;
1884 struct mailimf_date_time * date_time;
1885
1886 cur_token = 0;
1887 r = mailimf_date_time_parse(env->env_date, strlen(env->env_date),
1888 &cur_token, &date_time);
1889
1890 if (r == MAILIMF_NO_ERROR) {
1891 struct mailimf_orig_date * orig;
1892
1893 orig = mailimf_orig_date_new(date_time);
1894 if (orig == NULL) {
1895 mailimf_date_time_free(date_time);
1896 res = MAIL_ERROR_MEMORY;
1897 goto free_list;
1898 }
1899
1900 field = mailimf_field_new(MAILIMF_FIELD_ORIG_DATE,
1901 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1902 NULL, orig, NULL,
1903 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1904 NULL, NULL, NULL, NULL, NULL);
1905 if (field == NULL) {
1906 mailimf_orig_date_free(orig);
1907 res = MAIL_ERROR_MEMORY;
1908 goto free_list;
1909 }
1910
1911 r = clist_append(list, field);
1912 if (r != 0) {
1913 mailimf_field_free(field);
1914 res = MAIL_ERROR_MEMORY;
1915 goto free_list;
1916 }
1917 }
1918 }
1919
1920 if (env->env_subject != NULL) {
1921 char * subject;
1922 struct mailimf_subject * subject_field;
1923
1924 subject = strdup(env->env_subject);
1925 if (subject == NULL) {
1926 res = MAIL_ERROR_MEMORY;
1927 goto free_list;
1928 }
1929
1930
1931 subject_field = mailimf_subject_new(subject);
1932 if (subject_field == NULL) {
1933 free(subject);
1934 res = MAIL_ERROR_MEMORY;
1935 goto free_list;
1936 }
1937
1938 field = mailimf_field_new(MAILIMF_FIELD_SUBJECT,
1939 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1940 NULL, NULL, NULL,
1941 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1942 NULL, subject_field, NULL, NULL, NULL);
1943 if (field == NULL) {
1944 mailimf_subject_free(subject_field);
1945 res = MAIL_ERROR_MEMORY;
1946 goto free_list;
1947 }
1948
1949 r = clist_append(list, field);
1950 if (r != 0) {
1951 mailimf_field_free(field);
1952 res = MAIL_ERROR_MEMORY;
1953 goto free_list;
1954 }
1955 }
1956
1957 if (env->env_from != NULL) {
1958 if (env->env_from->frm_list != NULL) {
1959 struct mailimf_mailbox_list * mb_list;
1960 struct mailimf_from * from;
1961
1962 r = imap_mailbox_list_to_mailbox_list(env->env_from->frm_list, &mb_list);
1963
1964 if (r != MAIL_NO_ERROR) {
1965 res = r;
1966 goto free_list;
1967 }
1968
1969 from = mailimf_from_new(mb_list);
1970 if (from == NULL) {
1971 mailimf_mailbox_list_free(mb_list);
1972 res = MAIL_ERROR_MEMORY;
1973 goto free_list;
1974 }
1975
1976 field = mailimf_field_new(MAILIMF_FIELD_FROM,
1977 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1978 NULL, NULL, from,
1979 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
1980 NULL, NULL, NULL, NULL, NULL);
1981 if (field == NULL) {
1982 mailimf_from_free(from);
1983 res = MAIL_ERROR_MEMORY;
1984 goto free_list;
1985 }
1986
1987 r = clist_append(list, field);
1988 if (r != 0) {
1989 mailimf_field_free(field);
1990 res = MAIL_ERROR_MEMORY;
1991 goto free_list;
1992 }
1993 }
1994 }
1995
1996 if (env->env_sender != NULL) {
1997 if (env->env_sender->snd_list != NULL) {
1998 struct mailimf_sender * sender;
1999 struct mailimf_mailbox * mb;
2000
2001 r = imap_address_to_mailbox(clist_begin(env->env_sender->snd_list)->data, &mb);
2002
2003 if (r != MAIL_NO_ERROR) {
2004 res = r;
2005 goto free_list;
2006 }
2007
2008 sender = mailimf_sender_new(mb);
2009 if (sender == NULL) {
2010 mailimf_mailbox_free(mb);
2011 res = MAIL_ERROR_MEMORY;
2012 goto free_list;
2013 }
2014
2015 field = mailimf_field_new(MAILIMF_FIELD_SENDER,
2016 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2017 NULL, NULL, NULL,
2018 sender, NULL, NULL, NULL, NULL, NULL, NULL,
2019 NULL, NULL, NULL, NULL, NULL);
2020 if (field == NULL) {
2021 mailimf_sender_free(sender);
2022 res = MAIL_ERROR_MEMORY;
2023 goto free_list;
2024 }
2025
2026 r = clist_append(list, field);
2027 if (r != 0) {
2028 mailimf_field_free(field);
2029 res = MAIL_ERROR_MEMORY;
2030 goto free_list;
2031 }
2032 }
2033 }
2034
2035 if (env->env_reply_to != NULL) {
2036 if (env->env_reply_to->rt_list != NULL) {
2037 struct mailimf_address_list * addr_list;
2038 struct mailimf_reply_to * reply_to;
2039
2040 r = imap_mailbox_list_to_address_list(env->env_reply_to->rt_list,
2041 &addr_list);
2042
2043 if (r != MAIL_NO_ERROR) {
2044 res = r;
2045 goto free_list;
2046 }
2047
2048 reply_to = mailimf_reply_to_new(addr_list);
2049 if (reply_to == NULL) {
2050 mailimf_address_list_free(addr_list);
2051 res = MAIL_ERROR_MEMORY;
2052 goto free_list;
2053 }
2054
2055 field = mailimf_field_new(MAILIMF_FIELD_REPLY_TO,
2056 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2057 NULL, NULL, NULL,
2058 NULL, reply_to, NULL, NULL, NULL, NULL, NULL,
2059 NULL, NULL, NULL, NULL, NULL);
2060 if (field == NULL) {
2061 mailimf_reply_to_free(reply_to);
2062 res = MAIL_ERROR_MEMORY;
2063 goto free_list;
2064 }
2065
2066 r = clist_append(list, field);
2067 if (r != 0) {
2068 mailimf_field_free(field);
2069 res = MAIL_ERROR_MEMORY;
2070 goto free_list;
2071 }
2072 }
2073 }
2074
2075 if (env->env_to != NULL) {
2076 if (env->env_to->to_list != NULL) {
2077 struct mailimf_address_list * addr_list;
2078 struct mailimf_to * to;
2079
2080 r = imap_mailbox_list_to_address_list(env->env_to->to_list, &addr_list);
2081
2082 if (r != MAIL_NO_ERROR) {
2083 res = r;
2084 goto free_list;
2085 }
2086
2087 to = mailimf_to_new(addr_list);
2088 if (to == NULL) {
2089 mailimf_address_list_free(addr_list);
2090 res = MAIL_ERROR_MEMORY;
2091 goto free_list;
2092 }
2093
2094 field = mailimf_field_new(MAILIMF_FIELD_TO,
2095 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2096 NULL, NULL, NULL,
2097 NULL, NULL, to, NULL, NULL, NULL, NULL,
2098 NULL, NULL, NULL, NULL, NULL);
2099 if (field == NULL) {
2100 mailimf_to_free(to);
2101 res = MAIL_ERROR_MEMORY;
2102 goto free_list;
2103 }
2104
2105 r = clist_append(list, field);
2106 if (r != 0) {
2107 mailimf_field_free(field);
2108 res = MAIL_ERROR_MEMORY;
2109 goto free_list;
2110 }
2111 }
2112 }
2113
2114 if (env->env_cc != NULL) {
2115 if (env->env_cc->cc_list != NULL) {
2116 struct mailimf_address_list * addr_list;
2117 struct mailimf_cc * cc;
2118
2119 r = imap_mailbox_list_to_address_list(env->env_cc->cc_list, &addr_list);
2120
2121 if (r != MAIL_NO_ERROR) {
2122 res = r;
2123 goto free_list;
2124 }
2125
2126 cc = mailimf_cc_new(addr_list);
2127 if (cc == NULL) {
2128 mailimf_address_list_free(addr_list);
2129 res = MAIL_ERROR_MEMORY;
2130 goto free_list;
2131 }
2132
2133 field = mailimf_field_new(MAILIMF_FIELD_CC,
2134 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2135 NULL, NULL, NULL,
2136 NULL, NULL, NULL, cc, NULL, NULL, NULL,
2137 NULL, NULL, NULL, NULL, NULL);
2138 if (field == NULL) {
2139 mailimf_cc_free(cc);
2140 res = MAIL_ERROR_MEMORY;
2141 goto free_list;
2142 }
2143
2144 r = clist_append(list, field);
2145 if (r != 0) {
2146 mailimf_field_free(field);
2147 res = MAIL_ERROR_MEMORY;
2148 goto free_list;
2149 }
2150 }
2151 }
2152
2153 if (env->env_bcc != NULL) {
2154 if (env->env_bcc->bcc_list != NULL) {
2155 struct mailimf_address_list * addr_list;
2156 struct mailimf_bcc * bcc;
2157
2158 r = imap_mailbox_list_to_address_list(env->env_bcc->bcc_list,
2159 &addr_list);
2160
2161 if (r != MAIL_NO_ERROR) {
2162 res = r;
2163 goto free_list;
2164 }
2165
2166 bcc = mailimf_bcc_new(addr_list);
2167 if (bcc == NULL) {
2168 mailimf_address_list_free(addr_list);
2169 res = MAIL_ERROR_MEMORY;
2170 goto free_list;
2171 }
2172
2173 field = mailimf_field_new(MAILIMF_FIELD_BCC,
2174 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2175 NULL, NULL, NULL,
2176 NULL, NULL, NULL, NULL, bcc, NULL, NULL,
2177 NULL, NULL, NULL, NULL, NULL);
2178 if (field == NULL) {
2179 mailimf_bcc_free(bcc);
2180 res = MAIL_ERROR_MEMORY;
2181 goto free_list;
2182 }
2183
2184 r = clist_append(list, field);
2185 if (r != 0) {
2186 mailimf_field_free(field);
2187 res = MAIL_ERROR_MEMORY;
2188 goto free_list;
2189 }
2190 }
2191 }
2192
2193 if (env->env_in_reply_to != NULL) {
2194 struct mailimf_in_reply_to * in_reply_to;
2195 size_t cur_token;
2196 clist * msg_id_list;
2197
2198 cur_token = 0;
2199 r = mailimf_msg_id_list_parse(env->env_in_reply_to,
2200 strlen(env->env_in_reply_to), &cur_token, &msg_id_list);
2201
2202 switch (r) {
2203 case MAILIMF_NO_ERROR:
2204 in_reply_to = mailimf_in_reply_to_new(msg_id_list);
2205 if (in_reply_to == NULL) {
2206 clist_foreach(msg_id_list, (clist_func) mailimf_msg_id_free, NULL);
2207 clist_free(msg_id_list);
2208 res = MAIL_ERROR_MEMORY;
2209 goto free_list;
2210 }
2211
2212 field = mailimf_field_new(MAILIMF_FIELD_IN_REPLY_TO,
2213 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2214 NULL, NULL, NULL,
2215 NULL, NULL, NULL, NULL, NULL, NULL,
2216 in_reply_to,
2217 NULL, NULL, NULL, NULL, NULL);
2218 if (field == NULL) {
2219 mailimf_in_reply_to_free(in_reply_to);
2220 res = MAIL_ERROR_MEMORY;
2221 goto free_list;
2222 }
2223
2224 r = clist_append(list, field);
2225 if (r != 0) {
2226 mailimf_field_free(field);
2227 res = MAIL_ERROR_MEMORY;
2228 goto free_list;
2229 }
2230 break;
2231
2232 case MAILIMF_ERROR_PARSE:
2233 break;
2234
2235 default:
2236 res = maildriver_imf_error_to_mail_error(r);
2237 goto free_list;
2238 }
2239 }
2240
2241 if (env->env_message_id != NULL) {
2242 char * id;
2243 struct mailimf_message_id * msg_id;
2244 size_t cur_token;
2245
2246 cur_token = 0;
2247 r = mailimf_msg_id_parse(env->env_message_id, strlen(env->env_message_id),
2248 &cur_token, &id);
2249 switch (r) {
2250 case MAILIMF_NO_ERROR:
2251
2252 msg_id = mailimf_message_id_new(id);
2253 if (msg_id == NULL) {
2254 mailimf_msg_id_free(id);
2255 res = MAIL_ERROR_MEMORY;
2256 goto free_list;
2257 }
2258
2259 field = mailimf_field_new(MAILIMF_FIELD_MESSAGE_ID,
2260 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2261 NULL, NULL, NULL,
2262 NULL, NULL, NULL, NULL, NULL, msg_id, NULL,
2263 NULL, NULL, NULL, NULL, NULL);
2264 if (field == NULL) {
2265 mailimf_message_id_free(msg_id);
2266 res = MAIL_ERROR_MEMORY;
2267 goto free_list;
2268 }
2269
2270 r = clist_append(list, field);
2271 if (r != 0) {
2272 mailimf_field_free(field);
2273 res = MAIL_ERROR_MEMORY;
2274 goto free_list;
2275 }
2276 break;
2277
2278 case MAILIMF_ERROR_PARSE:
2279 break;
2280
2281 default:
2282 res = maildriver_imf_error_to_mail_error(r);
2283 goto free_list;
2284 }
2285 }
2286
2287 if (ref_str != NULL) {
2288 struct mailimf_references * references;
2289 size_t cur_token;
2290
2291 cur_token = 0;
2292 r = mailimf_references_parse(ref_str, ref_size,
2293 &cur_token, &references);
2294 switch (r) {
2295 case MAILIMF_NO_ERROR:
2296 field = mailimf_field_new(MAILIMF_FIELD_REFERENCES,
2297 NULL, NULL, NULL, NULL, NULL, NULL, NULL,
2298 NULL, NULL, NULL,
2299 NULL, NULL, NULL, NULL, NULL, NULL,
2300 NULL,
2301 references, NULL, NULL, NULL, NULL);
2302 if (field == NULL) {
2303 mailimf_references_free(references);
2304 res = MAIL_ERROR_MEMORY;
2305 goto free_list;
2306 }
2307
2308 r = clist_append(list, field);
2309 if (r < 0) {
2310 mailimf_field_free(field);
2311 res = MAIL_ERROR_MEMORY;
2312 goto free_list;
2313 }
2314 break;
2315
2316 case MAILIMF_ERROR_PARSE:
2317 break;
2318
2319 default:
2320 res = maildriver_imf_error_to_mail_error(r);
2321 goto free_list;
2322 }
2323 }
2324
2325 fields = mailimf_fields_new(list);
2326 if (fields == NULL) {
2327 res = MAIL_ERROR_MEMORY;
2328 goto free_list;
2329 }
2330
2331 * result = fields;
2332
2333 return MAIL_NO_ERROR;
2334
2335 free_list:
2336 clist_foreach(list, (clist_func) mailimf_field_free, NULL);
2337 clist_free(list);
2338 err:
2339 return res;
2340}
2341
2342int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
2343 uint32_t * puid,
2344 struct mailimap_envelope ** pimap_envelope,
2345 char ** preferences,
2346 size_t * pref_size,
2347 struct mailimap_msg_att_dynamic ** patt_dyn,
2348 struct mailimap_body ** pimap_body)
2349{
2350 clistiter * item_cur;
2351 uint32_t uid;
2352 struct mailimap_envelope * imap_envelope;
2353 char * references;
2354 size_t ref_size;
2355 struct mailimap_msg_att_dynamic * att_dyn;
2356 struct mailimap_body * imap_body;
2357
2358 uid = 0;
2359 imap_envelope = NULL;
2360 references = NULL;
2361 ref_size = 0;
2362 att_dyn = NULL;
2363 imap_body = NULL;
2364
2365 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
2366 item_cur = clist_next(item_cur)) {
2367 struct mailimap_msg_att_item * item;
2368
2369 item = clist_content(item_cur);
2370
2371 switch (item->att_type) {
2372 case MAILIMAP_MSG_ATT_ITEM_STATIC:
2373 switch (item->att_data.att_static->att_type) {
2374 case MAILIMAP_MSG_ATT_BODYSTRUCTURE:
2375 if (imap_body == NULL)
2376 imap_body = item->att_data.att_static->att_data.att_bodystructure;
2377 break;
2378
2379 case MAILIMAP_MSG_ATT_ENVELOPE:
2380 if (imap_envelope == NULL) {
2381 imap_envelope = item->att_data.att_static->att_data.att_env;
2382 }
2383 break;
2384
2385 case MAILIMAP_MSG_ATT_UID:
2386 uid = item->att_data.att_static->att_data.att_uid;
2387 break;
2388
2389 case MAILIMAP_MSG_ATT_BODY_SECTION:
2390 if (references == NULL) {
2391 references = item->att_data.att_static->att_data.att_body_section->sec_body_part;
2392 ref_size = item->att_data.att_static->att_data.att_body_section->sec_length;
2393 }
2394 break;
2395 }
2396 break;
2397
2398 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
2399 if (att_dyn == NULL) {
2400 att_dyn = item->att_data.att_dyn;
2401 }
2402 break;
2403 }
2404 }
2405
2406 if (puid != NULL)
2407 * puid = uid;
2408 if (pimap_envelope != NULL)
2409 * pimap_envelope = imap_envelope;
2410 if (preferences != NULL)
2411 * preferences = references;
2412 if (pref_size != NULL)
2413 * pref_size = ref_size;
2414 if (patt_dyn != NULL)
2415 * patt_dyn = att_dyn;
2416 if (pimap_body != NULL)
2417 * pimap_body = imap_body;
2418
2419 return MAIL_NO_ERROR;
2420}
2421
2422int
2423imap_fetch_result_to_envelop_list(clist * fetch_result,
2424 struct mailmessage_list * env_list)
2425{
2426 clistiter * cur;
2427 int r;
2428 unsigned int i;
2429
2430 i = 0;
2431
2432 for(cur = clist_begin(fetch_result) ; cur != NULL ;
2433 cur = clist_next(cur)) {
2434 struct mailimap_msg_att * msg_att;
2435 uint32_t uid;
2436 struct mailimap_envelope * imap_envelope;
2437 struct mailimap_msg_att_dynamic * att_dyn;
2438 char * references;
2439 size_t ref_size;
2440
2441 msg_att = clist_content(cur);
2442
2443 r = imap_get_msg_att_info(msg_att, &uid, &imap_envelope,
2444 &references, &ref_size,
2445 &att_dyn,
2446 NULL);
2447
2448 if (r == MAIL_NO_ERROR) {
2449 if (uid != 0) {
2450 while (i < carray_count(env_list->msg_tab)) {
2451 mailmessage * msg;
2452
2453 msg = carray_get(env_list->msg_tab, i);
2454
2455 if (uid == msg->msg_index) {
2456 struct mailimf_fields * fields;
2457 struct mail_flags * flags;
2458
2459 if (imap_envelope != NULL) {
2460 r = imap_env_to_fields(imap_envelope,
2461 references, ref_size, &fields);
2462 if (r == MAIL_NO_ERROR) {
2463 msg->msg_fields = fields;
2464 }
2465 }
2466
2467 if (att_dyn != NULL) {
2468 r = imap_flags_to_flags(att_dyn, &flags);
2469
2470 if (r == MAIL_NO_ERROR) {
2471 msg->msg_flags = flags;
2472 }
2473 }
2474
2475 i ++;
2476 break;
2477 }
2478
2479 i ++;
2480 }
2481 }
2482 }
2483 }
2484
2485 return MAIL_NO_ERROR;
2486}
2487
2488
2489int mailimf_date_time_to_imap_date(struct mailimf_date_time * date,
2490 struct mailimap_date ** result)
2491{
2492 struct mailimap_date * imap_date;
2493
2494 imap_date = mailimap_date_new(date->dt_day, date->dt_month, date->dt_year);
2495 if (imap_date == NULL)
2496 return MAIL_ERROR_MEMORY;
2497
2498 * result = imap_date;
2499
2500 return MAIL_NO_ERROR;
2501}
2502
2503
2504#if 0
2505int mail_search_to_imap_search(struct mail_search_key * key,
2506 struct mailimap_search_key ** result)
2507{
2508 struct mailimap_search_key * imap_key;
2509
2510 char * bcc;
2511 struct mailimap_date * before;
2512 char * body;
2513 char * cc;
2514 char * from;
2515 struct mailimap_date * on;
2516 struct mailimap_date * since;
2517 char * subject;
2518 char * text;
2519 char * to;
2520 char * header_name;
2521 char * header_value;
2522 size_t larger;
2523 struct mailimap_search_key * not;
2524 struct mailimap_search_key * or1;
2525 struct mailimap_search_key * or2;
2526 size_t smaller;
2527 clist * multiple;
2528 int type;
2529 clistiter * cur;
2530 int r;
2531 int res;
2532
2533 bcc = NULL;
2534 before = NULL;
2535 body = NULL;
2536 cc = NULL;
2537 from = NULL;
2538 on = NULL;
2539 since = NULL;
2540 subject = NULL;
2541 text = NULL;
2542 to = NULL;
2543 header_name = NULL;
2544 header_value = NULL;
2545 not = NULL;
2546 or1 = NULL;
2547 or2 = NULL;
2548 multiple = NULL;
2549 larger = 0;
2550 smaller = 0;
2551
2552 switch (key->sk_type) {
2553 case MAIL_SEARCH_KEY_ALL:
2554 type = MAILIMAP_SEARCH_KEY_ALL;
2555 break;
2556
2557 case MAIL_SEARCH_KEY_ANSWERED:
2558 type = MAILIMAP_SEARCH_KEY_ANSWERED;
2559 break;
2560
2561 case MAIL_SEARCH_KEY_BCC:
2562 type = MAILIMAP_SEARCH_KEY_BCC;
2563 bcc = strdup(key->sk_bcc);
2564 if (bcc == NULL) {
2565 res = MAIL_ERROR_MEMORY;
2566 goto err;
2567 }
2568 break;
2569
2570 case MAIL_SEARCH_KEY_BEFORE:
2571 type = MAILIMAP_SEARCH_KEY_BEFORE;
2572 r = mailimf_date_time_to_imap_date(key->sk_before, &before);
2573 if (r != MAIL_NO_ERROR) {
2574 res = r;
2575 goto err;
2576 }
2577 break;
2578
2579 case MAIL_SEARCH_KEY_BODY:
2580 type = MAILIMAP_SEARCH_KEY_BODY;
2581 body = strdup(key->sk_body);
2582 if (body == NULL) {
2583 res = MAIL_ERROR_MEMORY;
2584 goto err;
2585 }
2586 break;
2587
2588 case MAIL_SEARCH_KEY_CC:
2589 type = MAILIMAP_SEARCH_KEY_CC;
2590 cc = strdup(key->sk_cc);
2591 if (cc == NULL) {
2592 res = MAIL_ERROR_MEMORY;
2593 goto err;
2594 }
2595 break;
2596
2597 case MAIL_SEARCH_KEY_DELETED:
2598 type = MAILIMAP_SEARCH_KEY_DELETED;
2599 break;
2600
2601 case MAIL_SEARCH_KEY_FLAGGED:
2602 type = MAILIMAP_SEARCH_KEY_FLAGGED;
2603 break;
2604
2605 case MAIL_SEARCH_KEY_FROM:
2606 type = MAILIMAP_SEARCH_KEY_FROM;
2607 from = strdup(key->sk_from);
2608 if (from == NULL) {
2609 res = MAIL_ERROR_MEMORY;
2610 goto err;
2611 }
2612 break;
2613
2614 case MAIL_SEARCH_KEY_NEW:
2615 type = MAILIMAP_SEARCH_KEY_NEW;
2616 break;
2617
2618 case MAIL_SEARCH_KEY_OLD:
2619 type = MAILIMAP_SEARCH_KEY_OLD;
2620 break;
2621
2622 case MAIL_SEARCH_KEY_ON:
2623 type = MAILIMAP_SEARCH_KEY_ON;
2624 r = mailimf_date_time_to_imap_date(key->sk_on, &on);
2625 if (r != MAIL_NO_ERROR) {
2626 res = r;
2627 goto err;
2628 }
2629 break;
2630
2631 case MAIL_SEARCH_KEY_RECENT:
2632 type = MAILIMAP_SEARCH_KEY_RECENT;
2633 break;
2634
2635 case MAIL_SEARCH_KEY_SEEN:
2636 type = MAILIMAP_SEARCH_KEY_SEEN;
2637 break;
2638
2639 case MAIL_SEARCH_KEY_SINCE:
2640 type = MAILIMAP_SEARCH_KEY_SINCE;
2641 r = mailimf_date_time_to_imap_date(key->sk_since, &since);
2642 if (r != MAIL_NO_ERROR) {
2643 res = r;
2644 goto err;
2645 }
2646 break;
2647
2648 case MAIL_SEARCH_KEY_SUBJECT:
2649 type = MAILIMAP_SEARCH_KEY_SUBJECT;
2650 subject = strdup(key->sk_subject);
2651 if (subject == NULL) {
2652 res = MAIL_ERROR_MEMORY;
2653 goto err;
2654 }
2655 break;
2656
2657 case MAIL_SEARCH_KEY_TEXT:
2658 type = MAILIMAP_SEARCH_KEY_TEXT;
2659 text = strdup(key->sk_text);
2660 if (text == NULL) {
2661 res = MAIL_ERROR_MEMORY;
2662 goto err;
2663 }
2664 break;
2665
2666 case MAIL_SEARCH_KEY_TO:
2667 type = MAILIMAP_SEARCH_KEY_TO;
2668 to = strdup(key->sk_to);
2669 if (to == NULL) {
2670 return MAIL_ERROR_MEMORY;
2671 goto err;
2672 }
2673 break;
2674
2675 case MAIL_SEARCH_KEY_UNANSWERED:
2676 type = MAILIMAP_SEARCH_KEY_UNANSWERED;
2677 break;
2678
2679 case MAIL_SEARCH_KEY_UNDELETED:
2680 type = MAILIMAP_SEARCH_KEY_UNFLAGGED;
2681 break;
2682
2683 case MAIL_SEARCH_KEY_UNFLAGGED:
2684 type = MAILIMAP_SEARCH_KEY_UNANSWERED;
2685 break;
2686
2687 case MAIL_SEARCH_KEY_UNSEEN:
2688 type = MAILIMAP_SEARCH_KEY_UNSEEN;
2689 break;
2690
2691 case MAIL_SEARCH_KEY_HEADER:
2692 type = MAILIMAP_SEARCH_KEY_HEADER;
2693 header_name = strdup(key->sk_header_name);
2694 if (header_name == NULL) {
2695 res = MAIL_ERROR_MEMORY;
2696 goto err;
2697 }
2698 header_value = strdup(key->sk_header_value);
2699 if (header_value == NULL) {
2700 free(header_name);
2701 res = MAIL_ERROR_MEMORY;
2702 goto err;
2703 }
2704 break;
2705
2706 case MAIL_SEARCH_KEY_LARGER:
2707 type = MAILIMAP_SEARCH_KEY_LARGER;
2708 larger = key->sk_larger;
2709 break;
2710
2711 case MAIL_SEARCH_KEY_NOT:
2712 type = MAILIMAP_SEARCH_KEY_NOT;
2713 r = mail_search_to_imap_search(key->sk_not, &not);
2714 if (r != MAIL_NO_ERROR) {
2715 res = r;
2716 goto err;
2717 }
2718 break;
2719
2720 case MAIL_SEARCH_KEY_OR:
2721 type = MAILIMAP_SEARCH_KEY_OR;
2722 r = mail_search_to_imap_search(key->sk_or1, &or1);
2723 if (r != MAIL_NO_ERROR) {
2724 res = r;
2725 goto err;
2726 }
2727 r = mail_search_to_imap_search(key->sk_or2, &or2);
2728 if (r != MAIL_NO_ERROR) {
2729 mailimap_search_key_free(or1);
2730 res = r;
2731 goto err;
2732 }
2733 break;
2734
2735 case MAIL_SEARCH_KEY_SMALLER:
2736 type = MAILIMAP_SEARCH_KEY_SMALLER;
2737 smaller = key->sk_smaller;
2738 break;
2739
2740 case MAIL_SEARCH_KEY_MULTIPLE:
2741 multiple = clist_new();
2742 if (multiple == NULL) {
2743 res = MAIL_ERROR_MEMORY;
2744 goto err;
2745 }
2746
2747 type = MAILIMAP_SEARCH_KEY_MULTIPLE;
2748 for(cur = clist_begin(key->sk_multiple) ; cur != NULL ;
2749 cur = clist_next(cur)) {
2750 struct mail_search_key * key_elt;
2751 struct mailimap_search_key * imap_key_elt;
2752
2753 key_elt = clist_content(cur);
2754 r = mail_search_to_imap_search(key_elt, &imap_key_elt);
2755 if (r != MAIL_NO_ERROR) {
2756 res = r;
2757 goto free_list;
2758 }
2759
2760 r = clist_append(multiple, imap_key_elt);
2761 if (r != 0) {
2762 mailimap_search_key_free(imap_key_elt);
2763 res = MAIL_ERROR_MEMORY;
2764 goto free_list;
2765 }
2766 }
2767 break;
2768
2769 free_list:
2770 clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL);
2771 clist_free(multiple);
2772 goto err;
2773
2774 default:
2775 return MAIL_ERROR_INVAL;
2776 }
2777
2778 imap_key = mailimap_search_key_new(type, bcc, before, body, cc, from,
2779 NULL, on, since, subject, text,
2780 to, NULL, header_name,
2781 header_value, larger, not, or1, or2,
2782 NULL, NULL, NULL, smaller, NULL,
2783 NULL, multiple);
2784 if (imap_key == NULL) {
2785 res = MAIL_ERROR_MEMORY;
2786 goto free;
2787 }
2788
2789 * result = imap_key;
2790
2791 return MAIL_NO_ERROR;
2792
2793 free:
2794 if (bcc != NULL)
2795 free(bcc);
2796 if (before != NULL)
2797 mailimap_date_free(before);
2798 if (body != NULL)
2799 free(body);
2800 if (cc != NULL)
2801 free(cc);
2802 if (from != NULL)
2803 free(from);
2804 if (on != NULL)
2805 mailimap_date_free(on);
2806 if (since != NULL)
2807 mailimap_date_free(since);
2808 if (subject != NULL)
2809 free(subject);
2810 if (text != NULL)
2811 free(text);
2812 if (to != NULL)
2813 free(to);
2814 if (header_name != NULL)
2815 free(header_name);
2816 if (header_value != NULL)
2817 free(header_value);
2818 if (not != NULL)
2819 mailimap_search_key_free(not);
2820 if (or1 != NULL)
2821 mailimap_search_key_free(or1);
2822 if (or2 != NULL)
2823 mailimap_search_key_free(or2);
2824 clist_foreach(multiple, (clist_func) mailimap_search_key_free, NULL);
2825 clist_free(multiple);
2826 err:
2827 return res;
2828}
2829#endif
2830
2831
2832int msg_list_to_imap_set(clist * msg_list,
2833 struct mailimap_set ** result)
2834{
2835 struct mailimap_set * imap_set;
2836 clistiter * cur;
2837 int previous_valid;
2838 uint32_t first_seq;
2839 uint32_t previous;
2840 int r;
2841 int res;
2842
2843 imap_set = mailimap_set_new_empty();
2844 if (imap_set == NULL) {
2845 res = MAIL_ERROR_MEMORY;
2846 goto err;
2847 }
2848
2849 cur = clist_begin(msg_list);
2850 previous_valid = FALSE;
2851 first_seq = 0;
2852 previous = 0;
2853 while (1) {
2854 uint32_t * pindex;
2855
2856 if ((cur == NULL) && (previous_valid)) {
2857 if (first_seq == previous) {
2858 r = mailimap_set_add_single(imap_set, first_seq);
2859 if (r != MAILIMAP_NO_ERROR) {
2860 res = r;
2861 goto free;
2862 }
2863 }
2864 else {
2865 r = mailimap_set_add_interval(imap_set, first_seq, previous);
2866 if (r != MAILIMAP_NO_ERROR) {
2867 res = r;
2868 goto free;
2869 }
2870 }
2871 break;
2872 }
2873
2874 pindex = clist_content(cur);
2875
2876 if (!previous_valid) {
2877 first_seq = * pindex;
2878 previous_valid = TRUE;
2879 previous = * pindex;
2880 cur = clist_next(cur);
2881 }
2882 else {
2883 if (* pindex != previous + 1) {
2884 if (first_seq == previous) {
2885 r = mailimap_set_add_single(imap_set, first_seq);
2886 if (r != MAILIMAP_NO_ERROR) {
2887 res = r;
2888 goto free;
2889 }
2890 }
2891 else {
2892 r = mailimap_set_add_interval(imap_set, first_seq, previous);
2893 if (r != MAILIMAP_NO_ERROR) {
2894 res = r;
2895 goto free;
2896 }
2897 }
2898 previous_valid = FALSE;
2899 }
2900 else {
2901 previous = * pindex;
2902 cur = clist_next(cur);
2903 }
2904 }
2905 }
2906
2907 * result = imap_set;
2908
2909 return MAIL_NO_ERROR;
2910
2911 free:
2912 mailimap_set_free(imap_set);
2913 err:
2914 return res;
2915}
2916
2917
2918static int
2919uid_list_to_env_list(clist * fetch_result,
2920 struct mailmessage_list ** result,
2921 mailsession * session, mailmessage_driver * driver)
2922{
2923 clistiter * cur;
2924 struct mailmessage_list * env_list;
2925 int r;
2926 int res;
2927 carray * tab;
2928 unsigned int i;
2929 mailmessage * msg;
2930
2931 tab = carray_new(128);
2932 if (tab == NULL) {
2933 res = MAIL_ERROR_MEMORY;
2934 goto err;
2935 }
2936
2937 for(cur = clist_begin(fetch_result) ; cur != NULL ;
2938 cur = clist_next(cur)) {
2939 struct mailimap_msg_att * msg_att;
2940 clistiter * item_cur;
2941 uint32_t uid;
2942 size_t size;
2943
2944 msg_att = clist_content(cur);
2945
2946 uid = 0;
2947 size = 0;
2948 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
2949 item_cur = clist_next(item_cur)) {
2950 struct mailimap_msg_att_item * item;
2951
2952 item = clist_content(item_cur);
2953
2954 switch (item->att_type) {
2955 case MAILIMAP_MSG_ATT_ITEM_STATIC:
2956 switch (item->att_data.att_static->att_type) {
2957 case MAILIMAP_MSG_ATT_UID:
2958 uid = item->att_data.att_static->att_data.att_uid;
2959 break;
2960
2961 case MAILIMAP_MSG_ATT_RFC822_SIZE:
2962 size = item->att_data.att_static->att_data.att_rfc822_size;
2963 break;
2964 }
2965 break;
2966 }
2967 }
2968
2969 msg = mailmessage_new();
2970 if (msg == NULL) {
2971 res = MAIL_ERROR_MEMORY;
2972 goto free_list;
2973 }
2974
2975 r = mailmessage_init(msg, session, driver, uid, size);
2976 if (r != MAIL_NO_ERROR) {
2977 res = r;
2978 goto free_msg;
2979 }
2980
2981 r = carray_add(tab, msg, NULL);
2982 if (r < 0) {
2983 res = MAIL_ERROR_MEMORY;
2984 goto free_msg;
2985 }
2986 }
2987
2988 env_list = mailmessage_list_new(tab);
2989 if (env_list == NULL) {
2990 res = MAIL_ERROR_MEMORY;
2991 goto free_list;
2992 }
2993
2994 * result = env_list;
2995
2996 return MAIL_NO_ERROR;
2997
2998 free_msg:
2999 mailmessage_free(msg);
3000 free_list:
3001 for(i = 0 ; i < carray_count(tab) ; i++)
3002 mailmessage_free(carray_get(tab, i));
3003 err:
3004 return res;
3005}
3006
3007
3008/*
3009 MAILIMAP_FLAG_FETCH_RECENT,
3010 MAILIMAP_FLAG_FETCH_OTHER
3011
3012 MAILIMAP_FLAG_ANSWERED,
3013 MAILIMAP_FLAG_FLAGGED,
3014 MAILIMAP_FLAG_DELETED,
3015 MAILIMAP_FLAG_SEEN,
3016 MAILIMAP_FLAG_DRAFT,
3017 MAILIMAP_FLAG_KEYWORD,
3018 MAILIMAP_FLAG_EXTENSION
3019*/
3020
3021static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn,
3022 struct mail_flags ** result)
3023{
3024 struct mail_flags * flags;
3025 clist * flag_list;
3026 clistiter * cur;
3027
3028 flags = mail_flags_new_empty();
3029 if (flags == NULL)
3030 goto err;
3031 flags->fl_flags = 0;
3032
3033 flag_list = att_dyn->att_list;
3034 if (flag_list != NULL) {
3035 for(cur = clist_begin(flag_list) ; cur != NULL ;
3036 cur = clist_next(cur)) {
3037 struct mailimap_flag_fetch * flag_fetch;
3038
3039 flag_fetch = clist_content(cur);
3040 if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT)
3041 flags->fl_flags |= MAIL_FLAG_NEW;
3042 else {
3043 char * keyword;
3044 int r;
3045
3046 switch (flag_fetch->fl_flag->fl_type) {
3047 case MAILIMAP_FLAG_ANSWERED:
3048 flags->fl_flags |= MAIL_FLAG_ANSWERED;
3049 break;
3050 case MAILIMAP_FLAG_FLAGGED:
3051 flags->fl_flags |= MAIL_FLAG_FLAGGED;
3052 break;
3053 case MAILIMAP_FLAG_DELETED:
3054 flags->fl_flags |= MAIL_FLAG_DELETED;
3055 break;
3056 case MAILIMAP_FLAG_SEEN:
3057 flags->fl_flags |= MAIL_FLAG_SEEN;
3058 break;
3059 case MAILIMAP_FLAG_DRAFT:
3060 keyword = strdup("Draft");
3061 if (keyword == NULL)
3062 goto free;
3063 r = clist_append(flags->fl_extension, keyword);
3064 if (r < 0) {
3065 free(keyword);
3066 goto free;
3067 }
3068 break;
3069 case MAILIMAP_FLAG_KEYWORD:
3070 if (strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword,
3071 "$Forwarded") == 0) {
3072 flags->fl_flags |= MAIL_FLAG_FORWARDED;
3073 }
3074 else {
3075 keyword = strdup(flag_fetch->fl_flag->fl_data.fl_keyword);
3076 if (keyword == NULL)
3077 goto free;
3078 r = clist_append(flags->fl_extension, keyword);
3079 if (r < 0) {
3080 free(keyword);
3081 goto free;
3082 }
3083 }
3084 break;
3085 case MAILIMAP_FLAG_EXTENSION:
3086 /* do nothing */
3087 break;
3088 }
3089 }
3090 }
3091 /*
3092 MAIL_FLAG_NEW was set for \Recent messages.
3093 Correct this flag for \Seen messages by unsetting it.
3094 */
3095 if ((flags->fl_flags & MAIL_FLAG_SEEN) && (flags->fl_flags & MAIL_FLAG_NEW)) {
3096 flags->fl_flags &= ~MAIL_FLAG_NEW;
3097 }
3098 }
3099
3100 * result = flags;
3101
3102 return MAIL_NO_ERROR;
3103
3104 free:
3105 mail_flags_free(flags);
3106 err:
3107 return MAIL_ERROR_MEMORY;
3108}
3109
3110int imap_flags_to_imap_flags(struct mail_flags * flags,
3111 struct mailimap_flag_list ** result)
3112{
3113 struct mailimap_flag * flag;
3114 struct mailimap_flag_list * flag_list;
3115 int res;
3116 clistiter * cur;
3117 int r;
3118
3119 flag_list = mailimap_flag_list_new_empty();
3120 if (flag_list == NULL) {
3121 res = MAIL_ERROR_MEMORY;
3122 goto err;
3123 }
3124
3125 if ((flags->fl_flags & MAIL_FLAG_DELETED) != 0) {
3126 flag = mailimap_flag_new_deleted();
3127 if (flag == NULL) {
3128 res = MAIL_ERROR_MEMORY;
3129 goto free_flag_list;
3130 }
3131 r = mailimap_flag_list_add(flag_list, flag);
3132 if (r != MAILIMAP_NO_ERROR) {
3133 mailimap_flag_free(flag);
3134 res = MAIL_ERROR_MEMORY;
3135 goto free_flag_list;
3136 }
3137 }
3138
3139 if ((flags->fl_flags & MAIL_FLAG_FLAGGED) != 0) {
3140 flag = mailimap_flag_new_flagged();
3141 if (flag == NULL) {
3142 res = MAIL_ERROR_MEMORY;
3143 goto free_flag_list;
3144 }
3145 r = mailimap_flag_list_add(flag_list, flag);
3146 if (r != MAILIMAP_NO_ERROR) {
3147 mailimap_flag_free(flag);
3148 res = MAIL_ERROR_MEMORY;
3149 goto free_flag_list;
3150 }
3151 }
3152
3153 if ((flags->fl_flags & MAIL_FLAG_SEEN) != 0) {
3154 flag = mailimap_flag_new_seen();
3155 if (flag == NULL) {
3156 res = MAIL_ERROR_MEMORY;
3157 goto free_flag_list;
3158 }
3159 r = mailimap_flag_list_add(flag_list, flag);
3160 if (r != MAILIMAP_NO_ERROR) {
3161 res = MAIL_ERROR_MEMORY;
3162 goto free_flag_list;
3163 }
3164 }
3165
3166 if ((flags->fl_flags & MAIL_FLAG_ANSWERED) != 0) {
3167 flag = mailimap_flag_new_answered();
3168 if (flag == NULL) {
3169 res = MAIL_ERROR_MEMORY;
3170 goto free_flag_list;
3171 }
3172 r = mailimap_flag_list_add(flag_list, flag);
3173 if (r != MAILIMAP_NO_ERROR) {
3174 mailimap_flag_free(flag);
3175 res = MAIL_ERROR_MEMORY;
3176 goto free_flag_list;
3177 }
3178 }
3179
3180 if ((flags->fl_flags & MAIL_FLAG_FORWARDED) != 0) {
3181 char * flag_str;
3182
3183 flag_str = strdup("$Forwarded");
3184 if (flag_str == NULL) {
3185 res = MAIL_ERROR_MEMORY;
3186 goto free_flag_list;
3187 }
3188 flag = mailimap_flag_new_flag_keyword(flag_str);
3189 if (flag == NULL) {
3190 free(flag_str);
3191 res = MAIL_ERROR_MEMORY;
3192 goto free_flag_list;
3193 }
3194 r = mailimap_flag_list_add(flag_list, flag);
3195 if (r != MAILIMAP_NO_ERROR) {
3196 mailimap_flag_free(flag);
3197 res = MAIL_ERROR_MEMORY;
3198 goto free_flag_list;
3199 }
3200 }
3201
3202 for(cur = clist_begin(flags->fl_extension) ; cur != NULL ;
3203 cur = clist_next(cur)) {
3204 char * flag_str;
3205
3206 flag_str = clist_content(cur);
3207
3208 if (strcasecmp(flag_str, "Draft") == 0) {
3209 flag = mailimap_flag_new_draft();
3210 if (flag == NULL) {
3211 res = MAIL_ERROR_MEMORY;
3212 goto free_flag_list;
3213 }
3214 r = mailimap_flag_list_add(flag_list, flag);
3215 if (r != MAILIMAP_NO_ERROR) {
3216 mailimap_flag_free(flag);
3217 res = MAIL_ERROR_MEMORY;
3218 goto free_flag_list;
3219 }
3220 }
3221 else {
3222 flag_str = strdup(flag_str);
3223 if (flag_str == NULL) {
3224 res = MAIL_ERROR_MEMORY;
3225 goto free_flag_list;
3226 }
3227 flag = mailimap_flag_new_flag_keyword(flag_str);
3228 if (flag == NULL) {
3229 free(flag_str);
3230 res = MAIL_ERROR_MEMORY;
3231 goto free_flag_list;
3232 }
3233 r = mailimap_flag_list_add(flag_list, flag);
3234 if (r != MAILIMAP_NO_ERROR) {
3235 mailimap_flag_free(flag);
3236 res = MAIL_ERROR_MEMORY;
3237 goto free_flag_list;
3238 }
3239 }
3240 }
3241
3242 * result = flag_list;
3243
3244 return MAIL_NO_ERROR;
3245
3246 free_flag_list:
3247 mailimap_flag_list_free(flag_list);
3248 err:
3249 return res;
3250}
3251
3252static int flags_to_imap_flags(struct mail_flags * flags,
3253 struct mailimap_store_att_flags ** result)
3254{
3255 struct mailimap_flag_list * flag_list;
3256 struct mailimap_store_att_flags * att_flags;
3257 int res;
3258 int r;
3259
3260 r = imap_flags_to_imap_flags(flags,
3261 &flag_list);
3262 if (r != MAIL_NO_ERROR) {
3263 res = r;
3264 goto err;
3265 }
3266
3267 att_flags = mailimap_store_att_flags_new_set_flags_silent(flag_list);
3268 if (att_flags == NULL) {
3269 res = MAIL_ERROR_MEMORY;
3270 goto free_flag_list;
3271 }
3272
3273 * result = att_flags;
3274
3275 return MAIL_NO_ERROR;
3276
3277 free_flag_list:
3278 mailimap_flag_list_free(flag_list);
3279 err:
3280 return res;
3281}
3282
3283
3284static int
3285imap_fetch_result_to_flags(clist * fetch_result, uint32_t index,
3286 struct mail_flags ** result)
3287{
3288 clistiter * cur;
3289 int r;
3290
3291 for(cur = clist_begin(fetch_result) ; cur != NULL ;
3292 cur = clist_next(cur)) {
3293 struct mailimap_msg_att * msg_att;
3294 clistiter * item_cur;
3295 uint32_t uid;
3296 struct mailimap_msg_att_dynamic * att_dyn;
3297
3298 msg_att = clist_content(cur);
3299
3300 uid = 0;
3301 att_dyn = NULL;
3302
3303 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
3304 item_cur = clist_next(item_cur)) {
3305 struct mailimap_msg_att_item * item;
3306
3307 item = clist_content(item_cur);
3308
3309 if (item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
3310 switch (item->att_data.att_static->att_type) {
3311 case MAILIMAP_MSG_ATT_UID:
3312 uid = item->att_data.att_static->att_data.att_uid;
3313 break;
3314 }
3315 }
3316 else if (item->att_type == MAILIMAP_MSG_ATT_ITEM_DYNAMIC) {
3317 if (att_dyn == NULL) {
3318 att_dyn = item->att_data.att_dyn;
3319 }
3320 }
3321 }
3322
3323 if (uid != 0) {
3324 if (uid == index) {
3325 struct mail_flags * flags;
3326
3327 if (att_dyn != NULL) {
3328 r = imap_flags_to_flags(att_dyn, &flags);
3329
3330 if (r == MAIL_NO_ERROR) {
3331 * result = flags;
3332 return MAIL_NO_ERROR;
3333 }
3334 }
3335 }
3336 }
3337 }
3338
3339 return MAIL_ERROR_MSG_NOT_FOUND;
3340}
3341
3342
3343int imap_fetch_flags(mailimap * imap,
3344 uint32_t index, struct mail_flags ** result)
3345{
3346 struct mailimap_fetch_att * fetch_att;
3347 struct mailimap_fetch_type * fetch_type;
3348 struct mailimap_set * set;
3349 int r;
3350 int res;
3351 clist * fetch_result;
3352 struct mail_flags * flags;
3353
3354 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
3355 if (fetch_type == NULL) {
3356 res = MAIL_ERROR_MEMORY;
3357 goto err;
3358 }
3359
3360 fetch_att = mailimap_fetch_att_new_uid();
3361 if (fetch_att == NULL) {
3362 res = MAIL_ERROR_MEMORY;
3363 goto free_fetch_type;
3364 }
3365
3366 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3367 if (r != MAILIMAP_NO_ERROR) {
3368 mailimap_fetch_att_free(fetch_att);
3369 res = MAIL_ERROR_MEMORY;
3370 goto free_fetch_type;
3371 }
3372
3373 fetch_att = mailimap_fetch_att_new_flags();
3374 if (fetch_att == NULL) {
3375 res = MAIL_ERROR_MEMORY;
3376 goto free_fetch_type;
3377 }
3378
3379 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3380 if (r != MAILIMAP_NO_ERROR) {
3381 mailimap_fetch_att_free(fetch_att);
3382 res = MAIL_ERROR_MEMORY;
3383 goto free_fetch_type;
3384 }
3385
3386 set = mailimap_set_new_single(index);
3387 if (set == NULL) {
3388 res = MAIL_ERROR_MEMORY;
3389 goto free_fetch_type;
3390 }
3391
3392 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
3393
3394 mailimap_fetch_type_free(fetch_type);
3395 mailimap_set_free(set);
3396
3397 switch (r) {
3398 case MAILIMAP_NO_ERROR:
3399 break;
3400 default:
3401 return imap_error_to_mail_error(r);
3402 }
3403
3404 r = imap_fetch_result_to_flags(fetch_result, index, &flags);
3405 mailimap_fetch_list_free(fetch_result);
3406
3407 if (r != MAIL_NO_ERROR) {
3408 res = r;
3409 goto err;
3410 }
3411
3412 * result = flags;
3413
3414 return MAIL_NO_ERROR;
3415
3416 free_fetch_type:
3417 mailimap_fetch_type_free(fetch_type);
3418 err:
3419 return res;
3420}
3421
3422int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last,
3423 struct mail_flags * flags)
3424{
3425 struct mailimap_store_att_flags * att_flags;
3426 struct mailimap_set * set;
3427 int r;
3428 int res;
3429
3430 set = mailimap_set_new_interval(first, last);
3431 if (set == NULL) {
3432 res = MAIL_ERROR_MEMORY;
3433 goto err;
3434 }
3435
3436 r = flags_to_imap_flags(flags, &att_flags);
3437 if (r != MAIL_NO_ERROR) {
3438 res = r;
3439 goto free_set;
3440 }
3441
3442 r = mailimap_uid_store(imap, set, att_flags);
3443 if (r != MAILIMAP_NO_ERROR) {
3444 res = imap_error_to_mail_error(r);
3445 goto free_flag;
3446 }
3447
3448 mailimap_store_att_flags_free(att_flags);
3449 mailimap_set_free(set);
3450
3451 return MAIL_NO_ERROR;
3452
3453 free_flag:
3454 mailimap_store_att_flags_free(att_flags);
3455 free_set:
3456 mailimap_set_free(set);
3457 err:
3458 return res;
3459}
3460
3461
3462
3463
3464int imap_get_messages_list(mailimap * imap,
3465 mailsession * session, mailmessage_driver * driver,
3466 uint32_t first_index,
3467 struct mailmessage_list ** result)
3468{
3469 struct mailmessage_list * env_list;
3470 int r;
3471 struct mailimap_fetch_att * fetch_att;
3472 struct mailimap_fetch_type * fetch_type;
3473 struct mailimap_set * set;
3474 clist * fetch_result;
3475 int res;
3476
3477 set = mailimap_set_new_interval(first_index, 0);
3478 if (set == NULL) {
3479 res = MAIL_ERROR_MEMORY;
3480 goto err;
3481 }
3482
3483 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
3484 if (fetch_type == NULL) {
3485 res = MAIL_ERROR_MEMORY;
3486 goto free_set;
3487 }
3488
3489 fetch_att = mailimap_fetch_att_new_uid();
3490 if (fetch_att == NULL) {
3491 res = MAIL_ERROR_MEMORY;
3492 goto free_fetch_type;
3493 }
3494
3495 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3496 if (r != MAILIMAP_NO_ERROR) {
3497 mailimap_fetch_att_free(fetch_att);
3498 res = MAIL_ERROR_MEMORY;
3499 goto free_fetch_type;
3500 }
3501
3502 fetch_att = mailimap_fetch_att_new_rfc822_size();
3503 if (fetch_att == NULL) {
3504 res = MAIL_ERROR_MEMORY;
3505 goto free_fetch_type;
3506 }
3507
3508 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
3509 if (r != MAILIMAP_NO_ERROR) {
3510 mailimap_fetch_att_free(fetch_att);
3511 res = MAIL_ERROR_MEMORY;
3512 goto free_fetch_type;
3513 }
3514
3515 r = mailimap_uid_fetch(imap, set,
3516 fetch_type, &fetch_result);
3517
3518 mailimap_fetch_type_free(fetch_type);
3519 mailimap_set_free(set);
3520
3521 if (r != MAILIMAP_NO_ERROR) {
3522 res = imap_error_to_mail_error(r);
3523 goto err;
3524 }
3525
3526 r = uid_list_to_env_list(fetch_result, &env_list, session, driver);
3527 mailimap_fetch_list_free(fetch_result);
3528
3529 * result = env_list;
3530
3531 return MAIL_NO_ERROR;
3532
3533 free_fetch_type:
3534 mailimap_fetch_type_free(fetch_type);
3535 free_set:
3536 mailimap_set_free(set);
3537 err:
3538 return res;
3539}
3540
3541static void generate_key_from_message(char * key, size_t size,
3542 mailmessage * msg_info,
3543 int type)
3544{
3545 switch (type) {
3546 case MAILIMAP_MSG_ATT_RFC822:
3547 snprintf(key, size, "%s-rfc822", msg_info->msg_uid);
3548 break;
3549 case MAILIMAP_MSG_ATT_RFC822_HEADER:
3550 snprintf(key, size, "%s-rfc822-header", msg_info->msg_uid);
3551 break;
3552 case MAILIMAP_MSG_ATT_RFC822_TEXT:
3553 snprintf(key, size, "%s-rfc822-text", msg_info->msg_uid);
3554 break;
3555 case MAILIMAP_MSG_ATT_ENVELOPE:
3556 snprintf(key, size, "%s-envelope", msg_info->msg_uid);
3557 break;
3558 }
3559}
3560
3561int
3562imapdriver_get_cached_envelope(struct mail_cache_db * cache_db,
3563 MMAPString * mmapstr,
3564 mailsession * session, mailmessage * msg,
3565 struct mailimf_fields ** result)
3566{
3567#if 0
3568 mailsession * imap_session;
3569#endif
3570 mailimap * imap;
3571 int r;
3572 struct mailimf_fields * fields;
3573 int res;
3574 char keyname[PATH_MAX];
3575
3576#if 0
3577 imap_session = cached_session_get_ancestor(session);
3578 imap = ((struct imap_session_state_data *) (imap_session->data))->session;
3579#endif
3580 imap = cached_session_get_imap_session(session);
3581
3582 generate_key_from_message(keyname, PATH_MAX,
3583 msg, MAILIMAP_MSG_ATT_ENVELOPE);
3584
3585 r = generic_cache_fields_read(cache_db, mmapstr, keyname, &fields);
3586 if (r != MAIL_NO_ERROR) {
3587 res = r;
3588 goto err;
3589 }
3590
3591 * result = fields;
3592
3593 return MAIL_NO_ERROR;
3594
3595err:
3596 return res;
3597}
3598
3599int
3600imapdriver_write_cached_envelope(struct mail_cache_db * cache_db,
3601 MMAPString * mmapstr,
3602 mailsession * session, mailmessage * msg,
3603 struct mailimf_fields * fields)
3604{
3605 char keyname[PATH_MAX];
3606 int r;
3607 int res;
3608
3609 generate_key_from_message(keyname, PATH_MAX,
3610 msg, MAILIMAP_MSG_ATT_ENVELOPE);
3611
3612 r = generic_cache_fields_write(cache_db, mmapstr, keyname, fields);
3613 if (r != MAIL_NO_ERROR) {
3614 res = r;
3615 goto err;
3616 }
3617
3618 return MAIL_NO_ERROR;
3619
3620err:
3621 return res;
3622}
3623
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_tools.h b/libetpan/src/driver/implementation/imap/imapdriver_tools.h
new file mode 100644
index 0000000..e15fdda
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_tools.h
@@ -0,0 +1,116 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_TOOLS_H
37
38#define IMAPDRIVER_TOOLS_H
39
40#include "mailimap.h"
41#include "mailmime.h"
42#include "imapdriver_types.h"
43#include "mail_cache_db.h"
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
49int imap_list_to_list(clist * imap_list, struct mail_list ** result);
50
51int
52section_to_imap_section(struct mailmime_section * section, int type,
53 struct mailimap_section ** result);
54
55int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
56 uint32_t * puid,
57 struct mailimap_envelope ** pimap_envelope,
58 char ** preferences,
59 size_t * pref_size,
60 struct mailimap_msg_att_dynamic ** patt_dyn,
61 struct mailimap_body ** pimap_body);
62
63int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type);
64
65int imap_env_to_fields(struct mailimap_envelope * env,
66 char * ref_str, size_t ref_size,
67 struct mailimf_fields ** result);
68
69int
70imap_fetch_result_to_envelop_list(clist * fetch_result,
71 struct mailmessage_list * env_list);
72
73int imap_body_to_body(struct mailimap_body * imap_body,
74 struct mailmime ** result);
75
76#if 0
77int mail_search_to_imap_search(struct mail_search_key * key,
78 struct mailimap_search_key ** result);
79#endif
80
81int msg_list_to_imap_set(clist * msg_list,
82 struct mailimap_set ** result);
83
84int imap_error_to_mail_error(int error);
85
86int imap_store_flags(mailimap * imap, uint32_t first, uint32_t last,
87 struct mail_flags * flags);
88
89int imap_fetch_flags(mailimap * imap,
90 uint32_t index, struct mail_flags ** result);
91
92int imap_get_messages_list(mailimap * imap,
93 mailsession * session, mailmessage_driver * driver,
94 uint32_t first_index,
95 struct mailmessage_list ** result);
96
97int
98imapdriver_get_cached_envelope(struct mail_cache_db * cache_db,
99 MMAPString * mmapstr,
100 mailsession * session, mailmessage * msg,
101 struct mailimf_fields ** result);
102
103int
104imapdriver_write_cached_envelope(struct mail_cache_db * cache_db,
105 MMAPString * mmapstr,
106 mailsession * session, mailmessage * msg,
107 struct mailimf_fields * fields);
108
109int imap_flags_to_imap_flags(struct mail_flags * flags,
110 struct mailimap_flag_list ** result);
111
112#ifdef __cplusplus
113}
114#endif
115
116#endif
diff --git a/libetpan/src/driver/implementation/imap/imapdriver_types.h b/libetpan/src/driver/implementation/imap/imapdriver_types.h
new file mode 100644
index 0000000..00559dc
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapdriver_types.h
@@ -0,0 +1,144 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPDRIVER_TYPES_H
37
38#define IMAPDRIVER_TYPES_H
39
40#include <libetpan/libetpan-config.h>
41
42#include <libetpan/mailimap.h>
43#include <libetpan/maildriver_types.h>
44#include <libetpan/generic_cache_types.h>
45#include <libetpan/mailstorage_types.h>
46
47#ifdef __cplusplus
48extern "C" {
49#endif
50
51/* IMAP driver for session */
52
53struct imap_session_state_data {
54 mailimap * imap_session;
55 char * imap_mailbox;
56 struct mail_flags_store * imap_flags_store;
57};
58
59enum {
60 IMAP_SECTION_MESSAGE,
61 IMAP_SECTION_HEADER,
62 IMAP_SECTION_MIME,
63 IMAP_SECTION_BODY
64};
65
66/* cached IMAP driver for session */
67
68enum {
69 IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY = 1,
70};
71
72struct imap_cached_session_state_data {
73 mailsession * imap_ancestor;
74 char * imap_quoted_mb;
75 char imap_cache_directory[PATH_MAX];
76 carray * imap_uid_list;
77};
78
79
80/* IMAP storage */
81
82/*
83 imap_mailstorage is the state data specific to the IMAP4rev1 storage.
84
85 - servername this is the name of the IMAP4rev1 server
86
87 - port is the port to connect to, on the server.
88 you give 0 to use the default port.
89
90 - command, if non-NULL the command used to connect to the
91 server instead of allowing normal TCP connections to be used.
92
93 - connection_type is the type of socket layer to use.
94 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
95 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS or
96 CONNECTION_TYPE_COMMAND.
97
98 - auth_type is the authenticate mechanism to use.
99 The value can be IMAP_AUTH_TYPE_PLAIN.
100 Other values are not yet implemented.
101
102 - login is the login of the IMAP4rev1 account.
103
104 - password is the password of the IMAP4rev1 account.
105
106 - cached if this value is != 0, a persistant cache will be
107 stored on local system.
108
109 - cache_directory is the location of the cache
110*/
111
112struct imap_mailstorage {
113 char * imap_servername;
114 uint16_t imap_port;
115 char * imap_command;
116 int imap_connection_type;
117
118 int imap_auth_type;
119 char * imap_login;
120 char * imap_password;
121
122 int imap_cached;
123 char * imap_cache_directory;
124};
125
126/* this is the type of IMAP4rev1 authentication */
127
128enum {
129 IMAP_AUTH_TYPE_PLAIN, /* plain text authentication */
130 IMAP_AUTH_TYPE_SASL_ANONYMOUS, /* SASL anonymous */
131 IMAP_AUTH_TYPE_SASL_CRAM_MD5, /* SASL CRAM MD5 */
132 IMAP_AUTH_TYPE_SASL_KERBEROS_V4, /* SASL KERBEROS V4 */
133 IMAP_AUTH_TYPE_SASL_PLAIN, /* SASL plain */
134 IMAP_AUTH_TYPE_SASL_SCRAM_MD5, /* SASL SCRAM MD5 */
135 IMAP_AUTH_TYPE_SASL_GSSAPI, /* SASL GSSAPI */
136 IMAP_AUTH_TYPE_SASL_DIGEST_MD5, /* SASL digest MD5 */
137};
138
139
140#ifdef __cplusplus
141}
142#endif
143
144#endif
diff --git a/libetpan/src/driver/implementation/imap/imapstorage.c b/libetpan/src/driver/implementation/imap/imapstorage.c
new file mode 100644
index 0000000..0bf6ec2
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapstorage.c
@@ -0,0 +1,297 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#include "imapstorage.h"
37
38#include <stdlib.h>
39#include <string.h>
40
41#include "mail.h"
42#include "imapdriver.h"
43#include "imapdriver_cached.h"
44#include "mailstorage_tools.h"
45#include "maildriver.h"
46
47/* imap storage */
48
49#define IMAP_DEFAULT_PORT 143
50#define IMAPS_DEFAULT_PORT 993
51
52static int imap_mailstorage_connect(struct mailstorage * storage);
53static int
54imap_mailstorage_get_folder_session(struct mailstorage * storage,
55 char * pathname, mailsession ** result);
56static void imap_mailstorage_uninitialize(struct mailstorage * storage);
57
58static mailstorage_driver imap_mailstorage_driver = {
59 .sto_name = "imap",
60 .sto_connect = imap_mailstorage_connect,
61 .sto_get_folder_session = imap_mailstorage_get_folder_session,
62 .sto_uninitialize = imap_mailstorage_uninitialize,
63};
64
65int imap_mailstorage_init(struct mailstorage * storage,
66 char * imap_servername, uint16_t imap_port,
67 char * imap_command,
68 int imap_connection_type, int imap_auth_type,
69 char * imap_login, char * imap_password,
70 int imap_cached, char * imap_cache_directory)
71{
72 struct imap_mailstorage * imap_storage;
73
74 imap_storage = malloc(sizeof(* imap_storage));
75 if (imap_storage == NULL)
76 goto err;
77
78 imap_storage->imap_servername = strdup(imap_servername);
79 if (imap_storage->imap_servername == NULL)
80 goto free;
81
82 imap_storage->imap_connection_type = imap_connection_type;
83
84 if (imap_port == 0) {
85 switch (imap_connection_type) {
86 case CONNECTION_TYPE_PLAIN:
87 case CONNECTION_TYPE_TRY_STARTTLS:
88 case CONNECTION_TYPE_STARTTLS:
89 case CONNECTION_TYPE_COMMAND:
90 case CONNECTION_TYPE_COMMAND_TRY_STARTTLS:
91 case CONNECTION_TYPE_COMMAND_STARTTLS:
92 imap_port = IMAP_DEFAULT_PORT;
93 break;
94
95 case CONNECTION_TYPE_TLS:
96 case CONNECTION_TYPE_COMMAND_TLS:
97 imap_port = IMAPS_DEFAULT_PORT;
98 break;
99 }
100 }
101
102 imap_storage->imap_port = imap_port;
103
104 if (imap_command != NULL) {
105 imap_storage->imap_command = strdup(imap_command);
106 if (imap_storage->imap_command == NULL)
107 goto free_servername;
108 }
109 else
110 imap_storage->imap_command = NULL;
111
112 imap_storage->imap_auth_type = imap_auth_type;
113
114 if (imap_login != NULL) {
115 imap_storage->imap_login = strdup(imap_login);
116 if (imap_storage->imap_login == NULL)
117 goto free_command;
118 }
119 else
120 imap_storage->imap_login = NULL;
121
122 if (imap_password != NULL) {
123 imap_storage->imap_password = strdup(imap_password);
124 if (imap_storage->imap_password == NULL)
125 goto free_login;
126 }
127 else
128 imap_storage->imap_password = NULL;
129
130 imap_storage->imap_cached = imap_cached;
131
132 if (imap_cached && (imap_cache_directory != NULL)) {
133 imap_storage->imap_cache_directory = strdup(imap_cache_directory);
134 if (imap_storage->imap_cache_directory == NULL)
135 goto free_password;
136 }
137 else {
138 imap_storage->imap_cached = FALSE;
139 imap_storage->imap_cache_directory = NULL;
140 }
141
142 storage->sto_data = imap_storage;
143 storage->sto_driver = &imap_mailstorage_driver;
144
145 return MAIL_NO_ERROR;
146
147 free_password:
148 free(imap_storage->imap_password);
149 free_login:
150 free(imap_storage->imap_login);
151 free_command:
152 free(imap_storage->imap_command);
153 free_servername:
154 free(imap_storage->imap_servername);
155 free:
156 free(imap_storage);
157 err:
158 return MAIL_ERROR_MEMORY;
159}
160
161static void imap_mailstorage_uninitialize(struct mailstorage * storage)
162{
163 struct imap_mailstorage * imap_storage;
164
165 imap_storage = storage->sto_data;
166
167 if (imap_storage->imap_cache_directory != NULL)
168 free(imap_storage->imap_cache_directory);
169 if (imap_storage->imap_password != NULL)
170 free(imap_storage->imap_password);
171 if (imap_storage->imap_login != NULL)
172 free(imap_storage->imap_login);
173 if (imap_storage->imap_command != NULL)
174 free(imap_storage->imap_command);
175 free(imap_storage->imap_servername);
176 free(imap_storage);
177
178 storage->sto_data = NULL;
179}
180
181static int imap_connect(struct mailstorage * storage,
182 mailsession ** result)
183{
184 struct imap_mailstorage * imap_storage;
185 mailsession_driver * driver;
186 int r;
187 int res;
188 mailsession * session;
189
190 imap_storage = storage->sto_data;
191
192 if (imap_storage->imap_cached)
193 driver = imap_cached_session_driver;
194 else
195 driver = imap_session_driver;
196
197 r = mailstorage_generic_connect(driver,
198 imap_storage->imap_servername,
199 imap_storage->imap_port,
200 imap_storage->imap_command,
201 imap_storage->imap_connection_type,
202 IMAPDRIVER_CACHED_SET_CACHE_DIRECTORY,
203 imap_storage->imap_cache_directory,
204 0, NULL,
205 &session);
206 switch (r) {
207 case MAIL_NO_ERROR_NON_AUTHENTICATED:
208 case MAIL_NO_ERROR_AUTHENTICATED:
209 case MAIL_NO_ERROR:
210 break;
211 default:
212 res = r;
213 goto err;
214 }
215
216 r = mailstorage_generic_auth(session, r,
217 imap_storage->imap_connection_type,
218 imap_storage->imap_login,
219 imap_storage->imap_password);
220 if (r != MAIL_NO_ERROR) {
221 res = r;
222 goto free;
223 }
224
225 * result = session;
226
227 return MAIL_NO_ERROR;
228
229 free:
230 mailsession_free(session);
231 err:
232 return res;
233}
234
235static int imap_mailstorage_connect(struct mailstorage * storage)
236{
237 mailsession * session;
238 int r;
239 int res;
240
241 r = imap_connect(storage, &session);
242 if (r != MAIL_NO_ERROR) {
243 res = r;
244 goto err;
245 }
246
247 r = mailsession_select_folder(session, "INBOX");
248 if (r != MAIL_NO_ERROR) {
249 mailsession_logout(session);
250 res = r;
251 goto err;
252 }
253
254 storage->sto_session = session;
255 storage->sto_driver = &imap_mailstorage_driver;
256
257 return MAIL_NO_ERROR;
258
259 err:
260 return res;
261}
262
263static int
264imap_mailstorage_get_folder_session(struct mailstorage * storage,
265 char * pathname, mailsession ** result)
266{
267 mailsession * session;
268 int r;
269 int res;
270
271 if (strcasecmp(pathname, "INBOX") == 0) {
272 session = storage->sto_session;
273 }
274 else {
275 r = imap_connect(storage, &session);
276 if (r != MAIL_NO_ERROR) {
277 res = r;
278 goto err;
279 }
280
281 r = mailsession_select_folder(session, pathname);
282 if (r != MAIL_NO_ERROR) {
283 mailsession_logout(session);
284 res = r;
285 goto free;
286 }
287 }
288
289 * result = session;
290
291 return MAIL_NO_ERROR;
292
293 free:
294 mailsession_free(session);
295 err:
296 return res;
297}
diff --git a/libetpan/src/driver/implementation/imap/imapstorage.h b/libetpan/src/driver/implementation/imap/imapstorage.h
new file mode 100644
index 0000000..929a86e
--- a/dev/null
+++ b/libetpan/src/driver/implementation/imap/imapstorage.h
@@ -0,0 +1,90 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2005 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36#ifndef IMAPSTORAGE_H
37
38#define IMAPSTORAGE_H
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44#include <libetpan/imapdriver_types.h>
45
46/*
47 imap_mailstorage_init is the constructor for a IMAP4rev1 storage
48
49 @param storage this is the storage to initialize.
50
51 @param servername this is the name of the IMAP4rev1 server
52
53 @param port is the port to connect to, on the server.
54 you give 0 to use the default port.
55
56 @param command the command used to connect to the server instead of
57 allowing normal TCP connections to be used.
58
59 @param connection_type is the type of socket layer to use.
60 The value can be CONNECTION_TYPE_PLAIN, CONNECTION_TYPE_STARTTLS,
61 CONNECTION_TYPE_TRY_STARTTLS, CONNECTION_TYPE_TLS,
62 CONNECTION_TYPE_COMMAND, CONNECTION_TYPE_COMMAND_STARTTLS,
63 CONNECTION_TYPE_COMMAND_TRY_STARTTLS, CONNECTION_TYPE_COMMAND_TLS,.
64
65 @param auth_type is the authenticate mechanism to use.
66 The value can be IMAP_AUTH_TYPE_PLAIN.
67 Other values are not yet implemented.
68
69 @param login is the login of the IMAP4rev1 account.
70
71 @param password is the password of the IMAP4rev1 account.
72
73 @param cached if this value is != 0, a persistant cache will be
74 stored on local system.
75
76 @param cache_directory is the location of the cache
77*/
78
79int imap_mailstorage_init(struct mailstorage * storage,
80 char * imap_servername, uint16_t imap_port,
81 char * imap_command,
82 int imap_connection_type, int imap_auth_type,
83 char * imap_login, char * imap_password,
84 int imap_cached, char * imap_cache_directory);
85
86#ifdef __cplusplus
87}
88#endif
89
90#endif