summaryrefslogtreecommitdiffabout
path: root/libetpan/src/driver/implementation/imap/imapdriver_tools.c
Unidiff
Diffstat (limited to 'libetpan/src/driver/implementation/imap/imapdriver_tools.c') (more/less context) (ignore whitespace changes)
-rw-r--r--libetpan/src/driver/implementation/imap/imapdriver_tools.c3623
1 files changed, 3623 insertions, 0 deletions
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