7 #include "imap-thread.h"
16 #include "etpan-thread-manager.h"
19 static struct etpan_thread_manager * thread_manager = NULL;
20 static chash * courier_workaround_hash = NULL;
21 static chash * imap_hash = NULL;
22 static chash * session_hash = NULL;
23 static guint thread_manager_signal = 0;
24 static GIOChannel * io_channel = NULL;
27 static gboolean thread_manager_event(GIOChannel * source,
28 GIOCondition condition,
31 etpan_thread_manager_loop(thread_manager);
37 #define ETPAN_DEFAULT_NETWORK_TIMEOUT 60
39 void imap_main_init(void)
41 int fd_thread_manager;
43 mailstream_network_delay.tv_sec = ETPAN_DEFAULT_NETWORK_TIMEOUT;
44 mailstream_network_delay.tv_usec = 0;
49 imap_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
50 session_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
51 courier_workaround_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
53 thread_manager = etpan_thread_manager_new();
55 fd_thread_manager = etpan_thread_manager_get_fd(thread_manager);
57 io_channel = g_io_channel_unix_new(fd_thread_manager);
59 thread_manager_signal = g_io_add_watch_full(io_channel, 0, G_IO_IN,
65 void imap_main_set_timeout(int sec)
67 mailstream_network_delay.tv_sec = sec;
68 mailstream_network_delay.tv_usec = 0;
71 void imap_main_done(void)
73 etpan_thread_manager_stop(thread_manager);
74 etpan_thread_manager_join(thread_manager);
76 g_source_remove(thread_manager_signal);
77 g_io_channel_unref(io_channel);
79 etpan_thread_manager_free(thread_manager);
81 chash_free(courier_workaround_hash);
82 chash_free(session_hash);
83 chash_free(imap_hash);
86 void imap_init(Folder * folder)
88 struct etpan_thread * thread;
92 thread = etpan_thread_manager_get_thread(thread_manager);
95 key.len = sizeof(folder);
99 chash_set(imap_hash, &key, &value, NULL);
102 void imap_done(Folder * folder)
104 struct etpan_thread * thread;
110 key.len = sizeof(folder);
112 r = chash_get(imap_hash, &key, &value);
118 etpan_thread_unbind(thread);
120 chash_delete(imap_hash, &key, NULL);
122 debug_print("remove thread");
125 static struct etpan_thread * get_thread(Folder * folder)
127 struct etpan_thread * thread;
132 key.len = sizeof(folder);
134 chash_get(imap_hash, &key, &value);
140 static mailimap * get_imap(Folder * folder)
148 key.len = sizeof(folder);
150 r = chash_get(session_hash, &key, &value);
160 static void generic_cb(int cancelled, void * result, void * callback_data)
164 p_finished = callback_data;
166 debug_print("generic_cb\n");
171 static void threaded_run(Folder * folder, void * param, void * result,
172 void (* func)(struct etpan_thread_op * ))
174 struct etpan_thread_op * op;
175 struct etpan_thread * thread;
178 imap_folder_ref(folder);
180 op = etpan_thread_op_new();
186 op->callback = generic_cb;
187 op->callback_data = &finished;
192 thread = get_thread(folder);
193 etpan_thread_op_schedule(thread, op);
196 gtk_main_iteration();
199 etpan_thread_op_free(op);
201 imap_folder_unref(folder);
207 struct connect_param {
213 struct connect_result {
217 static void connect_run(struct etpan_thread_op * op)
220 struct connect_param * param;
221 struct connect_result * result;
226 r = mailimap_socket_connect(param->imap,
227 param->server, param->port);
233 int imap_threaded_connect(Folder * folder, const char * server, int port)
235 struct connect_param param;
236 struct connect_result result;
241 imap = mailimap_new(0, NULL);
244 key.len = sizeof(folder);
247 chash_set(session_hash, &key, &value, NULL);
250 param.server = server;
253 threaded_run(folder, ¶m, &result, connect_run);
255 debug_print("connect ok %i\n", result.error);
261 static void connect_ssl_run(struct etpan_thread_op * op)
264 struct connect_param * param;
265 struct connect_result * result;
270 r = mailimap_ssl_connect(param->imap,
271 param->server, param->port);
276 int imap_threaded_connect_ssl(Folder * folder, const char * server, int port)
278 struct connect_param param;
279 struct connect_result result;
284 imap = mailimap_new(0, NULL);
287 key.len = sizeof(folder);
290 chash_set(session_hash, &key, &value, NULL);
293 param.server = server;
296 threaded_run(folder, ¶m, &result, connect_ssl_run);
298 debug_print("connect ok\n");
303 struct disconnect_param {
307 struct disconnect_result {
311 static void disconnect_run(struct etpan_thread_op * op)
314 struct disconnect_param * param;
315 struct disconnect_result * result;
320 r = mailimap_logout(param->imap);
325 void imap_threaded_disconnect(Folder * folder)
327 struct connect_param param;
328 struct connect_result result;
333 imap = get_imap(folder);
335 debug_print("was disconnected\n");
341 threaded_run(folder, ¶m, &result, disconnect_run);
344 key.len = sizeof(folder);
347 chash_delete(session_hash, &key, NULL);
350 key.len = sizeof(imap);
351 chash_delete(courier_workaround_hash, &key, NULL);
355 debug_print("disconnect ok\n");
362 const char * wildcard;
370 static void list_run(struct etpan_thread_op * op)
372 struct list_param * param;
373 struct list_result * result;
379 r = mailimap_list(param->imap, param->base,
380 param->wildcard, &list);
385 debug_print("imap list run - end\n");
388 int imap_threaded_list(Folder * folder, const char * base,
389 const char * wildcard,
392 struct list_param param;
393 struct list_result result;
395 debug_print("imap list - begin\n");
397 param.imap = get_imap(folder);
399 param.wildcard = wildcard;
401 threaded_run(folder, ¶m, &result, list_run);
403 * p_result = result.list;
405 debug_print("imap list - end %p\n", result.list);
415 const char * password;
418 struct login_result {
422 static void login_run(struct etpan_thread_op * op)
424 struct login_param * param;
425 struct login_result * result;
429 r = mailimap_login(param->imap,
430 param->login, param->password);
434 debug_print("imap login run - end %i\n", r);
437 int imap_threaded_login(Folder * folder,
438 const char * login, const char * password)
440 struct login_param param;
441 struct login_result result;
443 debug_print("imap login - begin\n");
445 param.imap = get_imap(folder);
447 param.password = password;
449 threaded_run(folder, ¶m, &result, login_run);
451 debug_print("imap login - end\n");
457 struct status_param {
460 struct mailimap_status_att_list * status_att_list;
463 struct status_result {
465 struct mailimap_mailbox_data_status * data_status;
468 static void status_run(struct etpan_thread_op * op)
470 struct status_param * param;
471 struct status_result * result;
477 r = mailimap_status(param->imap, param->mb,
478 param->status_att_list,
479 &result->data_status);
482 debug_print("imap status run - end %i\n", r);
485 int imap_threaded_status(Folder * folder, const char * mb,
486 struct mailimap_mailbox_data_status ** data_status)
488 struct status_param param;
489 struct status_result result;
490 struct mailimap_status_att_list * status_att_list;
492 debug_print("imap status - begin\n");
494 status_att_list = mailimap_status_att_list_new_empty();
495 mailimap_status_att_list_add(status_att_list,
496 MAILIMAP_STATUS_ATT_MESSAGES);
497 mailimap_status_att_list_add(status_att_list,
498 MAILIMAP_STATUS_ATT_RECENT);
499 mailimap_status_att_list_add(status_att_list,
500 MAILIMAP_STATUS_ATT_UIDNEXT);
501 mailimap_status_att_list_add(status_att_list,
502 MAILIMAP_STATUS_ATT_UIDVALIDITY);
503 mailimap_status_att_list_add(status_att_list,
504 MAILIMAP_STATUS_ATT_UNSEEN);
506 param.imap = get_imap(folder);
508 param.status_att_list = status_att_list;
510 threaded_run(folder, ¶m, &result, status_run);
512 debug_print("imap status - end\n");
514 * data_status = result.data_status;
529 static void noop_run(struct etpan_thread_op * op)
531 struct noop_param * param;
532 struct noop_result * result;
536 r = mailimap_noop(param->imap);
540 debug_print("imap noop run - end %i\n", r);
543 int imap_threaded_noop(Folder * folder, unsigned int * p_exists)
545 struct noop_param param;
546 struct noop_result result;
549 debug_print("imap noop - begin\n");
551 imap = get_imap(folder);
554 threaded_run(folder, ¶m, &result, noop_run);
556 if (imap->imap_selection_info != NULL) {
557 * p_exists = imap->imap_selection_info->sel_exists;
563 debug_print("imap noop - end\n");
569 struct starttls_param {
573 struct starttls_result {
577 static void starttls_run(struct etpan_thread_op * op)
579 struct starttls_param * param;
580 struct starttls_result * result;
584 r = mailimap_starttls(param->imap);
588 debug_print("imap starttls run - end %i\n", r);
591 int imap_threaded_starttls(Folder * folder)
593 struct starttls_param param;
594 struct starttls_result result;
596 debug_print("imap starttls - begin\n");
598 param.imap = get_imap(folder);
600 threaded_run(folder, ¶m, &result, starttls_run);
602 debug_print("imap starttls - end\n");
609 struct create_param {
614 struct create_result {
618 static void create_run(struct etpan_thread_op * op)
620 struct create_param * param;
621 struct create_result * result;
625 r = mailimap_create(param->imap, param->mb);
629 debug_print("imap create run - end %i\n", r);
632 int imap_threaded_create(Folder * folder, const char * mb)
634 struct create_param param;
635 struct create_result result;
637 debug_print("imap create - begin\n");
639 param.imap = get_imap(folder);
642 threaded_run(folder, ¶m, &result, create_run);
644 debug_print("imap create - end\n");
652 struct rename_param {
655 const char * new_name;
658 struct rename_result {
662 static void rename_run(struct etpan_thread_op * op)
664 struct rename_param * param;
665 struct rename_result * result;
669 r = mailimap_rename(param->imap, param->mb, param->new_name);
673 debug_print("imap rename run - end %i\n", r);
676 int imap_threaded_rename(Folder * folder,
677 const char * mb, const char * new_name)
679 struct rename_param param;
680 struct rename_result result;
682 debug_print("imap rename - begin\n");
684 param.imap = get_imap(folder);
686 param.new_name = new_name;
688 threaded_run(folder, ¶m, &result, rename_run);
690 debug_print("imap rename - end\n");
698 struct delete_param {
703 struct delete_result {
707 static void delete_run(struct etpan_thread_op * op)
709 struct delete_param * param;
710 struct delete_result * result;
714 r = mailimap_delete(param->imap, param->mb);
718 debug_print("imap delete run - end %i\n", r);
721 int imap_threaded_delete(Folder * folder, const char * mb)
723 struct delete_param param;
724 struct delete_result result;
726 debug_print("imap delete - begin\n");
728 param.imap = get_imap(folder);
731 threaded_run(folder, ¶m, &result, delete_run);
733 debug_print("imap delete - end\n");
740 struct select_param {
745 struct select_result {
749 static void select_run(struct etpan_thread_op * op)
751 struct select_param * param;
752 struct select_result * result;
756 r = mailimap_select(param->imap, param->mb);
760 debug_print("imap select run - end %i\n", r);
763 int imap_threaded_select(Folder * folder, const char * mb,
764 gint * exists, gint * recent, gint * unseen,
765 guint32 * uid_validity)
767 struct select_param param;
768 struct select_result result;
771 debug_print("imap select - begin\n");
773 imap = get_imap(folder);
777 threaded_run(folder, ¶m, &result, select_run);
779 if (result.error != MAILIMAP_NO_ERROR)
782 if (imap->imap_selection_info == NULL)
783 return MAILIMAP_ERROR_PARSE;
785 * exists = imap->imap_selection_info->sel_exists;
786 * recent = imap->imap_selection_info->sel_recent;
787 * unseen = imap->imap_selection_info->sel_unseen;
788 * uid_validity = imap->imap_selection_info->sel_uidvalidity;
790 debug_print("imap select - end\n");
797 struct examine_param {
802 struct examine_result {
806 static void examine_run(struct etpan_thread_op * op)
808 struct examine_param * param;
809 struct examine_result * result;
813 r = mailimap_examine(param->imap, param->mb);
817 debug_print("imap examine run - end %i\n", r);
820 int imap_threaded_examine(Folder * folder, const char * mb,
821 gint * exists, gint * recent, gint * unseen,
822 guint32 * uid_validity)
824 struct examine_param param;
825 struct examine_result result;
828 debug_print("imap examine - begin\n");
830 imap = get_imap(folder);
834 threaded_run(folder, ¶m, &result, examine_run);
836 if (result.error != MAILIMAP_NO_ERROR)
839 if (imap->imap_selection_info == NULL)
840 return MAILIMAP_ERROR_PARSE;
842 * exists = imap->imap_selection_info->sel_exists;
843 * recent = imap->imap_selection_info->sel_recent;
844 * unseen = imap->imap_selection_info->sel_unseen;
845 * uid_validity = imap->imap_selection_info->sel_uidvalidity;
847 debug_print("imap examine - end\n");
855 struct search_param {
858 struct mailimap_set * set;
861 struct search_result {
863 clist * search_result;
866 static void search_run(struct etpan_thread_op * op)
868 struct search_param * param;
869 struct search_result * result;
871 struct mailimap_search_key * key;
872 struct mailimap_search_key * uid_key;
873 struct mailimap_search_key * search_type_key;
874 clist * search_result;
878 uid_key = mailimap_search_key_new_uid(param->set);
880 search_type_key = NULL;
881 switch (param->type) {
882 case IMAP_SEARCH_TYPE_SIMPLE:
883 search_type_key = NULL;
886 case IMAP_SEARCH_TYPE_SEEN:
887 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SEEN,
888 NULL, NULL, NULL, NULL, NULL,
889 NULL, NULL, NULL, NULL, NULL,
890 NULL, NULL, NULL, NULL, 0,
891 NULL, NULL, NULL, NULL, NULL,
892 NULL, 0, NULL, NULL, NULL);
895 case IMAP_SEARCH_TYPE_UNSEEN:
896 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN,
897 NULL, NULL, NULL, NULL, NULL,
898 NULL, NULL, NULL, NULL, NULL,
899 NULL, NULL, NULL, NULL, 0,
900 NULL, NULL, NULL, NULL, NULL,
901 NULL, 0, NULL, NULL, NULL);
904 case IMAP_SEARCH_TYPE_ANSWERED:
905 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ANSWERED,
906 NULL, NULL, NULL, NULL, NULL,
907 NULL, NULL, NULL, NULL, NULL,
908 NULL, NULL, NULL, NULL, 0,
909 NULL, NULL, NULL, NULL, NULL,
910 NULL, 0, NULL, NULL, NULL);
913 case IMAP_SEARCH_TYPE_FLAGGED:
914 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FLAGGED,
915 NULL, NULL, NULL, NULL, NULL,
916 NULL, NULL, NULL, NULL, NULL,
917 NULL, NULL, NULL, NULL, 0,
918 NULL, NULL, NULL, NULL, NULL,
919 NULL, 0, NULL, NULL, NULL);
923 if (search_type_key != NULL) {
924 key = mailimap_search_key_new_multiple_empty();
925 mailimap_search_key_multiple_add(key, search_type_key);
926 mailimap_search_key_multiple_add(key, uid_key);
932 r = mailimap_uid_search(param->imap, NULL, key, &search_result);
936 result->search_result = search_result;
937 debug_print("imap search run - end %i\n", r);
940 int imap_threaded_search(Folder * folder, int search_type,
941 struct mailimap_set * set, clist ** search_result)
943 struct search_param param;
944 struct search_result result;
947 debug_print("imap search - begin\n");
949 imap = get_imap(folder);
952 param.type = search_type;
954 threaded_run(folder, ¶m, &result, search_run);
956 if (result.error != MAILIMAP_NO_ERROR)
959 debug_print("imap search - end\n");
961 * search_result = result.search_result;
970 uid_list_to_env_list(clist * fetch_result, carray ** result)
978 tab = carray_new(128);
980 res = MAILIMAP_ERROR_MEMORY;
984 for(cur = clist_begin(fetch_result) ; cur != NULL ;
985 cur = clist_next(cur)) {
986 struct mailimap_msg_att * msg_att;
987 clistiter * item_cur;
992 msg_att = clist_content(cur);
996 for(item_cur = clist_begin(msg_att->att_list) ;
998 item_cur = clist_next(item_cur)) {
999 struct mailimap_msg_att_item * item;
1001 item = clist_content(item_cur);
1003 switch (item->att_type) {
1004 case MAILIMAP_MSG_ATT_ITEM_STATIC:
1005 switch (item->att_data.att_static->att_type) {
1006 case MAILIMAP_MSG_ATT_UID:
1007 uid = item->att_data.att_static->att_data.att_uid;
1013 puid = malloc(sizeof(* puid));
1015 res = MAILIMAP_ERROR_MEMORY;
1020 r = carray_add(tab, puid, NULL);
1023 res = MAILIMAP_ERROR_MEMORY;
1030 return MAILIMAP_NO_ERROR;
1033 for(i = 0 ; i < carray_count(tab) ; i++)
1034 mailmessage_free(carray_get(tab, i));
1039 static int imap_get_messages_list(mailimap * imap,
1040 uint32_t first_index,
1045 struct mailimap_fetch_att * fetch_att;
1046 struct mailimap_fetch_type * fetch_type;
1047 struct mailimap_set * set;
1048 clist * fetch_result;
1051 set = mailimap_set_new_interval(first_index, 0);
1053 res = MAILIMAP_ERROR_MEMORY;
1057 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
1058 if (fetch_type == NULL) {
1059 res = MAILIMAP_ERROR_MEMORY;
1063 fetch_att = mailimap_fetch_att_new_uid();
1064 if (fetch_att == NULL) {
1065 res = MAILIMAP_ERROR_MEMORY;
1066 goto free_fetch_type;
1069 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1070 if (r != MAILIMAP_NO_ERROR) {
1071 mailimap_fetch_att_free(fetch_att);
1072 res = MAILIMAP_ERROR_MEMORY;
1073 goto free_fetch_type;
1076 r = mailimap_uid_fetch(imap, set,
1077 fetch_type, &fetch_result);
1079 mailimap_fetch_type_free(fetch_type);
1080 mailimap_set_free(set);
1082 if (r != MAILIMAP_NO_ERROR) {
1088 r = uid_list_to_env_list(fetch_result, &env_list);
1089 mailimap_fetch_list_free(fetch_result);
1091 * result = env_list;
1093 return MAILIMAP_NO_ERROR;
1096 mailimap_fetch_type_free(fetch_type);
1098 mailimap_set_free(set);
1106 struct fetch_uid_param {
1108 uint32_t first_index;
1111 struct fetch_uid_result {
1113 carray * fetch_result;
1116 static void fetch_uid_run(struct etpan_thread_op * op)
1118 struct fetch_uid_param * param;
1119 struct fetch_uid_result * result;
1120 carray * fetch_result;
1125 fetch_result = NULL;
1126 r = imap_get_messages_list(param->imap, param->first_index,
1129 result = op->result;
1131 result->fetch_result = fetch_result;
1132 debug_print("imap fetch_uid run - end %i\n", r);
1135 int imap_threaded_fetch_uid(Folder * folder, uint32_t first_index,
1136 carray ** fetch_result)
1138 struct fetch_uid_param param;
1139 struct fetch_uid_result result;
1142 debug_print("imap fetch_uid - begin\n");
1144 imap = get_imap(folder);
1146 param.first_index = first_index;
1148 threaded_run(folder, ¶m, &result, fetch_uid_run);
1150 if (result.error != MAILIMAP_NO_ERROR)
1151 return result.error;
1153 debug_print("imap fetch_uid - end\n");
1155 * fetch_result = result.fetch_result;
1157 return result.error;
1161 void imap_fetch_uid_list_free(carray * uid_list)
1165 for(i = 0 ; i < carray_count(uid_list) ; i ++) {
1168 puid = carray_get(uid_list, i);
1171 carray_free(uid_list);
1176 static int imap_fetch(mailimap * imap,
1179 size_t * result_len)
1182 struct mailimap_set * set;
1183 struct mailimap_fetch_att * fetch_att;
1184 struct mailimap_fetch_type * fetch_type;
1185 clist * fetch_result;
1186 struct mailimap_msg_att * msg_att;
1187 struct mailimap_msg_att_item * msg_att_item;
1192 struct mailimap_section * section;
1194 set = mailimap_set_new_single(msg_index);
1196 res = MAILIMAP_ERROR_MEMORY;
1200 section = mailimap_section_new(NULL);
1201 if (section == NULL) {
1202 res = MAILIMAP_ERROR_MEMORY;
1206 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1207 if (fetch_att == NULL) {
1208 mailimap_section_free(section);
1209 res = MAILIMAP_ERROR_MEMORY;
1213 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1214 if (fetch_type == NULL) {
1215 res = MAILIMAP_ERROR_MEMORY;
1216 goto free_fetch_att;
1219 r = mailimap_uid_fetch(imap, set,
1220 fetch_type, &fetch_result);
1222 mailimap_fetch_type_free(fetch_type);
1223 mailimap_set_free(set);
1226 case MAILIMAP_NO_ERROR:
1232 if (clist_begin(fetch_result) == NULL) {
1233 mailimap_fetch_list_free(fetch_result);
1234 return MAILIMAP_ERROR_FETCH;
1237 msg_att = clist_begin(fetch_result)->data;
1242 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
1243 cur = clist_next(cur)) {
1244 msg_att_item = clist_content(cur);
1246 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
1247 if (msg_att_item->att_data.att_static->att_type ==
1248 MAILIMAP_MSG_ATT_BODY_SECTION) {
1249 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
1251 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
1253 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
1258 mailimap_fetch_list_free(fetch_result);
1261 return MAILIMAP_ERROR_FETCH;
1264 * result_len = text_length;
1266 return MAILIMAP_NO_ERROR;
1269 mailimap_fetch_att_free(fetch_att);
1271 mailimap_set_free(set);
1276 static int imap_fetch_header(mailimap * imap,
1279 size_t * result_len)
1282 struct mailimap_set * set;
1283 struct mailimap_fetch_att * fetch_att;
1284 struct mailimap_fetch_type * fetch_type;
1285 clist * fetch_result;
1286 struct mailimap_msg_att * msg_att;
1287 struct mailimap_msg_att_item * msg_att_item;
1292 struct mailimap_section * section;
1294 set = mailimap_set_new_single(msg_index);
1296 res = MAILIMAP_ERROR_MEMORY;
1300 section = mailimap_section_new_header();
1301 if (section == NULL) {
1302 res = MAILIMAP_ERROR_MEMORY;
1306 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1307 if (fetch_att == NULL) {
1308 mailimap_section_free(section);
1309 res = MAILIMAP_ERROR_MEMORY;
1313 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1314 if (fetch_type == NULL) {
1315 res = MAILIMAP_ERROR_MEMORY;
1316 goto free_fetch_att;
1319 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
1321 mailimap_fetch_type_free(fetch_type);
1322 mailimap_set_free(set);
1325 case MAILIMAP_NO_ERROR:
1331 if (clist_begin(fetch_result) == NULL) {
1332 mailimap_fetch_list_free(fetch_result);
1333 return MAILIMAP_ERROR_FETCH;
1336 msg_att = clist_begin(fetch_result)->data;
1341 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
1342 cur = clist_next(cur)) {
1343 msg_att_item = clist_content(cur);
1345 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
1346 if (msg_att_item->att_data.att_static->att_type ==
1347 MAILIMAP_MSG_ATT_BODY_SECTION) {
1348 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
1349 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
1351 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
1356 mailimap_fetch_list_free(fetch_result);
1359 return MAILIMAP_ERROR_FETCH;
1362 * result_len = text_length;
1364 return MAILIMAP_NO_ERROR;
1367 mailimap_fetch_att_free(fetch_att);
1369 mailimap_set_free(set);
1376 struct fetch_content_param {
1379 const char * filename;
1383 struct fetch_content_result {
1387 static void fetch_content_run(struct etpan_thread_op * op)
1389 struct fetch_content_param * param;
1390 struct fetch_content_result * result;
1392 size_t content_size;
1401 if (param->with_body)
1402 r = imap_fetch(param->imap, param->msg_index,
1403 &content, &content_size);
1405 r = imap_fetch_header(param->imap, param->msg_index,
1406 &content, &content_size);
1408 result = op->result;
1411 if (r == MAILIMAP_NO_ERROR) {
1412 fd = open(param->filename, O_RDWR | O_CREAT, 0600);
1414 result->error = MAILIMAP_ERROR_FETCH;
1418 f = fdopen(fd, "wb");
1420 result->error = MAILIMAP_ERROR_FETCH;
1424 r = fwrite(content, 1, content_size, f);
1431 unlink(param->filename);
1442 unlink(param->filename);
1445 if (mmap_string_unref(content) != 0)
1449 debug_print("imap fetch_content run - end %i\n", r);
1452 int imap_threaded_fetch_content(Folder * folder, uint32_t msg_index,
1454 const char * filename)
1456 struct fetch_content_param param;
1457 struct fetch_content_result result;
1460 debug_print("imap fetch_content - begin\n");
1462 imap = get_imap(folder);
1464 param.msg_index = msg_index;
1465 param.filename = filename;
1466 param.with_body = with_body;
1468 threaded_run(folder, ¶m, &result, fetch_content_run);
1470 if (result.error != MAILIMAP_NO_ERROR)
1471 return result.error;
1473 debug_print("imap fetch_content - end\n");
1475 return result.error;
1480 static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn)
1488 flag_list = att_dyn->att_list;
1489 if (flag_list == NULL)
1492 for(cur = clist_begin(flag_list) ; cur != NULL ;
1493 cur = clist_next(cur)) {
1494 struct mailimap_flag_fetch * flag_fetch;
1496 flag_fetch = clist_content(cur);
1497 if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT)
1500 switch (flag_fetch->fl_flag->fl_type) {
1501 case MAILIMAP_FLAG_ANSWERED:
1502 flags |= MSG_REPLIED;
1504 case MAILIMAP_FLAG_FLAGGED:
1505 flags |= MSG_MARKED;
1507 case MAILIMAP_FLAG_DELETED:
1508 flags |= MSG_DELETED;
1510 case MAILIMAP_FLAG_SEEN:
1511 flags &= ~MSG_UNREAD;
1521 static int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
1525 struct mailimap_msg_att_dynamic ** patt_dyn)
1527 clistiter * item_cur;
1531 struct mailimap_msg_att_dynamic * att_dyn;
1538 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
1539 item_cur = clist_next(item_cur)) {
1540 struct mailimap_msg_att_item * item;
1542 item = clist_content(item_cur);
1544 switch (item->att_type) {
1545 case MAILIMAP_MSG_ATT_ITEM_STATIC:
1546 switch (item->att_data.att_static->att_type) {
1547 case MAILIMAP_MSG_ATT_UID:
1548 uid = item->att_data.att_static->att_data.att_uid;
1551 case MAILIMAP_MSG_ATT_BODY_SECTION:
1552 if (headers == NULL) {
1553 headers = item->att_data.att_static->att_data.att_body_section->sec_body_part;
1556 case MAILIMAP_MSG_ATT_RFC822_SIZE:
1557 ref_size = item->att_data.att_static->att_data.att_rfc822_size;
1562 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
1563 if (att_dyn == NULL) {
1564 att_dyn = item->att_data.att_dyn;
1572 if (pheaders != NULL)
1573 * pheaders = headers;
1574 if (pref_size != NULL)
1575 * pref_size = ref_size;
1576 if (patt_dyn != NULL)
1577 * patt_dyn = att_dyn;
1579 return MAIL_NO_ERROR;
1582 static struct imap_fetch_env_info *
1583 fetch_to_env_info(struct mailimap_msg_att * msg_att)
1585 struct imap_fetch_env_info * info;
1589 struct mailimap_msg_att_dynamic * att_dyn;
1591 imap_get_msg_att_info(msg_att, &uid, &headers, &size,
1594 info = malloc(sizeof(* info));
1596 info->headers = strdup(headers);
1598 info->flags = imap_flags_to_flags(att_dyn);
1604 imap_fetch_result_to_envelop_list(clist * fetch_result,
1605 carray ** p_env_list)
1613 env_list = carray_new(16);
1615 for(cur = clist_begin(fetch_result) ; cur != NULL ;
1616 cur = clist_next(cur)) {
1617 struct mailimap_msg_att * msg_att;
1618 struct imap_fetch_env_info * env_info;
1620 msg_att = clist_content(cur);
1622 env_info = fetch_to_env_info(msg_att);
1623 carray_add(env_list, env_info, NULL);
1626 * p_env_list = env_list;
1628 return MAIL_NO_ERROR;
1631 int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type)
1633 struct mailimap_fetch_att * fetch_att;
1637 struct mailimap_header_list * imap_hdrlist;
1638 struct mailimap_section * section;
1640 hdrlist = clist_new();
1642 header = strdup("Date");
1643 r = clist_append(hdrlist, header);
1644 header = strdup("From");
1645 r = clist_append(hdrlist, header);
1646 header = strdup("To");
1647 r = clist_append(hdrlist, header);
1648 header = strdup("Cc");
1649 r = clist_append(hdrlist, header);
1650 header = strdup("Subject");
1651 r = clist_append(hdrlist, header);
1652 header = strdup("Message-ID");
1653 r = clist_append(hdrlist, header);
1654 header = strdup("References");
1655 r = clist_append(hdrlist, header);
1656 header = strdup("In-Reply-To");
1657 r = clist_append(hdrlist, header);
1659 imap_hdrlist = mailimap_header_list_new(hdrlist);
1660 section = mailimap_section_new_header_fields(imap_hdrlist);
1661 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1662 mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1664 return MAIL_NO_ERROR;
1667 int imap_add_header_fetch_att(struct mailimap_fetch_type * fetch_type)
1669 struct mailimap_fetch_att * fetch_att;
1670 struct mailimap_section * section;
1672 section = mailimap_section_new_header();
1673 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1674 mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1676 return MAIL_NO_ERROR;
1680 imap_get_envelopes_list(mailimap * imap, struct mailimap_set * set,
1681 carray ** p_env_list)
1683 struct mailimap_fetch_att * fetch_att;
1684 struct mailimap_fetch_type * fetch_type;
1686 clist * fetch_result;
1692 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
1695 fetch_att = mailimap_fetch_att_new_uid();
1696 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1699 fetch_att = mailimap_fetch_att_new_flags();
1700 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1703 fetch_att = mailimap_fetch_att_new_rfc822_size();
1704 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1708 key.len = sizeof(imap);
1709 r = chash_get(courier_workaround_hash, &key, &value);
1711 r = imap_add_envelope_fetch_att(fetch_type);
1713 r = imap_add_header_fetch_att(fetch_type);
1715 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
1718 case MAILIMAP_NO_ERROR:
1721 mailimap_fetch_type_free(fetch_type);
1725 if (clist_begin(fetch_result) == NULL) {
1726 res = MAILIMAP_ERROR_FETCH;
1730 r = imap_fetch_result_to_envelop_list(fetch_result, &env_list);
1731 mailimap_fetch_list_free(fetch_result);
1733 if (r != MAILIMAP_NO_ERROR) {
1734 mailimap_fetch_type_free(fetch_type);
1735 res = MAILIMAP_ERROR_MEMORY;
1739 mailimap_fetch_type_free(fetch_type);
1741 * p_env_list = env_list;
1743 return MAILIMAP_NO_ERROR;
1749 struct fetch_env_param {
1751 struct mailimap_set * set;
1754 struct fetch_env_result {
1755 carray * fetch_env_result;
1759 static void fetch_env_run(struct etpan_thread_op * op)
1761 struct fetch_env_param * param;
1762 struct fetch_env_result * result;
1769 r = imap_get_envelopes_list(param->imap, param->set,
1772 result = op->result;
1774 result->fetch_env_result = env_list;
1776 debug_print("imap fetch_env run - end %i\n", r);
1779 int imap_threaded_fetch_env(Folder * folder, struct mailimap_set * set,
1780 carray ** p_env_list)
1782 struct fetch_env_param param;
1783 struct fetch_env_result result;
1786 debug_print("imap fetch_env - begin\n");
1788 imap = get_imap(folder);
1792 threaded_run(folder, ¶m, &result, fetch_env_run);
1794 if (result.error != MAILIMAP_NO_ERROR) {
1800 key.len = sizeof(imap);
1801 r = chash_get(courier_workaround_hash, &key, &value);
1805 chash_set(courier_workaround_hash, &key, &value, NULL);
1807 threaded_run(folder, ¶m, &result, fetch_env_run);
1811 if (result.error != MAILIMAP_NO_ERROR)
1812 return result.error;
1814 debug_print("imap fetch_env - end\n");
1816 * p_env_list = result.fetch_env_result;
1818 return result.error;
1821 void imap_fetch_env_free(carray * env_list)
1825 for(i = 0 ; i < carray_count(env_list) ; i ++) {
1826 struct imap_fetch_env_info * env_info;
1828 env_info = carray_get(env_list, i);
1829 free(env_info->headers);
1832 carray_free(env_list);
1839 struct append_param {
1841 const char * mailbox;
1842 const char * filename;
1843 struct mailimap_flag_list * flag_list;
1846 struct append_result {
1850 static void append_run(struct etpan_thread_op * op)
1852 struct append_param * param;
1853 struct append_result * result;
1857 struct stat stat_buf;
1861 result = op->result;
1863 r = stat(param->filename, &stat_buf);
1865 result->error = MAILIMAP_ERROR_APPEND;
1868 size = stat_buf.st_size;
1870 fd = open(param->filename, O_RDONLY);
1872 result->error = MAILIMAP_ERROR_APPEND;
1876 data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
1877 if (data == (void *) MAP_FAILED) {
1879 result->error = MAILIMAP_ERROR_APPEND;
1883 r = mailimap_append(param->imap, param->mailbox,
1884 param->flag_list, NULL,
1892 debug_print("imap append run - end %i\n", r);
1895 int imap_threaded_append(Folder * folder, const char * mailbox,
1896 const char * filename,
1897 struct mailimap_flag_list * flag_list)
1899 struct append_param param;
1900 struct append_result result;
1903 debug_print("imap append - begin\n");
1905 imap = get_imap(folder);
1907 param.mailbox = mailbox;
1908 param.filename = filename;
1909 param.flag_list = flag_list;
1911 threaded_run(folder, ¶m, &result, append_run);
1913 if (result.error != MAILIMAP_NO_ERROR)
1914 return result.error;
1916 debug_print("imap append - end\n");
1918 return result.error;
1924 struct expunge_param {
1928 struct expunge_result {
1932 static void expunge_run(struct etpan_thread_op * op)
1934 struct expunge_param * param;
1935 struct expunge_result * result;
1939 r = mailimap_expunge(param->imap);
1941 result = op->result;
1943 debug_print("imap expunge run - end %i\n", r);
1946 int imap_threaded_expunge(Folder * folder)
1948 struct expunge_param param;
1949 struct expunge_result result;
1951 debug_print("imap expunge - begin\n");
1953 param.imap = get_imap(folder);
1955 threaded_run(folder, ¶m, &result, expunge_run);
1957 debug_print("imap expunge - end\n");
1959 return result.error;
1965 struct mailimap_set * set;
1969 struct copy_result {
1973 static void copy_run(struct etpan_thread_op * op)
1975 struct copy_param * param;
1976 struct copy_result * result;
1981 r = mailimap_uid_copy(param->imap, param->set, param->mb);
1983 result = op->result;
1986 debug_print("imap copy run - end %i\n", r);
1989 int imap_threaded_copy(Folder * folder, struct mailimap_set * set,
1992 struct copy_param param;
1993 struct copy_result result;
1996 debug_print("imap copy - begin\n");
1998 imap = get_imap(folder);
2003 threaded_run(folder, ¶m, &result, copy_run);
2005 if (result.error != MAILIMAP_NO_ERROR)
2006 return result.error;
2008 debug_print("imap copy - end\n");
2010 return result.error;
2015 struct store_param {
2017 struct mailimap_set * set;
2018 struct mailimap_store_att_flags * store_att_flags;
2021 struct store_result {
2025 static void store_run(struct etpan_thread_op * op)
2027 struct store_param * param;
2028 struct store_result * result;
2033 r = mailimap_uid_store(param->imap, param->set,
2034 param->store_att_flags);
2036 result = op->result;
2039 debug_print("imap store run - end %i\n", r);
2042 int imap_threaded_store(Folder * folder, struct mailimap_set * set,
2043 struct mailimap_store_att_flags * store_att_flags)
2045 struct store_param param;
2046 struct store_result result;
2049 debug_print("imap store - begin\n");
2051 imap = get_imap(folder);
2054 param.store_att_flags = store_att_flags;
2056 threaded_run(folder, ¶m, &result, store_run);
2058 if (result.error != MAILIMAP_NO_ERROR)
2059 return result.error;
2061 debug_print("imap store - end\n");
2063 return result.error;
2068 static void do_exec_command(int fd, const char * command,
2069 const char * servername, uint16_t port)
2074 /* Fork again to become a child of init rather than
2075 the etpan client. */
2080 setenv("ETPANSERVER", servername, 1);
2082 unsetenv("ETPANSERVER");
2087 snprintf(porttext, sizeof(porttext), "%d", port);
2088 setenv("ETPANPORT", porttext, 1);
2091 unsetenv("ETPANPORT");
2094 /* Not a lot we can do if there's an error other than bail. */
2095 if (dup2(fd, 0) == -1)
2097 if (dup2(fd, 1) == -1)
2100 /* Should we close stderr and reopen /dev/null? */
2102 maxopen = sysconf(_SC_OPEN_MAX);
2103 for (i=3; i < maxopen; i++)
2107 /* Detach from the controlling tty if we have one. Otherwise,
2108 SSH might do something stupid like trying to use it instead
2109 of running $SSH_ASKPASS. Doh. */
2110 fd = open("/dev/tty", O_RDONLY);
2112 ioctl(fd, TIOCNOTTY, NULL);
2115 #endif /* TIOCNOTTY */
2117 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
2119 /* Eep. Shouldn't reach this */
2123 static int subcommand_connect(const char *command,
2124 const char *servername, uint16_t port)
2126 /* SEB unsupported on Windows */
2130 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds))
2135 do_exec_command(sockfds[1], command, servername, port);
2137 else if (childpid == -1) {
2145 /* Reap child, leaving grandchild process to run */
2146 waitpid(childpid, NULL, 0);
2151 int socket_connect_cmd(mailimap * imap, const char * command,
2152 const char * server, int port)
2158 fd = subcommand_connect(command, server, port);
2160 return MAILIMAP_ERROR_STREAM;
2162 s = mailstream_socket_open(fd);
2165 return MAILIMAP_ERROR_STREAM;
2168 r = mailimap_connect(imap, s);
2169 if (r != MAILIMAP_NO_ERROR) {
2170 mailstream_close(s);
2174 return MAILIMAP_NO_ERROR;
2179 struct connect_cmd_param {
2181 const char * command;
2182 const char * server;
2186 struct connect_cmd_result {
2190 static void connect_cmd_run(struct etpan_thread_op * op)
2193 struct connect_cmd_param * param;
2194 struct connect_cmd_result * result;
2197 result = op->result;
2199 r = socket_connect_cmd(param->imap, param->command,
2200 param->server, param->port);
2206 int imap_threaded_connect_cmd(Folder * folder, const char * command,
2207 const char * server, int port)
2209 struct connect_cmd_param param;
2210 struct connect_cmd_result result;
2215 imap = mailimap_new(0, NULL);
2218 key.len = sizeof(folder);
2221 chash_set(session_hash, &key, &value, NULL);
2224 param.command = command;
2225 param.server = server;
2228 threaded_run(folder, ¶m, &result, connect_cmd_run);
2230 debug_print("connect_cmd ok %i\n", result.error);
2232 return result.error;
2236 void imap_main_init(void)
2239 void imap_main_done(void)
2242 void imap_main_set_timeout(int sec)