7 #include "imap-thread.h"
11 #if (defined(__DragonFly__) || defined (__NetBSD__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__CYGWIN__))
12 #include <sys/socket.h>
20 #include "etpan-thread-manager.h"
22 #include "ssl_certificate.h"
25 #define DISABLE_LOG_DURING_LOGIN
27 static struct etpan_thread_manager * thread_manager = NULL;
28 static chash * courier_workaround_hash = NULL;
29 static chash * imap_hash = NULL;
30 static chash * session_hash = NULL;
31 static guint thread_manager_signal = 0;
32 static GIOChannel * io_channel = NULL;
35 static gboolean thread_manager_event(GIOChannel * source,
36 GIOCondition condition,
39 etpan_thread_manager_loop(thread_manager);
44 static void imap_logger_cmd(int direction, const char * str, size_t size)
51 memset(buf, 0, size+1);
52 strncpy(buf, str, size);
55 if (!strncmp(buf, "<<<<<<<", 7)
56 || !strncmp(buf, ">>>>>>>", 7)) {
60 while (strstr(buf, "\r"))
61 *strstr(buf, "\r") = ' ';
62 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
63 buf[strlen(buf)-1] = '\0';
65 lines = g_strsplit(buf, "\n", -1);
67 while (lines[i] && *lines[i]) {
68 log_print("IMAP4%c %s\n", direction?'>':'<', lines[i]);
75 static void imap_logger_fetch(int direction, const char * str, size_t size)
82 memset(buf, 0, size+1);
83 strncpy(buf, str, size);
85 if (!strncmp(buf, "<<<<<<<", 7)
86 || !strncmp(buf, ">>>>>>>", 7)) {
90 while (strstr(buf, "\r"))
91 *strstr(buf, "\r") = ' ';
92 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
93 buf[strlen(buf)-1] = '\0';
95 lines = g_strsplit(buf, "\n", -1);
97 if (direction != 0 || (buf[0] == '*' && buf[1] == ' ') || size < 32) {
98 while (lines[i] && *lines[i]) {
99 log_print("IMAP4%c %s\n", direction?'>':'<', lines[i]);
103 log_print("IMAP4%c [data - %zd bytes]\n", direction?'>':'<', size);
109 static void imap_logger_uid(int direction, const char * str, size_t size)
115 buf = malloc(size+1);
116 memset(buf, 0, size+1);
117 strncpy(buf, str, size);
119 if (!strncmp(buf, "<<<<<<<", 7)
120 || !strncmp(buf, ">>>>>>>", 7)) {
124 while (strstr(buf, "\r"))
125 *strstr(buf, "\r") = ' ';
126 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
127 buf[strlen(buf)-1] = '\0';
129 lines = g_strsplit(buf, "\n", -1);
131 while (lines[i] && *lines[i]) {
132 int llen = strlen(lines[i]);
134 log_print("IMAP4%c %s\n", direction?'>':'<', lines[i]);
137 strncpy2(tmp, lines[i], 63);
138 log_print("IMAP4%c %s[... - %zd bytes more]\n", direction?'>':'<', tmp,
147 void imap_logger_append(int direction, const char * str, size_t size)
153 buf = malloc(size+1);
154 memset(buf, 0, size+1);
155 strncpy(buf, str, size);
157 if (!strncmp(buf, "<<<<<<<", 7)
158 || !strncmp(buf, ">>>>>>>", 7)) {
162 while (strstr(buf, "\r"))
163 *strstr(buf, "\r") = ' ';
164 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
165 buf[strlen(buf)-1] = '\0';
167 lines = g_strsplit(buf, "\n", -1);
169 if (direction == 0 || (buf[0] == '*' && buf[1] == ' ') || size < 64) {
170 while (lines[i] && *lines[i]) {
171 log_print("IMAP4%c %s\n", direction?'>':'<', lines[i]);
175 log_print("IMAP4%c [data - %zd bytes]\n", direction?'>':'<', size);
181 #define ETPAN_DEFAULT_NETWORK_TIMEOUT 60
182 static gboolean etpan_skip_ssl_cert_check = FALSE;
184 void imap_main_init(gboolean skip_ssl_cert_check)
186 int fd_thread_manager;
188 etpan_skip_ssl_cert_check = skip_ssl_cert_check;
189 mailstream_network_delay.tv_sec = ETPAN_DEFAULT_NETWORK_TIMEOUT;
190 mailstream_network_delay.tv_usec = 0;
192 mailstream_debug = 1;
193 mailstream_logger = imap_logger_cmd;
195 imap_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
196 session_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
197 courier_workaround_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
199 thread_manager = etpan_thread_manager_new();
201 fd_thread_manager = etpan_thread_manager_get_fd(thread_manager);
203 io_channel = g_io_channel_unix_new(fd_thread_manager);
205 thread_manager_signal = g_io_add_watch_full(io_channel, 0, G_IO_IN,
206 thread_manager_event,
211 void imap_main_set_timeout(int sec)
213 mailstream_network_delay.tv_sec = sec;
214 mailstream_network_delay.tv_usec = 0;
217 void imap_main_done(void)
219 etpan_thread_manager_stop(thread_manager);
220 etpan_thread_manager_join(thread_manager);
222 g_source_remove(thread_manager_signal);
223 g_io_channel_unref(io_channel);
225 etpan_thread_manager_free(thread_manager);
227 chash_free(courier_workaround_hash);
228 chash_free(session_hash);
229 chash_free(imap_hash);
232 void imap_init(Folder * folder)
234 struct etpan_thread * thread;
238 thread = etpan_thread_manager_get_thread(thread_manager);
241 key.len = sizeof(folder);
245 chash_set(imap_hash, &key, &value, NULL);
248 void imap_done(Folder * folder)
250 struct etpan_thread * thread;
256 key.len = sizeof(folder);
258 r = chash_get(imap_hash, &key, &value);
264 etpan_thread_unbind(thread);
266 chash_delete(imap_hash, &key, NULL);
268 debug_print("remove thread");
271 static struct etpan_thread * get_thread(Folder * folder)
273 struct etpan_thread * thread;
278 key.len = sizeof(folder);
280 chash_get(imap_hash, &key, &value);
286 static mailimap * get_imap(Folder * folder)
294 key.len = sizeof(folder);
296 r = chash_get(session_hash, &key, &value);
306 static void generic_cb(int cancelled, void * result, void * callback_data)
310 p_finished = callback_data;
312 debug_print("generic_cb\n");
317 static void threaded_run(Folder * folder, void * param, void * result,
318 void (* func)(struct etpan_thread_op * ))
320 struct etpan_thread_op * op;
321 struct etpan_thread * thread;
324 imap_folder_ref(folder);
326 op = etpan_thread_op_new();
332 op->callback = generic_cb;
333 op->callback_data = &finished;
338 thread = get_thread(folder);
339 etpan_thread_op_schedule(thread, op);
342 gtk_main_iteration();
345 etpan_thread_op_free(op);
347 imap_folder_unref(folder);
353 struct connect_param {
359 struct connect_result {
363 static void connect_run(struct etpan_thread_op * op)
366 struct connect_param * param;
367 struct connect_result * result;
372 r = mailimap_socket_connect(param->imap,
373 param->server, param->port);
379 int imap_threaded_connect(Folder * folder, const char * server, int port)
381 struct connect_param param;
382 struct connect_result result;
387 imap = mailimap_new(0, NULL);
390 key.len = sizeof(folder);
393 chash_set(session_hash, &key, &value, NULL);
396 param.server = server;
400 threaded_run(folder, ¶m, &result, connect_run);
402 debug_print("connect ok %i\n", result.error);
407 static int etpan_certificate_check(const unsigned char *certificate, int len, void *data)
410 struct connect_param *param = (struct connect_param *)data;
413 if (certificate == NULL || len < 0) {
414 g_warning("no cert presented.\n");
417 cert = d2i_X509(NULL, (unsigned char **) &certificate, len);
419 g_warning("can't get cert\n");
421 } else if (ssl_certificate_check(cert, NULL,
422 (gchar *)param->server, (gushort)param->port) == TRUE) {
434 static void connect_ssl_run(struct etpan_thread_op * op)
437 struct connect_param * param;
438 struct connect_result * result;
443 r = mailimap_ssl_connect(param->imap,
444 param->server, param->port);
448 int imap_threaded_connect_ssl(Folder * folder, const char * server, int port)
450 struct connect_param param;
451 struct connect_result result;
455 unsigned char *certificate = NULL;
458 imap = mailimap_new(0, NULL);
461 key.len = sizeof(folder);
464 chash_set(session_hash, &key, &value, NULL);
467 param.server = server;
471 threaded_run(folder, ¶m, &result, connect_ssl_run);
473 if (result.error >= 0 && !etpan_skip_ssl_cert_check) {
474 cert_len = mailstream_ssl_get_certificate(imap->imap_stream, &certificate);
475 if (etpan_certificate_check(certificate, cert_len, ¶m) < 0)
480 debug_print("connect %d\n", result.error);
491 struct mailimap_capability_data *caps;
494 static void capability_run(struct etpan_thread_op * op)
497 struct capa_param * param;
498 struct capa_result * result;
499 struct mailimap_capability_data *caps;
504 r = mailimap_capability(param->imap, &caps);
507 result->caps = (r == 0 ? caps : NULL);
511 struct mailimap_capability_data * imap_threaded_capability(Folder *folder, int *ok)
513 struct capa_param param;
514 struct capa_result result;
517 imap = get_imap(folder);
521 threaded_run(folder, ¶m, &result, capability_run);
523 debug_print("capa %d\n", result.error);
532 struct disconnect_param {
536 struct disconnect_result {
540 static void disconnect_run(struct etpan_thread_op * op)
543 struct disconnect_param * param;
544 struct disconnect_result * result;
549 r = mailimap_logout(param->imap);
554 void imap_threaded_disconnect(Folder * folder)
556 struct connect_param param;
557 struct connect_result result;
562 imap = get_imap(folder);
564 debug_print("was disconnected\n");
570 threaded_run(folder, ¶m, &result, disconnect_run);
573 key.len = sizeof(folder);
576 chash_delete(session_hash, &key, NULL);
579 key.len = sizeof(imap);
580 chash_delete(courier_workaround_hash, &key, NULL);
584 debug_print("disconnect ok\n");
591 const char * wildcard;
599 static void list_run(struct etpan_thread_op * op)
601 struct list_param * param;
602 struct list_result * result;
608 r = mailimap_list(param->imap, param->base,
609 param->wildcard, &list);
614 debug_print("imap list run - end\n");
617 int imap_threaded_list(Folder * folder, const char * base,
618 const char * wildcard,
621 struct list_param param;
622 struct list_result result;
624 debug_print("imap list - begin\n");
626 param.imap = get_imap(folder);
628 param.wildcard = wildcard;
630 threaded_run(folder, ¶m, &result, list_run);
632 * p_result = result.list;
634 debug_print("imap list - end %p\n", result.list);
644 const char * password;
649 struct login_result {
653 static void login_run(struct etpan_thread_op * op)
655 struct login_param * param;
656 struct login_result * result;
658 #ifdef DISABLE_LOG_DURING_LOGIN
664 #ifdef DISABLE_LOG_DURING_LOGIN
665 old_debug = mailstream_debug;
666 mailstream_debug = 0;
668 if (!strcmp(param->type, "LOGIN"))
669 r = mailimap_login(param->imap,
670 param->login, param->password);
671 else if (!strcmp(param->type, "GSSAPI"))
672 r = mailimap_authenticate(param->imap,
673 param->type, param->server, NULL, NULL,
674 param->login, param->login,
675 param->password, NULL);
677 r = mailimap_authenticate(param->imap,
678 param->type, NULL, NULL, NULL,
679 param->login, param->login,
680 param->password, NULL);
681 #ifdef DISABLE_LOG_DURING_LOGIN
682 mailstream_debug = old_debug;
687 debug_print("imap login run - end %i\n", r);
690 int imap_threaded_login(Folder * folder,
691 const char * login, const char * password,
694 struct login_param param;
695 struct login_result result;
697 debug_print("imap login - begin\n");
699 param.imap = get_imap(folder);
701 param.password = password;
703 if (folder && folder->account)
704 param.server = folder->account->recv_server;
708 threaded_run(folder, ¶m, &result, login_run);
710 debug_print("imap login - end\n");
716 struct status_param {
719 struct mailimap_status_att_list * status_att_list;
722 struct status_result {
724 struct mailimap_mailbox_data_status * data_status;
727 static void status_run(struct etpan_thread_op * op)
729 struct status_param * param;
730 struct status_result * result;
736 r = mailimap_status(param->imap, param->mb,
737 param->status_att_list,
738 &result->data_status);
741 debug_print("imap status run - end %i\n", r);
744 int imap_threaded_status(Folder * folder, const char * mb,
745 struct mailimap_mailbox_data_status ** data_status,
748 struct status_param param;
749 struct status_result result;
750 struct mailimap_status_att_list * status_att_list;
752 debug_print("imap status - begin\n");
754 status_att_list = mailimap_status_att_list_new_empty();
756 mailimap_status_att_list_add(status_att_list,
757 MAILIMAP_STATUS_ATT_MESSAGES);
760 mailimap_status_att_list_add(status_att_list,
761 MAILIMAP_STATUS_ATT_RECENT);
764 mailimap_status_att_list_add(status_att_list,
765 MAILIMAP_STATUS_ATT_UIDNEXT);
768 mailimap_status_att_list_add(status_att_list,
769 MAILIMAP_STATUS_ATT_UIDVALIDITY);
772 mailimap_status_att_list_add(status_att_list,
773 MAILIMAP_STATUS_ATT_UNSEEN);
775 param.imap = get_imap(folder);
777 param.status_att_list = status_att_list;
779 threaded_run(folder, ¶m, &result, status_run);
781 debug_print("imap status - end\n");
783 * data_status = result.data_status;
785 mailimap_status_att_list_free(status_att_list);
800 static void noop_run(struct etpan_thread_op * op)
802 struct noop_param * param;
803 struct noop_result * result;
807 r = mailimap_noop(param->imap);
811 debug_print("imap noop run - end %i\n", r);
814 int imap_threaded_noop(Folder * folder, unsigned int * p_exists)
816 struct noop_param param;
817 struct noop_result result;
820 debug_print("imap noop - begin\n");
822 imap = get_imap(folder);
825 threaded_run(folder, ¶m, &result, noop_run);
827 if (imap->imap_selection_info != NULL) {
828 * p_exists = imap->imap_selection_info->sel_exists;
834 debug_print("imap noop - end\n");
840 struct starttls_result {
844 static void starttls_run(struct etpan_thread_op * op)
846 struct connect_param * param;
847 struct starttls_result * result;
851 r = mailimap_starttls(param->imap);
855 debug_print("imap starttls run - end %i\n", r);
858 mailimap *imap = param->imap;
859 mailstream_low *plain_low = NULL;
860 mailstream_low *tls_low = NULL;
863 plain_low = mailstream_get_low(imap->imap_stream);
864 fd = mailstream_low_get_fd(plain_low);
866 debug_print("imap starttls run - can't get fd\n");
867 result->error = MAILIMAP_ERROR_STREAM;
871 tls_low = mailstream_low_tls_open(fd);
872 if (tls_low == NULL) {
873 debug_print("imap starttls run - can't tls_open\n");
874 result->error = MAILIMAP_ERROR_STREAM;
877 mailstream_low_free(plain_low);
878 mailstream_set_low(imap->imap_stream, tls_low);
882 int imap_threaded_starttls(Folder * folder, const gchar *host, int port)
884 struct connect_param param;
885 struct starttls_result result;
887 unsigned char *certificate;
889 debug_print("imap starttls - begin\n");
891 param.imap = get_imap(folder);
895 threaded_run(folder, ¶m, &result, starttls_run);
897 debug_print("imap starttls - end\n");
899 if (result.error == 0 && !etpan_skip_ssl_cert_check) {
900 cert_len = mailstream_ssl_get_certificate(param.imap->imap_stream, &certificate);
901 if (etpan_certificate_check(certificate, cert_len, ¶m) < 0)
902 result.error = MAILIMAP_ERROR_STREAM;
911 struct create_param {
916 struct create_result {
920 static void create_run(struct etpan_thread_op * op)
922 struct create_param * param;
923 struct create_result * result;
927 r = mailimap_create(param->imap, param->mb);
931 debug_print("imap create run - end %i\n", r);
934 int imap_threaded_create(Folder * folder, const char * mb)
936 struct create_param param;
937 struct create_result result;
939 debug_print("imap create - begin\n");
941 param.imap = get_imap(folder);
944 threaded_run(folder, ¶m, &result, create_run);
946 debug_print("imap create - end\n");
954 struct rename_param {
957 const char * new_name;
960 struct rename_result {
964 static void rename_run(struct etpan_thread_op * op)
966 struct rename_param * param;
967 struct rename_result * result;
971 r = mailimap_rename(param->imap, param->mb, param->new_name);
975 debug_print("imap rename run - end %i\n", r);
978 int imap_threaded_rename(Folder * folder,
979 const char * mb, const char * new_name)
981 struct rename_param param;
982 struct rename_result result;
984 debug_print("imap rename - begin\n");
986 param.imap = get_imap(folder);
988 param.new_name = new_name;
990 threaded_run(folder, ¶m, &result, rename_run);
992 debug_print("imap rename - end\n");
1000 struct delete_param {
1005 struct delete_result {
1009 static void delete_run(struct etpan_thread_op * op)
1011 struct delete_param * param;
1012 struct delete_result * result;
1016 r = mailimap_delete(param->imap, param->mb);
1018 result = op->result;
1020 debug_print("imap delete run - end %i\n", r);
1023 int imap_threaded_delete(Folder * folder, const char * mb)
1025 struct delete_param param;
1026 struct delete_result result;
1028 debug_print("imap delete - begin\n");
1030 param.imap = get_imap(folder);
1033 threaded_run(folder, ¶m, &result, delete_run);
1035 debug_print("imap delete - end\n");
1037 return result.error;
1042 struct select_param {
1047 struct select_result {
1051 static void select_run(struct etpan_thread_op * op)
1053 struct select_param * param;
1054 struct select_result * result;
1058 r = mailimap_select(param->imap, param->mb);
1060 result = op->result;
1062 debug_print("imap select run - end %i\n", r);
1065 int imap_threaded_select(Folder * folder, const char * mb,
1066 gint * exists, gint * recent, gint * unseen,
1067 guint32 * uid_validity)
1069 struct select_param param;
1070 struct select_result result;
1073 debug_print("imap select - begin\n");
1075 imap = get_imap(folder);
1079 threaded_run(folder, ¶m, &result, select_run);
1081 if (result.error != MAILIMAP_NO_ERROR)
1082 return result.error;
1084 if (imap->imap_selection_info == NULL)
1085 return MAILIMAP_ERROR_PARSE;
1087 * exists = imap->imap_selection_info->sel_exists;
1088 * recent = imap->imap_selection_info->sel_recent;
1089 * unseen = imap->imap_selection_info->sel_unseen;
1090 * uid_validity = imap->imap_selection_info->sel_uidvalidity;
1092 debug_print("imap select - end\n");
1094 return result.error;
1099 struct examine_param {
1104 struct examine_result {
1108 static void examine_run(struct etpan_thread_op * op)
1110 struct examine_param * param;
1111 struct examine_result * result;
1115 r = mailimap_examine(param->imap, param->mb);
1117 result = op->result;
1119 debug_print("imap examine run - end %i\n", r);
1122 int imap_threaded_examine(Folder * folder, const char * mb,
1123 gint * exists, gint * recent, gint * unseen,
1124 guint32 * uid_validity)
1126 struct examine_param param;
1127 struct examine_result result;
1130 debug_print("imap examine - begin\n");
1132 imap = get_imap(folder);
1136 threaded_run(folder, ¶m, &result, examine_run);
1138 if (result.error != MAILIMAP_NO_ERROR)
1139 return result.error;
1141 if (imap->imap_selection_info == NULL)
1142 return MAILIMAP_ERROR_PARSE;
1144 * exists = imap->imap_selection_info->sel_exists;
1145 * recent = imap->imap_selection_info->sel_recent;
1146 * unseen = imap->imap_selection_info->sel_unseen;
1147 * uid_validity = imap->imap_selection_info->sel_uidvalidity;
1149 debug_print("imap examine - end\n");
1151 return result.error;
1157 struct search_param {
1160 struct mailimap_set * set;
1163 struct search_result {
1165 clist * search_result;
1168 static struct mailimap_set_item *sc_mailimap_set_item_copy(struct mailimap_set_item *orig)
1170 return mailimap_set_item_new(orig->set_first, orig->set_last);
1173 static struct mailimap_set *sc_mailimap_set_copy(struct mailimap_set *orig)
1175 clist *list = orig ? orig->set_list : NULL;
1176 clist *newlist = clist_new();
1181 for (cur = clist_begin(list); cur; cur = clist_next(cur))
1182 clist_append(newlist,
1183 sc_mailimap_set_item_copy(
1184 (struct mailimap_set_item *)clist_content(cur)));
1185 return mailimap_set_new(newlist);
1188 static void search_run(struct etpan_thread_op * op)
1190 struct search_param * param;
1191 struct search_result * result;
1193 struct mailimap_search_key * key = NULL;
1194 struct mailimap_search_key * uid_key = NULL;
1195 struct mailimap_search_key * search_type_key;
1196 clist * search_result;
1200 /* we copy the mailimap_set because freeing the key is recursive */
1201 if (param->set != NULL) {
1202 uid_key = mailimap_search_key_new_uid(sc_mailimap_set_copy(param->set));
1203 } else if (param->type == IMAP_SEARCH_TYPE_SIMPLE) {
1204 uid_key = mailimap_search_key_new_all();
1206 search_type_key = NULL;
1207 switch (param->type) {
1208 case IMAP_SEARCH_TYPE_SIMPLE:
1209 search_type_key = NULL;
1212 case IMAP_SEARCH_TYPE_SEEN:
1213 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SEEN,
1214 NULL, NULL, NULL, NULL, NULL,
1215 NULL, NULL, NULL, NULL, NULL,
1216 NULL, NULL, NULL, NULL, 0,
1217 NULL, NULL, NULL, NULL, NULL,
1218 NULL, 0, NULL, NULL, NULL);
1221 case IMAP_SEARCH_TYPE_UNSEEN:
1222 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN,
1223 NULL, NULL, NULL, NULL, NULL,
1224 NULL, NULL, NULL, NULL, NULL,
1225 NULL, NULL, NULL, NULL, 0,
1226 NULL, NULL, NULL, NULL, NULL,
1227 NULL, 0, NULL, NULL, NULL);
1230 case IMAP_SEARCH_TYPE_ANSWERED:
1231 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ANSWERED,
1232 NULL, NULL, NULL, NULL, NULL,
1233 NULL, NULL, NULL, NULL, NULL,
1234 NULL, NULL, NULL, NULL, 0,
1235 NULL, NULL, NULL, NULL, NULL,
1236 NULL, 0, NULL, NULL, NULL);
1239 case IMAP_SEARCH_TYPE_FLAGGED:
1240 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FLAGGED,
1241 NULL, NULL, NULL, NULL, NULL,
1242 NULL, NULL, NULL, NULL, NULL,
1243 NULL, NULL, NULL, NULL, 0,
1244 NULL, NULL, NULL, NULL, NULL,
1245 NULL, 0, NULL, NULL, NULL);
1247 case IMAP_SEARCH_TYPE_DELETED:
1248 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_DELETED,
1249 NULL, NULL, NULL, NULL, NULL,
1250 NULL, NULL, NULL, NULL, NULL,
1251 NULL, NULL, NULL, NULL, 0,
1252 NULL, NULL, NULL, NULL, NULL,
1253 NULL, 0, NULL, NULL, NULL);
1257 if (search_type_key != NULL) {
1258 if (param->set != NULL) {
1259 key = mailimap_search_key_new_multiple_empty();
1260 mailimap_search_key_multiple_add(key, search_type_key);
1261 mailimap_search_key_multiple_add(key, uid_key);
1263 key = search_type_key;
1265 } else if (uid_key != NULL) {
1270 g_warning("no key!");
1271 result = op->result;
1273 result->search_result = NULL;
1275 mailstream_logger = imap_logger_uid;
1277 r = mailimap_uid_search(param->imap, NULL, key, &search_result);
1279 mailstream_logger = imap_logger_cmd;
1281 /* free the key (with the imapset) */
1282 mailimap_search_key_free(key);
1284 result = op->result;
1286 result->search_result = search_result;
1288 debug_print("imap search run - end %i\n", result->error);
1291 int imap_threaded_search(Folder * folder, int search_type,
1292 struct mailimap_set * set, clist ** search_result)
1294 struct search_param param;
1295 struct search_result result;
1298 debug_print("imap search - begin\n");
1300 imap = get_imap(folder);
1303 param.type = search_type;
1305 threaded_run(folder, ¶m, &result, search_run);
1307 if (result.error != MAILIMAP_NO_ERROR)
1308 return result.error;
1310 debug_print("imap search - end\n");
1312 * search_result = result.search_result;
1314 return result.error;
1321 uid_list_to_env_list(clist * fetch_result, carray ** result)
1329 tab = carray_new(128);
1331 res = MAILIMAP_ERROR_MEMORY;
1335 for(cur = clist_begin(fetch_result) ; cur != NULL ;
1336 cur = clist_next(cur)) {
1337 struct mailimap_msg_att * msg_att;
1338 clistiter * item_cur;
1343 msg_att = clist_content(cur);
1347 for(item_cur = clist_begin(msg_att->att_list) ;
1349 item_cur = clist_next(item_cur)) {
1350 struct mailimap_msg_att_item * item;
1352 item = clist_content(item_cur);
1354 switch (item->att_type) {
1355 case MAILIMAP_MSG_ATT_ITEM_STATIC:
1356 switch (item->att_data.att_static->att_type) {
1357 case MAILIMAP_MSG_ATT_UID:
1358 uid = item->att_data.att_static->att_data.att_uid;
1364 puid = malloc(sizeof(* puid));
1366 res = MAILIMAP_ERROR_MEMORY;
1371 r = carray_add(tab, puid, NULL);
1374 res = MAILIMAP_ERROR_MEMORY;
1381 return MAILIMAP_NO_ERROR;
1384 for(i = 0 ; i < carray_count(tab) ; i++)
1385 mailmessage_free(carray_get(tab, i));
1390 static int imap_get_messages_list(mailimap * imap,
1391 uint32_t first_index,
1396 struct mailimap_fetch_att * fetch_att;
1397 struct mailimap_fetch_type * fetch_type;
1398 struct mailimap_set * set;
1399 clist * fetch_result;
1402 set = mailimap_set_new_interval(first_index, 0);
1404 res = MAILIMAP_ERROR_MEMORY;
1408 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
1409 if (fetch_type == NULL) {
1410 res = MAILIMAP_ERROR_MEMORY;
1414 fetch_att = mailimap_fetch_att_new_uid();
1415 if (fetch_att == NULL) {
1416 res = MAILIMAP_ERROR_MEMORY;
1417 goto free_fetch_type;
1420 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1421 if (r != MAILIMAP_NO_ERROR) {
1422 mailimap_fetch_att_free(fetch_att);
1423 res = MAILIMAP_ERROR_MEMORY;
1424 goto free_fetch_type;
1427 r = mailimap_uid_fetch(imap, set,
1428 fetch_type, &fetch_result);
1430 mailimap_fetch_type_free(fetch_type);
1431 mailimap_set_free(set);
1433 if (r != MAILIMAP_NO_ERROR) {
1439 r = uid_list_to_env_list(fetch_result, &env_list);
1440 mailimap_fetch_list_free(fetch_result);
1442 * result = env_list;
1444 return MAILIMAP_NO_ERROR;
1447 mailimap_fetch_type_free(fetch_type);
1449 mailimap_set_free(set);
1457 struct fetch_uid_param {
1459 uint32_t first_index;
1462 struct fetch_uid_result {
1464 carray * fetch_result;
1467 static void fetch_uid_run(struct etpan_thread_op * op)
1469 struct fetch_uid_param * param;
1470 struct fetch_uid_result * result;
1471 carray * fetch_result;
1476 fetch_result = NULL;
1477 r = imap_get_messages_list(param->imap, param->first_index,
1480 result = op->result;
1482 result->fetch_result = fetch_result;
1483 debug_print("imap fetch_uid run - end %i\n", r);
1486 int imap_threaded_fetch_uid(Folder * folder, uint32_t first_index,
1487 carray ** fetch_result)
1489 struct fetch_uid_param param;
1490 struct fetch_uid_result result;
1493 debug_print("imap fetch_uid - begin\n");
1495 imap = get_imap(folder);
1497 param.first_index = first_index;
1499 threaded_run(folder, ¶m, &result, fetch_uid_run);
1501 if (result.error != MAILIMAP_NO_ERROR)
1502 return result.error;
1504 debug_print("imap fetch_uid - end\n");
1506 * fetch_result = result.fetch_result;
1508 return result.error;
1512 void imap_fetch_uid_list_free(carray * uid_list)
1516 for(i = 0 ; i < carray_count(uid_list) ; i ++) {
1519 puid = carray_get(uid_list, i);
1522 carray_free(uid_list);
1527 static int imap_fetch(mailimap * imap,
1530 size_t * result_len)
1533 struct mailimap_set * set;
1534 struct mailimap_fetch_att * fetch_att;
1535 struct mailimap_fetch_type * fetch_type;
1536 clist * fetch_result;
1537 struct mailimap_msg_att * msg_att;
1538 struct mailimap_msg_att_item * msg_att_item;
1543 struct mailimap_section * section;
1545 set = mailimap_set_new_single(msg_index);
1547 res = MAILIMAP_ERROR_MEMORY;
1551 section = mailimap_section_new(NULL);
1552 if (section == NULL) {
1553 res = MAILIMAP_ERROR_MEMORY;
1557 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1558 if (fetch_att == NULL) {
1559 mailimap_section_free(section);
1560 res = MAILIMAP_ERROR_MEMORY;
1564 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1565 if (fetch_type == NULL) {
1566 res = MAILIMAP_ERROR_MEMORY;
1567 goto free_fetch_att;
1570 mailstream_logger = imap_logger_fetch;
1572 r = mailimap_uid_fetch(imap, set,
1573 fetch_type, &fetch_result);
1575 mailstream_logger = imap_logger_cmd;
1577 mailimap_fetch_type_free(fetch_type);
1578 mailimap_set_free(set);
1581 case MAILIMAP_NO_ERROR:
1587 if (clist_begin(fetch_result) == NULL) {
1588 mailimap_fetch_list_free(fetch_result);
1589 return MAILIMAP_ERROR_FETCH;
1592 msg_att = clist_begin(fetch_result)->data;
1597 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
1598 cur = clist_next(cur)) {
1599 msg_att_item = clist_content(cur);
1601 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
1602 if (msg_att_item->att_data.att_static->att_type ==
1603 MAILIMAP_MSG_ATT_BODY_SECTION) {
1604 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
1606 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
1608 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
1613 mailimap_fetch_list_free(fetch_result);
1616 return MAILIMAP_ERROR_FETCH;
1619 * result_len = text_length;
1621 return MAILIMAP_NO_ERROR;
1624 mailimap_fetch_att_free(fetch_att);
1626 mailimap_set_free(set);
1631 static int imap_fetch_header(mailimap * imap,
1634 size_t * result_len)
1637 struct mailimap_set * set;
1638 struct mailimap_fetch_att * fetch_att;
1639 struct mailimap_fetch_type * fetch_type;
1640 clist * fetch_result;
1641 struct mailimap_msg_att * msg_att;
1642 struct mailimap_msg_att_item * msg_att_item;
1647 struct mailimap_section * section;
1649 set = mailimap_set_new_single(msg_index);
1651 res = MAILIMAP_ERROR_MEMORY;
1655 section = mailimap_section_new_header();
1656 if (section == NULL) {
1657 res = MAILIMAP_ERROR_MEMORY;
1661 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
1662 if (fetch_att == NULL) {
1663 mailimap_section_free(section);
1664 res = MAILIMAP_ERROR_MEMORY;
1668 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
1669 if (fetch_type == NULL) {
1670 res = MAILIMAP_ERROR_MEMORY;
1671 goto free_fetch_att;
1674 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
1676 mailimap_fetch_type_free(fetch_type);
1677 mailimap_set_free(set);
1680 case MAILIMAP_NO_ERROR:
1686 if (clist_begin(fetch_result) == NULL) {
1687 mailimap_fetch_list_free(fetch_result);
1688 return MAILIMAP_ERROR_FETCH;
1691 msg_att = clist_begin(fetch_result)->data;
1696 for(cur = clist_begin(msg_att->att_list) ; cur != NULL ;
1697 cur = clist_next(cur)) {
1698 msg_att_item = clist_content(cur);
1700 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
1701 if (msg_att_item->att_data.att_static->att_type ==
1702 MAILIMAP_MSG_ATT_BODY_SECTION) {
1703 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
1704 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
1706 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
1711 mailimap_fetch_list_free(fetch_result);
1714 return MAILIMAP_ERROR_FETCH;
1717 * result_len = text_length;
1719 return MAILIMAP_NO_ERROR;
1722 mailimap_fetch_att_free(fetch_att);
1724 mailimap_set_free(set);
1731 struct fetch_content_param {
1734 const char * filename;
1738 struct fetch_content_result {
1742 static void fetch_content_run(struct etpan_thread_op * op)
1744 struct fetch_content_param * param;
1745 struct fetch_content_result * result;
1747 size_t content_size;
1756 if (param->with_body)
1757 r = imap_fetch(param->imap, param->msg_index,
1758 &content, &content_size);
1760 r = imap_fetch_header(param->imap, param->msg_index,
1761 &content, &content_size);
1763 result = op->result;
1766 if (r == MAILIMAP_NO_ERROR) {
1767 fd = open(param->filename, O_RDWR | O_CREAT, 0600);
1769 result->error = MAILIMAP_ERROR_FETCH;
1773 f = fdopen(fd, "wb");
1775 result->error = MAILIMAP_ERROR_FETCH;
1779 r = fwrite(content, 1, content_size, f);
1786 g_unlink(param->filename);
1797 g_unlink(param->filename);
1800 if (mmap_string_unref(content) != 0)
1804 debug_print("imap fetch_content run - end %i\n", r);
1807 int imap_threaded_fetch_content(Folder * folder, uint32_t msg_index,
1809 const char * filename)
1811 struct fetch_content_param param;
1812 struct fetch_content_result result;
1815 debug_print("imap fetch_content - begin\n");
1817 imap = get_imap(folder);
1819 param.msg_index = msg_index;
1820 param.filename = filename;
1821 param.with_body = with_body;
1823 threaded_run(folder, ¶m, &result, fetch_content_run);
1825 if (result.error != MAILIMAP_NO_ERROR)
1826 return result.error;
1828 debug_print("imap fetch_content - end\n");
1830 return result.error;
1835 static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn)
1843 flag_list = att_dyn->att_list;
1844 if (flag_list == NULL)
1847 for(cur = clist_begin(flag_list) ; cur != NULL ;
1848 cur = clist_next(cur)) {
1849 struct mailimap_flag_fetch * flag_fetch;
1851 flag_fetch = clist_content(cur);
1852 if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT)
1855 switch (flag_fetch->fl_flag->fl_type) {
1856 case MAILIMAP_FLAG_ANSWERED:
1857 flags |= MSG_REPLIED;
1859 case MAILIMAP_FLAG_FLAGGED:
1860 flags |= MSG_MARKED;
1862 case MAILIMAP_FLAG_DELETED:
1863 flags |= MSG_DELETED;
1865 case MAILIMAP_FLAG_SEEN:
1866 flags &= ~MSG_UNREAD;
1876 static int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
1880 struct mailimap_msg_att_dynamic ** patt_dyn)
1882 clistiter * item_cur;
1886 struct mailimap_msg_att_dynamic * att_dyn;
1893 for(item_cur = clist_begin(msg_att->att_list) ; item_cur != NULL ;
1894 item_cur = clist_next(item_cur)) {
1895 struct mailimap_msg_att_item * item;
1897 item = clist_content(item_cur);
1899 switch (item->att_type) {
1900 case MAILIMAP_MSG_ATT_ITEM_STATIC:
1901 switch (item->att_data.att_static->att_type) {
1902 case MAILIMAP_MSG_ATT_UID:
1903 uid = item->att_data.att_static->att_data.att_uid;
1906 case MAILIMAP_MSG_ATT_BODY_SECTION:
1907 if (headers == NULL) {
1908 headers = item->att_data.att_static->att_data.att_body_section->sec_body_part;
1911 case MAILIMAP_MSG_ATT_RFC822_SIZE:
1912 ref_size = item->att_data.att_static->att_data.att_rfc822_size;
1917 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
1918 if (att_dyn == NULL) {
1919 att_dyn = item->att_data.att_dyn;
1927 if (pheaders != NULL)
1928 * pheaders = headers;
1929 if (pref_size != NULL)
1930 * pref_size = ref_size;
1931 if (patt_dyn != NULL)
1932 * patt_dyn = att_dyn;
1934 return MAIL_NO_ERROR;
1937 static struct imap_fetch_env_info *
1938 fetch_to_env_info(struct mailimap_msg_att * msg_att)
1940 struct imap_fetch_env_info * info;
1944 struct mailimap_msg_att_dynamic * att_dyn;
1946 imap_get_msg_att_info(msg_att, &uid, &headers, &size,
1951 info = malloc(sizeof(* info));
1953 info->headers = strdup(headers);
1955 info->flags = imap_flags_to_flags(att_dyn);
1961 imap_fetch_result_to_envelop_list(clist * fetch_result,
1962 carray ** p_env_list)
1969 env_list = carray_new(16);
1971 for(cur = clist_begin(fetch_result) ; cur != NULL ;
1972 cur = clist_next(cur)) {
1973 struct mailimap_msg_att * msg_att;
1974 struct imap_fetch_env_info * env_info;
1976 msg_att = clist_content(cur);
1978 env_info = fetch_to_env_info(msg_att);
1980 return MAILIMAP_ERROR_MEMORY;
1981 carray_add(env_list, env_info, NULL);
1984 * p_env_list = env_list;
1986 return MAIL_NO_ERROR;
1989 int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type)
1991 struct mailimap_fetch_att * fetch_att;
1995 struct mailimap_header_list * imap_hdrlist;
1996 struct mailimap_section * section;
1998 hdrlist = clist_new();
2000 header = strdup("Date");
2001 r = clist_append(hdrlist, header);
2002 header = strdup("From");
2003 r = clist_append(hdrlist, header);
2004 header = strdup("To");
2005 r = clist_append(hdrlist, header);
2006 header = strdup("Cc");
2007 r = clist_append(hdrlist, header);
2008 header = strdup("Subject");
2009 r = clist_append(hdrlist, header);
2010 header = strdup("Message-ID");
2011 r = clist_append(hdrlist, header);
2012 header = strdup("References");
2013 r = clist_append(hdrlist, header);
2014 header = strdup("In-Reply-To");
2015 r = clist_append(hdrlist, header);
2017 imap_hdrlist = mailimap_header_list_new(hdrlist);
2018 section = mailimap_section_new_header_fields(imap_hdrlist);
2019 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
2020 mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2022 return MAIL_NO_ERROR;
2025 int imap_add_header_fetch_att(struct mailimap_fetch_type * fetch_type)
2027 struct mailimap_fetch_att * fetch_att;
2028 struct mailimap_section * section;
2030 section = mailimap_section_new_header();
2031 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
2032 mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2034 return MAIL_NO_ERROR;
2038 imap_get_envelopes_list(mailimap * imap, struct mailimap_set * set,
2039 carray ** p_env_list)
2041 struct mailimap_fetch_att * fetch_att;
2042 struct mailimap_fetch_type * fetch_type;
2044 clist * fetch_result;
2046 carray * env_list = NULL;
2050 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
2053 fetch_att = mailimap_fetch_att_new_uid();
2054 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2057 fetch_att = mailimap_fetch_att_new_flags();
2058 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2061 fetch_att = mailimap_fetch_att_new_rfc822_size();
2062 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2066 key.len = sizeof(imap);
2067 r = chash_get(courier_workaround_hash, &key, &value);
2069 r = imap_add_envelope_fetch_att(fetch_type);
2071 r = imap_add_header_fetch_att(fetch_type);
2073 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
2076 case MAILIMAP_NO_ERROR:
2079 mailimap_fetch_type_free(fetch_type);
2080 debug_print("uid_fetch: %d\n", r);
2084 if (clist_begin(fetch_result) == NULL) {
2085 res = MAILIMAP_ERROR_FETCH;
2086 debug_print("clist_begin = NULL\n");
2090 r = imap_fetch_result_to_envelop_list(fetch_result, &env_list);
2091 mailimap_fetch_list_free(fetch_result);
2093 if (r != MAILIMAP_NO_ERROR) {
2094 mailimap_fetch_type_free(fetch_type);
2095 res = MAILIMAP_ERROR_MEMORY;
2096 debug_print("fetch_result_to_envelop_list: %d\n", res);
2100 mailimap_fetch_type_free(fetch_type);
2102 * p_env_list = env_list;
2104 return MAILIMAP_NO_ERROR;
2110 struct fetch_env_param {
2112 struct mailimap_set * set;
2115 struct fetch_env_result {
2116 carray * fetch_env_result;
2120 static void fetch_env_run(struct etpan_thread_op * op)
2122 struct fetch_env_param * param;
2123 struct fetch_env_result * result;
2130 r = imap_get_envelopes_list(param->imap, param->set,
2133 result = op->result;
2135 result->fetch_env_result = env_list;
2137 debug_print("imap fetch_env run - end %i\n", r);
2140 int imap_threaded_fetch_env(Folder * folder, struct mailimap_set * set,
2141 carray ** p_env_list)
2143 struct fetch_env_param param;
2144 struct fetch_env_result result;
2147 debug_print("imap fetch_env - begin\n");
2149 imap = get_imap(folder);
2153 threaded_run(folder, ¶m, &result, fetch_env_run);
2155 if (result.error != MAILIMAP_NO_ERROR) {
2161 key.len = sizeof(imap);
2162 r = chash_get(courier_workaround_hash, &key, &value);
2166 chash_set(courier_workaround_hash, &key, &value, NULL);
2168 threaded_run(folder, ¶m, &result, fetch_env_run);
2172 if (result.error != MAILIMAP_NO_ERROR)
2173 return result.error;
2175 debug_print("imap fetch_env - end\n");
2177 * p_env_list = result.fetch_env_result;
2179 return result.error;
2182 void imap_fetch_env_free(carray * env_list)
2186 for(i = 0 ; i < carray_count(env_list) ; i ++) {
2187 struct imap_fetch_env_info * env_info;
2189 env_info = carray_get(env_list, i);
2190 free(env_info->headers);
2193 carray_free(env_list);
2200 struct append_param {
2202 const char * mailbox;
2203 const char * filename;
2204 struct mailimap_flag_list * flag_list;
2207 struct append_result {
2212 static void append_run(struct etpan_thread_op * op)
2214 struct append_param * param;
2215 struct append_result * result;
2219 struct stat stat_buf;
2221 guint32 uid = 0, val = 0;
2224 result = op->result;
2226 r = stat(param->filename, &stat_buf);
2228 result->error = MAILIMAP_ERROR_APPEND;
2231 size = stat_buf.st_size;
2233 fd = open(param->filename, O_RDONLY);
2235 result->error = MAILIMAP_ERROR_APPEND;
2239 data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
2240 if (data == (void *) MAP_FAILED) {
2242 result->error = MAILIMAP_ERROR_APPEND;
2246 mailstream_logger = imap_logger_append;
2248 r = mailimap_uidplus_append(param->imap, param->mailbox,
2249 param->flag_list, NULL,
2250 data, size, &val, &uid);
2252 mailstream_logger = imap_logger_cmd;
2259 debug_print("imap append run - end %i uid %d\n", r, uid);
2262 int imap_threaded_append(Folder * folder, const char * mailbox,
2263 const char * filename,
2264 struct mailimap_flag_list * flag_list,
2267 struct append_param param;
2268 struct append_result result;
2271 debug_print("imap append - begin\n");
2273 imap = get_imap(folder);
2275 param.mailbox = mailbox;
2276 param.filename = filename;
2277 param.flag_list = flag_list;
2279 threaded_run(folder, ¶m, &result, append_run);
2281 if (result.error != MAILIMAP_NO_ERROR)
2282 return result.error;
2284 debug_print("imap append - end\n");
2288 return result.error;
2294 struct expunge_param {
2298 struct expunge_result {
2302 static void expunge_run(struct etpan_thread_op * op)
2304 struct expunge_param * param;
2305 struct expunge_result * result;
2309 r = mailimap_expunge(param->imap);
2311 result = op->result;
2313 debug_print("imap expunge run - end %i\n", r);
2316 int imap_threaded_expunge(Folder * folder)
2318 struct expunge_param param;
2319 struct expunge_result result;
2321 debug_print("imap expunge - begin\n");
2323 param.imap = get_imap(folder);
2325 threaded_run(folder, ¶m, &result, expunge_run);
2327 debug_print("imap expunge - end\n");
2329 return result.error;
2335 struct mailimap_set * set;
2339 struct copy_result {
2341 struct mailimap_set *source;
2342 struct mailimap_set *dest;
2345 static void copy_run(struct etpan_thread_op * op)
2347 struct copy_param * param;
2348 struct copy_result * result;
2352 struct mailimap_set *source = NULL, *dest = NULL;
2354 r = mailimap_uidplus_uid_copy(param->imap, param->set, param->mb,
2355 &val, &source, &dest);
2357 result = op->result;
2360 result->source = source;
2361 result->dest = dest;
2363 result->source = NULL;
2364 result->dest = NULL;
2366 debug_print("imap copy run - end %i\n", r);
2369 int imap_threaded_copy(Folder * folder, struct mailimap_set * set,
2370 const char * mb, struct mailimap_set **source,
2371 struct mailimap_set **dest)
2373 struct copy_param param;
2374 struct copy_result result;
2377 debug_print("imap copy - begin\n");
2379 imap = get_imap(folder);
2384 threaded_run(folder, ¶m, &result, copy_run);
2388 if (result.error != MAILIMAP_NO_ERROR)
2389 return result.error;
2391 *source = result.source;
2392 *dest = result.dest;
2394 debug_print("imap copy - end\n");
2396 return result.error;
2401 struct store_param {
2403 struct mailimap_set * set;
2404 struct mailimap_store_att_flags * store_att_flags;
2407 struct store_result {
2411 static void store_run(struct etpan_thread_op * op)
2413 struct store_param * param;
2414 struct store_result * result;
2419 r = mailimap_uid_store(param->imap, param->set,
2420 param->store_att_flags);
2422 result = op->result;
2425 debug_print("imap store run - end %i\n", r);
2428 int imap_threaded_store(Folder * folder, struct mailimap_set * set,
2429 struct mailimap_store_att_flags * store_att_flags)
2431 struct store_param param;
2432 struct store_result result;
2435 debug_print("imap store - begin\n");
2437 imap = get_imap(folder);
2440 param.store_att_flags = store_att_flags;
2442 threaded_run(folder, ¶m, &result, store_run);
2444 if (result.error != MAILIMAP_NO_ERROR)
2445 return result.error;
2447 debug_print("imap store - end\n");
2449 return result.error;
2453 #define ENV_BUFFER_SIZE 512
2455 static void do_exec_command(int fd, const char * command,
2456 const char * servername, uint16_t port)
2460 char env_buffer[ENV_BUFFER_SIZE];
2464 /* Fork again to become a child of init rather than
2465 the etpan client. */
2471 snprintf(env_buffer, ENV_BUFFER_SIZE,
2472 "ETPANSERVER=%s", servername);
2474 snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANSERVER=");
2478 setenv("ETPANSERVER", servername, 1);
2480 unsetenv("ETPANSERVER");
2485 snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANPORT=%d", port);
2487 snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANPORT=");
2493 snprintf(porttext, sizeof(porttext), "%d", port);
2494 setenv("ETPANPORT", porttext, 1);
2497 unsetenv("ETPANPORT");
2501 /* Not a lot we can do if there's an error other than bail. */
2502 if (dup2(fd, 0) == -1)
2504 if (dup2(fd, 1) == -1)
2507 /* Should we close stderr and reopen /dev/null? */
2509 maxopen = sysconf(_SC_OPEN_MAX);
2510 for (i=3; i < maxopen; i++)
2514 /* Detach from the controlling tty if we have one. Otherwise,
2515 SSH might do something stupid like trying to use it instead
2516 of running $SSH_ASKPASS. Doh. */
2517 fd = open("/dev/tty", O_RDONLY);
2519 ioctl(fd, TIOCNOTTY, NULL);
2522 #endif /* TIOCNOTTY */
2524 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
2526 /* Eep. Shouldn't reach this */
2530 static int subcommand_connect(const char *command,
2531 const char *servername, uint16_t port)
2533 /* SEB unsupported on Windows */
2537 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds))
2542 do_exec_command(sockfds[1], command, servername, port);
2544 else if (childpid == -1) {
2552 /* Reap child, leaving grandchild process to run */
2553 waitpid(childpid, NULL, 0);
2558 int socket_connect_cmd(mailimap * imap, const char * command,
2559 const char * server, int port)
2565 fd = subcommand_connect(command, server, port);
2567 return MAILIMAP_ERROR_STREAM;
2569 s = mailstream_socket_open(fd);
2572 return MAILIMAP_ERROR_STREAM;
2575 r = mailimap_connect(imap, s);
2576 if (r != MAILIMAP_NO_ERROR_AUTHENTICATED
2577 && r != MAILIMAP_NO_ERROR_NON_AUTHENTICATED) {
2578 mailstream_close(s);
2587 struct connect_cmd_param {
2589 const char * command;
2590 const char * server;
2594 struct connect_cmd_result {
2598 static void connect_cmd_run(struct etpan_thread_op * op)
2601 struct connect_cmd_param * param;
2602 struct connect_cmd_result * result;
2605 result = op->result;
2607 r = socket_connect_cmd(param->imap, param->command,
2608 param->server, param->port);
2614 int imap_threaded_connect_cmd(Folder * folder, const char * command,
2615 const char * server, int port)
2617 struct connect_cmd_param param;
2618 struct connect_cmd_result result;
2623 imap = mailimap_new(0, NULL);
2626 key.len = sizeof(folder);
2629 chash_set(session_hash, &key, &value, NULL);
2632 param.command = command;
2633 param.server = server;
2636 threaded_run(folder, ¶m, &result, connect_cmd_run);
2638 debug_print("connect_cmd ok %i\n", result.error);
2640 return result.error;
2644 void imap_main_init(void)
2647 void imap_main_done(void)
2650 void imap_main_set_timeout(int sec)