7 #include "imap-thread.h"
16 #include "etpan-thread-manager.h"
18 static struct etpan_thread_manager * thread_manager = NULL;
19 static chash * imap_hash = NULL;
20 static chash * session_hash = NULL;
21 static guint thread_manager_signal = 0;
22 static GIOChannel * io_channel = NULL;
25 static gboolean thread_manager_event(GIOChannel * source,
26 GIOCondition condition,
29 etpan_thread_manager_loop(thread_manager);
35 #define ETPAN_DEFAULT_NETWORK_TIMEOUT 60
37 void imap_main_init(void)
39 int fd_thread_manager;
41 mailstream_network_delay.tv_sec = ETPAN_DEFAULT_NETWORK_TIMEOUT;
42 mailstream_network_delay.tv_usec = 0;
47 imap_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
48 session_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
50 thread_manager = etpan_thread_manager_new();
52 fd_thread_manager = etpan_thread_manager_get_fd(thread_manager);
54 io_channel = g_io_channel_unix_new(fd_thread_manager);
56 thread_manager_signal = g_io_add_watch_full(io_channel, 0, G_IO_IN,
62 void imap_main_set_timeout(int sec)
64 mailstream_network_delay.tv_sec = sec;
65 mailstream_network_delay.tv_usec = 0;
68 void imap_main_done(void)
70 etpan_thread_manager_stop(thread_manager);
71 etpan_thread_manager_join(thread_manager);
73 g_source_remove(thread_manager_signal);
74 g_io_channel_unref(io_channel);
76 etpan_thread_manager_free(thread_manager);
78 chash_free(session_hash);
79 chash_free(imap_hash);
82 void imap_init(Folder * folder)
84 struct etpan_thread * thread;
88 thread = etpan_thread_manager_get_thread(thread_manager);
91 key.len = sizeof(folder);
95 chash_set(imap_hash, &key, &value, NULL);
98 void imap_done(Folder * folder)
100 struct etpan_thread * thread;
106 key.len = sizeof(folder);
108 r = chash_get(imap_hash, &key, &value);
114 etpan_thread_unbind(thread);
116 chash_delete(imap_hash, &key, NULL);
118 debug_print("remove thread");
121 static struct etpan_thread * get_thread(Folder * folder)
123 struct etpan_thread * thread;
128 key.len = sizeof(folder);
130 chash_get(imap_hash, &key, &value);
136 static mailimap * get_imap(Folder * folder)
144 key.len = sizeof(folder);
146 r = chash_get(session_hash, &key, &value);
156 static void generic_cb(int cancelled, void * result, void * callback_data)
160 p_finished = callback_data;
162 debug_print("generic_cb\n");
167 static void threaded_run(Folder * folder, void * param, void * result,
168 void (* func)(struct etpan_thread_op * ))
170 struct etpan_thread_op * op;
171 struct etpan_thread * thread;
174 imap_folder_ref(folder);
176 op = etpan_thread_op_new();
182 op->callback = generic_cb;
183 op->callback_data = &finished;
188 thread = get_thread(folder);
189 etpan_thread_op_schedule(thread, op);
192 gtk_main_iteration();
195 etpan_thread_op_free(op);
197 imap_folder_unref(folder);
203 struct connect_param {
209 struct connect_result {
213 static void connect_run(struct etpan_thread_op * op)
216 struct connect_param * param;
217 struct connect_result * result;
222 r = mailimap_socket_connect(param->imap,
223 param->server, param->port);
229 int imap_threaded_connect(Folder * folder, const char * server, int port)
231 struct connect_param param;
232 struct connect_result result;
237 imap = mailimap_new(0, NULL);
240 key.len = sizeof(folder);
243 chash_set(session_hash, &key, &value, NULL);
246 param.server = server;
249 threaded_run(folder, ¶m, &result, connect_run);
251 debug_print("connect ok %i\n", result.error);
257 static void connect_ssl_run(struct etpan_thread_op * op)
260 struct connect_param * param;
261 struct connect_result * result;
266 r = mailimap_ssl_connect(param->imap,
267 param->server, param->port);
272 int imap_threaded_connect_ssl(Folder * folder, const char * server, int port)
274 struct connect_param param;
275 struct connect_result result;
280 imap = mailimap_new(0, NULL);
283 key.len = sizeof(folder);
286 chash_set(session_hash, &key, &value, NULL);
289 param.server = server;
292 threaded_run(folder, ¶m, &result, connect_ssl_run);
294 debug_print("connect ok\n");
299 struct disconnect_param {
303 struct disconnect_result {
307 static void disconnect_run(struct etpan_thread_op * op)
310 struct disconnect_param * param;
311 struct disconnect_result * result;
316 r = mailimap_logout(param->imap);
321 void imap_threaded_disconnect(Folder * folder)
323 struct connect_param param;
324 struct connect_result result;
329 imap = get_imap(folder);
331 debug_print("was disconnected\n");
337 threaded_run(folder, ¶m, &result, disconnect_run);
340 key.len = sizeof(folder);
343 chash_delete(session_hash, &key, NULL);
347 debug_print("disconnect ok\n");
354 const char * wildcard;
362 static void list_run(struct etpan_thread_op * op)
364 struct list_param * param;
365 struct list_result * result;
371 r = mailimap_list(param->imap, param->base,
372 param->wildcard, &list);
377 debug_print("imap list run - end\n");
380 int imap_threaded_list(Folder * folder, const char * base,
381 const char * wildcard,
384 struct list_param param;
385 struct list_result result;
387 debug_print("imap list - begin\n");
389 param.imap = get_imap(folder);
391 param.wildcard = wildcard;
393 threaded_run(folder, ¶m, &result, list_run);
395 * p_result = result.list;
397 debug_print("imap list - end %p\n", result.list);
407 const char * password;
410 struct login_result {
414 static void login_run(struct etpan_thread_op * op)
416 struct login_param * param;
417 struct login_result * result;
421 r = mailimap_login(param->imap,
422 param->login, param->password);
426 debug_print("imap login run - end %i\n", r);
429 int imap_threaded_login(Folder * folder,
430 const char * login, const char * password)
432 struct login_param param;
433 struct login_result result;
435 debug_print("imap login - begin\n");
437 param.imap = get_imap(folder);
439 param.password = password;
441 threaded_run(folder, ¶m, &result, login_run);
443 debug_print("imap login - end\n");
449 struct status_param {
452 struct mailimap_status_att_list * status_att_list;
455 struct status_result {
457 struct mailimap_mailbox_data_status * data_status;
460 static void status_run(struct etpan_thread_op * op)
462 struct status_param * param;
463 struct status_result * result;
469 r = mailimap_status(param->imap, param->mb,
470 param->status_att_list,
471 &result->data_status);
474 debug_print("imap status run - end %i\n", r);
477 int imap_threaded_status(Folder * folder, const char * mb,
478 struct mailimap_mailbox_data_status ** data_status)
480 struct status_param param;
481 struct status_result result;
482 struct mailimap_status_att_list * status_att_list;
484 debug_print("imap status - begin\n");
486 status_att_list = mailimap_status_att_list_new_empty();
487 mailimap_status_att_list_add(status_att_list,
488 MAILIMAP_STATUS_ATT_MESSAGES);
489 mailimap_status_att_list_add(status_att_list,
490 MAILIMAP_STATUS_ATT_RECENT);
491 mailimap_status_att_list_add(status_att_list,
492 MAILIMAP_STATUS_ATT_UIDNEXT);
493 mailimap_status_att_list_add(status_att_list,
494 MAILIMAP_STATUS_ATT_UIDVALIDITY);
495 mailimap_status_att_list_add(status_att_list,
496 MAILIMAP_STATUS_ATT_UNSEEN);
498 param.imap = get_imap(folder);
500 param.status_att_list = status_att_list;
502 threaded_run(folder, ¶m, &result, status_run);
504 debug_print("imap status - end\n");
506 * data_status = result.data_status;
521 static void noop_run(struct etpan_thread_op * op)
523 struct noop_param * param;
524 struct noop_result * result;
528 r = mailimap_noop(param->imap);
532 debug_print("imap noop run - end %i\n", r);
535 int imap_threaded_noop(Folder * folder, unsigned int * p_exists)
537 struct noop_param param;
538 struct noop_result result;
541 debug_print("imap noop - begin\n");
543 imap = get_imap(folder);
546 threaded_run(folder, ¶m, &result, noop_run);
548 if (imap->imap_selection_info != NULL) {
549 * p_exists = imap->imap_selection_info->sel_exists;
555 debug_print("imap noop - end\n");
561 struct starttls_param {
565 struct starttls_result {
569 static void starttls_run(struct etpan_thread_op * op)
571 struct starttls_param * param;
572 struct starttls_result * result;
576 r = mailimap_starttls(param->imap);
580 debug_print("imap starttls run - end %i\n", r);
583 int imap_threaded_starttls(Folder * folder)
585 struct starttls_param param;
586 struct starttls_result result;
588 debug_print("imap starttls - begin\n");
590 param.imap = get_imap(folder);
592 threaded_run(folder, ¶m, &result, starttls_run);
594 debug_print("imap starttls - end\n");
601 struct create_param {
606 struct create_result {
610 static void create_run(struct etpan_thread_op * op)
612 struct create_param * param;
613 struct create_result * result;
617 r = mailimap_create(param->imap, param->mb);
621 debug_print("imap create run - end %i\n", r);
624 int imap_threaded_create(Folder * folder, const char * mb)
626 struct create_param param;
627 struct create_result result;
629 debug_print("imap create - begin\n");
631 param.imap = get_imap(folder);
634 threaded_run(folder, ¶m, &result, create_run);
636 debug_print("imap create - end\n");
644 struct rename_param {
647 const char * new_name;
650 struct rename_result {
654 static void rename_run(struct etpan_thread_op * op)
656 struct rename_param * param;
657 struct rename_result * result;
661 r = mailimap_rename(param->imap, param->mb, param->new_name);
665 debug_print("imap rename run - end %i\n", r);
668 int imap_threaded_rename(Folder * folder,
669 const char * mb, const char * new_name)
671 struct rename_param param;
672 struct rename_result result;
674 debug_print("imap rename - begin\n");
676 param.imap = get_imap(folder);
678 param.new_name = new_name;
680 threaded_run(folder, ¶m, &result, rename_run);
682 debug_print("imap rename - end\n");
690 struct delete_param {
695 struct delete_result {
699 static void delete_run(struct etpan_thread_op * op)
701 struct delete_param * param;
702 struct delete_result * result;
706 r = mailimap_delete(param->imap, param->mb);
710 debug_print("imap delete run - end %i\n", r);
713 int imap_threaded_delete(Folder * folder, const char * mb)
715 struct delete_param param;
716 struct delete_result result;
718 debug_print("imap delete - begin\n");
720 param.imap = get_imap(folder);
723 threaded_run(folder, ¶m, &result, delete_run);
725 debug_print("imap delete - end\n");
732 struct select_param {
737 struct select_result {
741 static void select_run(struct etpan_thread_op * op)
743 struct select_param * param;
744 struct select_result * result;
748 r = mailimap_select(param->imap, param->mb);
752 debug_print("imap select run - end %i\n", r);
755 int imap_threaded_select(Folder * folder, const char * mb,
756 gint * exists, gint * recent, gint * unseen,
757 guint32 * uid_validity)
759 struct select_param param;
760 struct select_result result;
763 debug_print("imap select - begin\n");
765 imap = get_imap(folder);
769 threaded_run(folder, ¶m, &result, select_run);
771 if (result.error != MAILIMAP_NO_ERROR)
774 if (imap->imap_selection_info == NULL)
775 return MAILIMAP_ERROR_PARSE;
777 * exists = imap->imap_selection_info->sel_exists;
778 * recent = imap->imap_selection_info->sel_recent;
779 * unseen = imap->imap_selection_info->sel_unseen;
780 * uid_validity = imap->imap_selection_info->sel_uidvalidity;
782 debug_print("imap select - end\n");
789 struct examine_param {
794 struct examine_result {
798 static void examine_run(struct etpan_thread_op * op)
800 struct examine_param * param;
801 struct examine_result * result;
805 r = mailimap_examine(param->imap, param->mb);
809 debug_print("imap examine run - end %i\n", r);
812 int imap_threaded_examine(Folder * folder, const char * mb,
813 gint * exists, gint * recent, gint * unseen,
814 guint32 * uid_validity)
816 struct examine_param param;
817 struct examine_result result;
820 debug_print("imap examine - begin\n");
822 imap = get_imap(folder);
826 threaded_run(folder, ¶m, &result, examine_run);
828 if (result.error != MAILIMAP_NO_ERROR)
831 if (imap->imap_selection_info == NULL)
832 return MAILIMAP_ERROR_PARSE;
834 * exists = imap->imap_selection_info->sel_exists;
835 * recent = imap->imap_selection_info->sel_recent;
836 * unseen = imap->imap_selection_info->sel_unseen;
837 * uid_validity = imap->imap_selection_info->sel_uidvalidity;
839 debug_print("imap examine - end\n");
847 struct search_param {
850 struct mailimap_set * set;
853 struct search_result {
855 clist * search_result;
858 static void search_run(struct etpan_thread_op * op)
860 struct search_param * param;
861 struct search_result * result;
863 struct mailimap_search_key * key;
864 struct mailimap_search_key * uid_key;
865 struct mailimap_search_key * search_type_key;
866 clist * search_result;
870 uid_key = mailimap_search_key_new_uid(param->set);
872 search_type_key = NULL;
873 switch (param->type) {
874 case IMAP_SEARCH_TYPE_SIMPLE:
875 search_type_key = NULL;
878 case IMAP_SEARCH_TYPE_SEEN:
879 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SEEN,
880 NULL, NULL, NULL, NULL, NULL,
881 NULL, NULL, NULL, NULL, NULL,
882 NULL, NULL, NULL, NULL, 0,
883 NULL, NULL, NULL, NULL, NULL,
884 NULL, 0, NULL, NULL, NULL);
887 case IMAP_SEARCH_TYPE_UNSEEN:
888 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN,
889 NULL, NULL, NULL, NULL, NULL,
890 NULL, NULL, NULL, NULL, NULL,
891 NULL, NULL, NULL, NULL, 0,
892 NULL, NULL, NULL, NULL, NULL,
893 NULL, 0, NULL, NULL, NULL);
896 case IMAP_SEARCH_TYPE_ANSWERED:
897 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ANSWERED,
898 NULL, NULL, NULL, NULL, NULL,
899 NULL, NULL, NULL, NULL, NULL,
900 NULL, NULL, NULL, NULL, 0,
901 NULL, NULL, NULL, NULL, NULL,
902 NULL, 0, NULL, NULL, NULL);
905 case IMAP_SEARCH_TYPE_FLAGGED:
906 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FLAGGED,
907 NULL, NULL, NULL, NULL, NULL,
908 NULL, NULL, NULL, NULL, NULL,
909 NULL, NULL, NULL, NULL, 0,
910 NULL, NULL, NULL, NULL, NULL,
911 NULL, 0, NULL, NULL, NULL);
915 if (search_type_key != NULL) {
916 key = mailimap_search_key_new_multiple_empty();
917 mailimap_search_key_multiple_add(key, search_type_key);
918 mailimap_search_key_multiple_add(key, uid_key);
924 r = mailimap_uid_search(param->imap, NULL, key, &search_result);
928 result->search_result = search_result;
929 debug_print("imap search run - end %i\n", r);
932 int imap_threaded_search(Folder * folder, int search_type,
933 struct mailimap_set * set, clist ** search_result)
935 struct search_param param;
936 struct search_result result;
939 debug_print("imap search - begin\n");
941 imap = get_imap(folder);
944 param.type = search_type;
946 threaded_run(folder, ¶m, &result, search_run);
948 if (result.error != MAILIMAP_NO_ERROR)
951 debug_print("imap search - end\n");
953 * search_result = result.search_result;
962 uid_list_to_env_list(clist * fetch_result, carray ** result)
970 tab = carray_new(128);
972 res = MAILIMAP_ERROR_MEMORY;
976 for(cur = clist_begin(fetch_result) ; cur != NULL ;
977 cur = clist_next(cur)) {
978 struct mailimap_msg_att * msg_att;
979 clistiter * item_cur;
984 msg_att = clist_content(cur);
988 for(item_cur = clist_begin(msg_att->att_list) ;
990 item_cur = clist_next(item_cur)) {
991 struct mailimap_msg_att_item * item;
993 item = clist_content(item_cur);
995 switch (item->att_type) {
996 case MAILIMAP_MSG_ATT_ITEM_STATIC:
997 switch (item->att_data.att_static->att_type) {
998 case MAILIMAP_MSG_ATT_UID:
999 uid = item->att_data.att_static->att_data.att_uid;
1005 puid = malloc(sizeof(* puid));
1007 res = MAILIMAP_ERROR_MEMORY;
1012 r = carray_add(tab, puid, NULL);
1015 res = MAILIMAP_ERROR_MEMORY;
1022 return MAILIMAP_NO_ERROR;
1025 for(i = 0 ; i < carray_count(tab) ; i++)
1026 mailmessage_free(carray_get(tab, i));
1031 static int imap_get_messages_list(mailimap * imap,
1032 uint32_t first_index,
1037 struct mailimap_fetch_att * fetch_att;
1038 struct mailimap_fetch_type * fetch_type;
1039 struct mailimap_set * set;
1040 clist * fetch_result;
1043 set = mailimap_set_new_interval(first_index, 0);
1045 res = MAILIMAP_ERROR_MEMORY;
1049 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
1050 if (fetch_type == NULL) {
1051 res = MAILIMAP_ERROR_MEMORY;
1055 fetch_att = mailimap_fetch_att_new_uid();
1056 if (fetch_att == NULL) {
1057 res = MAILIMAP_ERROR_MEMORY;
1058 goto free_fetch_type;
1061 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1062 if (r != MAILIMAP_NO_ERROR) {
1063 mailimap_fetch_att_free(fetch_att);
1064 res = MAILIMAP_ERROR_MEMORY;
1065 goto free_fetch_type;
1068 r = mailimap_uid_fetch(imap, set,
1069 fetch_type, &fetch_result);
1071 mailimap_fetch_type_free(fetch_type);
1072 mailimap_set_free(set);
1074 if (r != MAILIMAP_NO_ERROR) {
1080 r = uid_list_to_env_list(fetch_result, &env_list);
1081 mailimap_fetch_list_free(fetch_result);
1083 * result = env_list;
1085 return MAILIMAP_NO_ERROR;
1088 mailimap_fetch_type_free(fetch_type);
1090 mailimap_set_free(set);
1098 struct fetch_uid_param {
1100 uint32_t first_index;
1103 struct fetch_uid_result {
1105 carray * fetch_result;
1108 static void fetch_uid_run(struct etpan_thread_op * op)
1110 struct fetch_uid_param * param;
1111 struct fetch_uid_result * result;
1112 carray * fetch_result;
1117 r = imap_get_messages_list(param->imap, param->first_index,
1120 result = op->result;
1122 result->fetch_result = fetch_result;
1123 debug_print("imap fetch_uid run - end %i\n", r);
1126 int imap_threaded_fetch_uid(Folder * folder, uint32_t first_index,
1127 carray ** fetch_result)
1129 struct fetch_uid_param param;
1130 struct fetch_uid_result result;
1133 debug_print("imap fetch_uid - begin\n");
1135 imap = get_imap(folder);
1137 param.first_index = first_index;
1139 threaded_run(folder, ¶m, &result, fetch_uid_run);
1141 if (result.error != MAILIMAP_NO_ERROR)
1142 return result.error;
1144 debug_print("imap fetch_uid - end\n");
1146 * fetch_result = result.fetch_result;
1148 return result.error;
1152 void imap_fetch_uid_list_free(carray * uid_list)
1156 for(i = 0 ; i < carray_count(uid_list) ; i ++) {
1159 puid = carray_get(uid_list, i);
1162 carray_free(uid_list);
1167 static int imap_fetch(mailimap * imap,
1170 size_t * result_len)
1173 struct mailimap_set * set;
1174 struct mailimap_fetch_att * fetch_att;
1175 struct mailimap_fetch_type * fetch_type;
1176 clist * fetch_result;
1177 struct mailimap_msg_att * msg_att;
1178 struct mailimap_msg_att_item * msg_att_item;
1183 struct mailimap_section * section;
1185 set = mailimap_set_new_single(msg_index);
1187 res = MAILIMAP_ERROR_MEMORY;
1191 section = mailimap_section_new(NULL);
1192 if (section == NULL) {
1193 res = MAILIMAP_ERROR_MEMORY;
1197 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1198 if (fetch_att == NULL) {
1199 mailimap_section_free(section);
1200 res = MAILIMAP_ERROR_MEMORY;
1204 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1205 if (fetch_type == NULL) {
1206 res = MAILIMAP_ERROR_MEMORY;
1207 goto free_fetch_att;
1210 r = mailimap_uid_fetch(imap, set,
1211 fetch_type, &fetch_result);
1213 mailimap_fetch_type_free(fetch_type);
1214 mailimap_set_free(set);
1217 case MAILIMAP_NO_ERROR:
1223 if (clist_begin(fetch_result) == NULL) {
1224 mailimap_fetch_list_free(fetch_result);
1225 return MAILIMAP_ERROR_FETCH;
1228 msg_att = clist_begin(fetch_result)->data;
1233 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
1234 cur = clist_next(cur)) {
1235 msg_att_item = clist_content(cur);
1237 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
1238 if (msg_att_item->att_data.att_static->att_type ==
1239 MAILIMAP_MSG_ATT_BODY_SECTION) {
1240 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
1242 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
1244 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
1249 mailimap_fetch_list_free(fetch_result);
1252 return MAILIMAP_ERROR_FETCH;
1255 * result_len = text_length;
1257 return MAILIMAP_NO_ERROR;
1260 mailimap_fetch_att_free(fetch_att);
1262 mailimap_set_free(set);
1267 static int imap_fetch_header(mailimap * imap,
1270 size_t * result_len)
1273 struct mailimap_set * set;
1274 struct mailimap_fetch_att * fetch_att;
1275 struct mailimap_fetch_type * fetch_type;
1276 clist * fetch_result;
1277 struct mailimap_msg_att * msg_att;
1278 struct mailimap_msg_att_item * msg_att_item;
1283 struct mailimap_section * section;
1285 set = mailimap_set_new_single(msg_index);
1287 res = MAILIMAP_ERROR_MEMORY;
1291 section = mailimap_section_new_header();
1292 if (section == NULL) {
1293 res = MAILIMAP_ERROR_MEMORY;
1297 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1298 if (fetch_att == NULL) {
1299 mailimap_section_free(section);
1300 res = MAILIMAP_ERROR_MEMORY;
1304 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1305 if (fetch_type == NULL) {
1306 res = MAILIMAP_ERROR_MEMORY;
1307 goto free_fetch_att;
1310 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
1312 mailimap_fetch_type_free(fetch_type);
1313 mailimap_set_free(set);
1316 case MAILIMAP_NO_ERROR:
1322 if (clist_begin(fetch_result) == NULL) {
1323 mailimap_fetch_list_free(fetch_result);
1324 return MAILIMAP_ERROR_FETCH;
1327 msg_att = clist_begin(fetch_result)->data;
1332 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
1333 cur = clist_next(cur)) {
1334 msg_att_item = clist_content(cur);
1336 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
1337 if (msg_att_item->att_data.att_static->att_type ==
1338 MAILIMAP_MSG_ATT_BODY_SECTION) {
1339 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
1340 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
1342 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
1347 mailimap_fetch_list_free(fetch_result);
1350 return MAILIMAP_ERROR_FETCH;
1353 * result_len = text_length;
1355 return MAILIMAP_NO_ERROR;
1358 mailimap_fetch_att_free(fetch_att);
1360 mailimap_set_free(set);
1367 struct fetch_content_param {
1370 const char * filename;
1374 struct fetch_content_result {
1378 static void fetch_content_run(struct etpan_thread_op * op)
1380 struct fetch_content_param * param;
1381 struct fetch_content_result * result;
1383 size_t content_size;
1392 if (param->with_body)
1393 r = imap_fetch(param->imap, param->msg_index,
1394 &content, &content_size);
1396 r = imap_fetch_header(param->imap, param->msg_index,
1397 &content, &content_size);
1399 result = op->result;
1402 if (r == MAILIMAP_NO_ERROR) {
1403 fd = open(param->filename, O_RDWR | O_CREAT, 0600);
1405 result->error = MAILIMAP_ERROR_FETCH;
1409 f = fdopen(fd, "wb");
1411 result->error = MAILIMAP_ERROR_FETCH;
1415 r = fwrite(content, 1, content_size, f);
1422 unlink(param->filename);
1433 unlink(param->filename);
1436 if (mmap_string_unref(content) != 0)
1440 debug_print("imap fetch_content run - end %i\n", r);
1443 int imap_threaded_fetch_content(Folder * folder, uint32_t msg_index,
1445 const char * filename)
1447 struct fetch_content_param param;
1448 struct fetch_content_result result;
1451 debug_print("imap fetch_content - begin\n");
1453 imap = get_imap(folder);
1455 param.msg_index = msg_index;
1456 param.filename = filename;
1457 param.with_body = with_body;
1459 threaded_run(folder, ¶m, &result, fetch_content_run);
1461 if (result.error != MAILIMAP_NO_ERROR)
1462 return result.error;
1464 debug_print("imap fetch_content - end\n");
1466 return result.error;
1471 static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn)
1479 flag_list = att_dyn->att_list;
1480 if (flag_list == NULL)
1483 for(cur = clist_begin(flag_list) ; cur != NULL ;
1484 cur = clist_next(cur)) {
1485 struct mailimap_flag_fetch * flag_fetch;
1487 flag_fetch = clist_content(cur);
1488 if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT)
1491 switch (flag_fetch->fl_flag->fl_type) {
1492 case MAILIMAP_FLAG_ANSWERED:
1493 flags |= MSG_REPLIED;
1495 case MAILIMAP_FLAG_FLAGGED:
1496 flags |= MSG_MARKED;
1498 case MAILIMAP_FLAG_DELETED:
1499 flags |= MSG_DELETED;
1501 case MAILIMAP_FLAG_SEEN:
1502 flags &= ~MSG_UNREAD;
1512 static int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
1516 struct mailimap_msg_att_dynamic ** patt_dyn)
1518 clistiter * item_cur;
1522 struct mailimap_msg_att_dynamic * att_dyn;
1529 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
1530 item_cur = clist_next(item_cur)) {
1531 struct mailimap_msg_att_item * item;
1533 item = clist_content(item_cur);
1535 switch (item->att_type) {
1536 case MAILIMAP_MSG_ATT_ITEM_STATIC:
1537 switch (item->att_data.att_static->att_type) {
1538 case MAILIMAP_MSG_ATT_UID:
1539 uid = item->att_data.att_static->att_data.att_uid;
1542 case MAILIMAP_MSG_ATT_BODY_SECTION:
1543 if (headers == NULL) {
1544 headers = item->att_data.att_static->att_data.att_body_section->sec_body_part;
1547 case MAILIMAP_MSG_ATT_RFC822_SIZE:
1548 ref_size = item->att_data.att_static->att_data.att_rfc822_size;
1553 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
1554 if (att_dyn == NULL) {
1555 att_dyn = item->att_data.att_dyn;
1563 if (pheaders != NULL)
1564 * pheaders = headers;
1565 if (pref_size != NULL)
1566 * pref_size = ref_size;
1567 if (patt_dyn != NULL)
1568 * patt_dyn = att_dyn;
1570 return MAIL_NO_ERROR;
1573 static struct imap_fetch_env_info *
1574 fetch_to_env_info(struct mailimap_msg_att * msg_att)
1576 struct imap_fetch_env_info * info;
1580 struct mailimap_msg_att_dynamic * att_dyn;
1582 imap_get_msg_att_info(msg_att, &uid, &headers, &size,
1585 info = malloc(sizeof(* info));
1587 info->headers = strdup(headers);
1589 info->flags = imap_flags_to_flags(att_dyn);
1595 imap_fetch_result_to_envelop_list(clist * fetch_result,
1596 carray ** p_env_list)
1604 env_list = carray_new(16);
1606 for(cur = clist_begin(fetch_result) ; cur != NULL ;
1607 cur = clist_next(cur)) {
1608 struct mailimap_msg_att * msg_att;
1609 struct imap_fetch_env_info * env_info;
1611 msg_att = clist_content(cur);
1613 env_info = fetch_to_env_info(msg_att);
1614 carray_add(env_list, env_info, NULL);
1617 * p_env_list = env_list;
1619 return MAIL_NO_ERROR;
1622 int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type)
1624 struct mailimap_fetch_att * fetch_att;
1628 struct mailimap_header_list * imap_hdrlist;
1629 struct mailimap_section * section;
1631 hdrlist = clist_new();
1633 header = strdup("Date");
1634 r = clist_append(hdrlist, header);
1635 header = strdup("From");
1636 r = clist_append(hdrlist, header);
1637 header = strdup("To");
1638 r = clist_append(hdrlist, header);
1639 header = strdup("Cc");
1640 r = clist_append(hdrlist, header);
1641 header = strdup("Subject");
1642 r = clist_append(hdrlist, header);
1643 header = strdup("Message-ID");
1644 r = clist_append(hdrlist, header);
1645 header = strdup("References");
1646 r = clist_append(hdrlist, header);
1647 header = strdup("In-Reply-To");
1648 r = clist_append(hdrlist, header);
1650 imap_hdrlist = mailimap_header_list_new(hdrlist);
1651 section = mailimap_section_new_header_fields(imap_hdrlist);
1652 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1653 mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1655 return MAIL_NO_ERROR;
1659 imap_get_envelopes_list(mailimap * imap, struct mailimap_set * set,
1660 carray ** p_env_list)
1662 struct mailimap_fetch_att * fetch_att;
1663 struct mailimap_fetch_type * fetch_type;
1665 clist * fetch_result;
1669 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
1672 fetch_att = mailimap_fetch_att_new_uid();
1673 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1676 fetch_att = mailimap_fetch_att_new_flags();
1677 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1680 fetch_att = mailimap_fetch_att_new_rfc822_size();
1681 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1684 r = imap_add_envelope_fetch_att(fetch_type);
1686 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
1689 case MAILIMAP_NO_ERROR:
1692 mailimap_fetch_type_free(fetch_type);
1696 if (clist_begin(fetch_result) == NULL) {
1697 res = MAILIMAP_ERROR_FETCH;
1701 r = imap_fetch_result_to_envelop_list(fetch_result, &env_list);
1702 mailimap_fetch_list_free(fetch_result);
1704 if (r != MAILIMAP_NO_ERROR) {
1705 mailimap_fetch_type_free(fetch_type);
1706 res = MAILIMAP_ERROR_MEMORY;
1710 mailimap_fetch_type_free(fetch_type);
1712 * p_env_list = env_list;
1714 return MAILIMAP_NO_ERROR;
1720 struct fetch_env_param {
1722 struct mailimap_set * set;
1725 struct fetch_env_result {
1726 carray * fetch_env_result;
1730 static void fetch_env_run(struct etpan_thread_op * op)
1732 struct fetch_env_param * param;
1733 struct fetch_env_result * result;
1739 r = imap_get_envelopes_list(param->imap, param->set,
1742 result = op->result;
1744 result->fetch_env_result = env_list;
1746 debug_print("imap fetch_env run - end %i\n", r);
1749 int imap_threaded_fetch_env(Folder * folder, struct mailimap_set * set,
1750 carray ** p_env_list)
1752 struct fetch_env_param param;
1753 struct fetch_env_result result;
1756 debug_print("imap fetch_env - begin\n");
1758 imap = get_imap(folder);
1762 threaded_run(folder, ¶m, &result, fetch_env_run);
1764 if (result.error != MAILIMAP_NO_ERROR)
1765 return result.error;
1767 debug_print("imap fetch_env - end\n");
1769 * p_env_list = result.fetch_env_result;
1771 return result.error;
1774 void imap_fetch_env_free(carray * env_list)
1778 for(i = 0 ; i < carray_count(env_list) ; i ++) {
1779 struct imap_fetch_env_info * env_info;
1781 env_info = carray_get(env_list, i);
1782 free(env_info->headers);
1785 carray_free(env_list);
1792 struct append_param {
1794 const char * mailbox;
1795 const char * filename;
1796 struct mailimap_flag_list * flag_list;
1799 struct append_result {
1803 static void append_run(struct etpan_thread_op * op)
1805 struct append_param * param;
1806 struct append_result * result;
1810 struct stat stat_buf;
1814 result = op->result;
1816 r = stat(param->filename, &stat_buf);
1818 result->error = MAILIMAP_ERROR_APPEND;
1821 size = stat_buf.st_size;
1823 fd = open(param->filename, O_RDONLY);
1825 result->error = MAILIMAP_ERROR_APPEND;
1829 data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
1830 if (data == (void *) MAP_FAILED) {
1832 result->error = MAILIMAP_ERROR_APPEND;
1836 r = mailimap_append(param->imap, param->mailbox,
1837 param->flag_list, NULL,
1845 debug_print("imap append run - end %i\n", r);
1848 int imap_threaded_append(Folder * folder, const char * mailbox,
1849 const char * filename,
1850 struct mailimap_flag_list * flag_list)
1852 struct append_param param;
1853 struct append_result result;
1856 debug_print("imap append - begin\n");
1858 imap = get_imap(folder);
1860 param.mailbox = mailbox;
1861 param.filename = filename;
1862 param.flag_list = flag_list;
1864 threaded_run(folder, ¶m, &result, append_run);
1866 if (result.error != MAILIMAP_NO_ERROR)
1867 return result.error;
1869 debug_print("imap append - end\n");
1871 return result.error;
1877 struct expunge_param {
1881 struct expunge_result {
1885 static void expunge_run(struct etpan_thread_op * op)
1887 struct expunge_param * param;
1888 struct expunge_result * result;
1892 r = mailimap_expunge(param->imap);
1894 result = op->result;
1896 debug_print("imap expunge run - end %i\n", r);
1899 int imap_threaded_expunge(Folder * folder)
1901 struct expunge_param param;
1902 struct expunge_result result;
1904 debug_print("imap expunge - begin\n");
1906 param.imap = get_imap(folder);
1908 threaded_run(folder, ¶m, &result, expunge_run);
1910 debug_print("imap expunge - end\n");
1912 return result.error;
1918 struct mailimap_set * set;
1922 struct copy_result {
1926 static void copy_run(struct etpan_thread_op * op)
1928 struct copy_param * param;
1929 struct copy_result * result;
1934 r = mailimap_uid_copy(param->imap, param->set, param->mb);
1936 result = op->result;
1939 debug_print("imap copy run - end %i\n", r);
1942 int imap_threaded_copy(Folder * folder, struct mailimap_set * set,
1945 struct copy_param param;
1946 struct copy_result result;
1949 debug_print("imap copy - begin\n");
1951 imap = get_imap(folder);
1956 threaded_run(folder, ¶m, &result, copy_run);
1958 if (result.error != MAILIMAP_NO_ERROR)
1959 return result.error;
1961 debug_print("imap copy - end\n");
1963 return result.error;
1968 struct store_param {
1970 struct mailimap_set * set;
1971 struct mailimap_store_att_flags * store_att_flags;
1974 struct store_result {
1978 static void store_run(struct etpan_thread_op * op)
1980 struct store_param * param;
1981 struct store_result * result;
1986 r = mailimap_uid_store(param->imap, param->set,
1987 param->store_att_flags);
1989 result = op->result;
1992 debug_print("imap store run - end %i\n", r);
1995 int imap_threaded_store(Folder * folder, struct mailimap_set * set,
1996 struct mailimap_store_att_flags * store_att_flags)
1998 struct store_param param;
1999 struct store_result result;
2002 debug_print("imap store - begin\n");
2004 imap = get_imap(folder);
2007 param.store_att_flags = store_att_flags;
2009 threaded_run(folder, ¶m, &result, store_run);
2011 if (result.error != MAILIMAP_NO_ERROR)
2012 return result.error;
2014 debug_print("imap store - end\n");
2016 return result.error;
2021 static void do_exec_command(int fd, const char * command,
2022 const char * servername, uint16_t port)
2027 /* Fork again to become a child of init rather than
2028 the etpan client. */
2033 setenv("ETPANSERVER", servername, 1);
2035 unsetenv("ETPANSERVER");
2040 snprintf(porttext, sizeof(porttext), "%d", port);
2041 setenv("ETPANPORT", porttext, 1);
2044 unsetenv("ETPANPORT");
2047 /* Not a lot we can do if there's an error other than bail. */
2048 if (dup2(fd, 0) == -1)
2050 if (dup2(fd, 1) == -1)
2053 /* Should we close stderr and reopen /dev/null? */
2055 maxopen = sysconf(_SC_OPEN_MAX);
2056 for (i=3; i < maxopen; i++)
2060 /* Detach from the controlling tty if we have one. Otherwise,
2061 SSH might do something stupid like trying to use it instead
2062 of running $SSH_ASKPASS. Doh. */
2063 fd = open("/dev/tty", O_RDONLY);
2065 ioctl(fd, TIOCNOTTY, NULL);
2068 #endif /* TIOCNOTTY */
2070 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
2072 /* Eep. Shouldn't reach this */
2076 static int subcommand_connect(const char *command,
2077 const char *servername, uint16_t port)
2079 /* SEB unsupported on Windows */
2083 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds))
2088 do_exec_command(sockfds[1], command, servername, port);
2090 else if (childpid == -1) {
2098 /* Reap child, leaving grandchild process to run */
2099 waitpid(childpid, NULL, 0);
2104 int socket_connect_cmd(mailimap * imap, const char * command,
2105 const char * server, int port)
2111 fd = subcommand_connect(command, server, port);
2113 return MAILIMAP_ERROR_STREAM;
2115 s = mailstream_socket_open(fd);
2118 return MAILIMAP_ERROR_STREAM;
2121 r = mailimap_connect(imap, s);
2122 if (r != MAILIMAP_NO_ERROR) {
2123 mailstream_close(s);
2127 return MAILIMAP_NO_ERROR;
2132 struct connect_cmd_param {
2134 const char * command;
2135 const char * server;
2139 struct connect_cmd_result {
2143 static void connect_cmd_run(struct etpan_thread_op * op)
2146 struct connect_cmd_param * param;
2147 struct connect_cmd_result * result;
2150 result = op->result;
2152 r = socket_connect_cmd(param->imap, param->command,
2153 param->server, param->port);
2159 int imap_threaded_connect_cmd(Folder * folder, const char * command,
2160 const char * server, int port)
2162 struct connect_cmd_param param;
2163 struct connect_cmd_result result;
2168 imap = mailimap_new(0, NULL);
2171 key.len = sizeof(folder);
2174 chash_set(session_hash, &key, &value, NULL);
2177 param.command = command;
2178 param.server = server;
2181 threaded_run(folder, ¶m, &result, connect_cmd_run);
2183 debug_print("connect_cmd ok %i\n", result.error);
2185 return result.error;
2189 void imap_main_init(void)
2192 void imap_main_done(void)
2195 void imap_main_set_timeout(int sec)