2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2005-2009 DINH Viet Hoa and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "imap-thread.h"
28 #include <sys/types.h>
30 #if (defined(__DragonFly__) || defined (__NetBSD__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__CYGWIN__))
31 #include <sys/socket.h>
40 #include "etpan-thread-manager.h"
42 #include "mainwindow.h"
44 #include "ssl_certificate.h"
46 #include "remotefolder.h"
48 #define DISABLE_LOG_DURING_LOGIN
50 static struct etpan_thread_manager * thread_manager = NULL;
51 static chash * courier_workaround_hash = NULL;
52 static chash * imap_hash = NULL;
53 static chash * session_hash = NULL;
54 static guint thread_manager_signal = 0;
55 static GIOChannel * io_channel = NULL;
57 static void delete_imap(Folder *folder, mailimap *imap)
63 key.len = sizeof(folder);
66 chash_delete(session_hash, &key, NULL);
69 key.len = sizeof(imap);
70 chash_delete(courier_workaround_hash, &key, NULL);
71 if (imap && imap->imap_stream) {
72 /* we don't want libetpan to logout */
73 mailstream_close(imap->imap_stream);
74 imap->imap_stream = NULL;
76 debug_print("removing mailimap %p\n", imap);
80 static gboolean thread_manager_event(GIOChannel * source,
81 GIOCondition condition,
88 if (condition & G_IO_IN)
89 g_io_channel_read_chars(source, &ch, 1, &bytes_read, NULL);
91 etpan_thread_manager_loop(thread_manager);
96 static void imap_logger_noop(int direction, const char * str, size_t size)
101 static void imap_logger_cmd(int direction, const char * str, size_t size)
108 log_print(LOG_PROTOCOL, "IMAP4%c [CMD data - %zd bytes]\n", direction?'>':'<', size);
111 buf = malloc(size+1);
112 memset(buf, 0, size+1);
113 strncpy(buf, str, size);
116 if (!strncmp(buf, "<<<<<<<", 7)
117 || !strncmp(buf, ">>>>>>>", 7)) {
121 while (strstr(buf, "\r"))
122 *strstr(buf, "\r") = ' ';
123 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
124 buf[strlen(buf)-1] = '\0';
126 lines = g_strsplit(buf, "\n", -1);
128 while (lines[i] && *lines[i]) {
129 log_print(LOG_PROTOCOL, "IMAP4%c %s\n", direction?'>':'<', lines[i]);
136 static void imap_logger_fetch(int direction, const char * str, size_t size)
142 if (size > 128 && !direction) {
143 log_print(LOG_PROTOCOL, "IMAP4%c [FETCH data - %zd bytes]\n", direction?'>':'<', size);
147 buf = malloc(size+1);
148 memset(buf, 0, size+1);
149 strncpy(buf, str, size);
151 if (!strncmp(buf, "<<<<<<<", 7)
152 || !strncmp(buf, ">>>>>>>", 7)) {
156 while (strstr(buf, "\r"))
157 *strstr(buf, "\r") = ' ';
158 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
159 buf[strlen(buf)-1] = '\0';
161 lines = g_strsplit(buf, "\n", -1);
163 if (direction != 0 || (buf[0] == '*' && buf[1] == ' ') || size < 32) {
164 while (lines[i] && *lines[i]) {
165 log_print(LOG_PROTOCOL, "IMAP4%c %s\n", direction?'>':'<', lines[i]);
169 log_print(LOG_PROTOCOL, "IMAP4%c [data - %zd bytes]\n", direction?'>':'<', size);
175 static void imap_logger_uid(int direction, const char * str, size_t size)
182 log_print(LOG_PROTOCOL, "IMAP4%c [UID data - %zd bytes]\n", direction?'>':'<', size);
185 buf = malloc(size+1);
186 memset(buf, 0, size+1);
187 strncpy(buf, str, size);
189 if (!strncmp(buf, "<<<<<<<", 7)
190 || !strncmp(buf, ">>>>>>>", 7)) {
194 while (strstr(buf, "\r"))
195 *strstr(buf, "\r") = ' ';
196 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
197 buf[strlen(buf)-1] = '\0';
199 lines = g_strsplit(buf, "\n", -1);
201 while (lines[i] && *lines[i]) {
202 int llen = strlen(lines[i]);
204 log_print(LOG_PROTOCOL, "IMAP4%c %s\n", direction?'>':'<', lines[i]);
207 strncpy2(tmp, lines[i], 63);
208 log_print(LOG_PROTOCOL, "IMAP4%c %s[... - %d bytes more]\n", direction?'>':'<', tmp,
217 static void imap_logger_append(int direction, const char * str, size_t size)
224 log_print(LOG_PROTOCOL, "IMAP4%c [APPEND data - %zd bytes]\n", direction?'>':'<', size);
226 } else if (direction == 0 && size > 64) {
227 log_print(LOG_PROTOCOL, "IMAP4%c [APPEND data - %zd bytes]\n", direction?'>':'<', size);
230 buf = malloc(size+1);
231 memset(buf, 0, size+1);
232 strncpy(buf, str, size);
234 if (!strncmp(buf, "<<<<<<<", 7)
235 || !strncmp(buf, ">>>>>>>", 7)) {
239 while (strstr(buf, "\r"))
240 *strstr(buf, "\r") = ' ';
241 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
242 buf[strlen(buf)-1] = '\0';
244 lines = g_strsplit(buf, "\n", -1);
246 if (direction == 0 || (buf[0] == '*' && buf[1] == ' ') || size < 64) {
247 while (lines[i] && *lines[i]) {
248 log_print(LOG_PROTOCOL, "IMAP4%c %s\n", direction?'>':'<', lines[i]);
252 log_print(LOG_PROTOCOL, "IMAP4%c [data - %zd bytes]\n", direction?'>':'<', size);
258 #define ETPAN_DEFAULT_NETWORK_TIMEOUT 60
259 gboolean etpan_skip_ssl_cert_check = FALSE;
260 extern void mailsasl_ref(void);
262 void imap_main_init(gboolean skip_ssl_cert_check)
264 int fd_thread_manager;
266 etpan_skip_ssl_cert_check = skip_ssl_cert_check;
267 mailstream_network_delay.tv_sec = ETPAN_DEFAULT_NETWORK_TIMEOUT;
268 mailstream_network_delay.tv_usec = 0;
270 mailstream_debug = 1;
271 mailstream_logger = imap_logger_cmd;
274 imap_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
275 session_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
276 courier_workaround_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
278 thread_manager = etpan_thread_manager_new();
280 fd_thread_manager = etpan_thread_manager_get_fd(thread_manager);
283 io_channel = g_io_channel_unix_new(fd_thread_manager);
285 io_channel = g_io_channel_win32_new_fd(fd_thread_manager);
287 thread_manager_signal = g_io_add_watch_full(io_channel, 0, G_IO_IN,
288 thread_manager_event,
293 void imap_main_set_timeout(int sec)
295 mailstream_network_delay.tv_sec = sec;
296 mailstream_network_delay.tv_usec = 0;
299 void imap_main_done(gboolean have_connectivity)
301 imap_disconnect_all(have_connectivity);
302 etpan_thread_manager_stop(thread_manager);
303 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
306 etpan_thread_manager_join(thread_manager);
308 g_source_remove(thread_manager_signal);
309 g_io_channel_unref(io_channel);
311 etpan_thread_manager_free(thread_manager);
313 chash_free(courier_workaround_hash);
314 chash_free(session_hash);
315 chash_free(imap_hash);
318 void imap_init(Folder * folder)
320 struct etpan_thread * thread;
324 thread = etpan_thread_manager_get_thread(thread_manager);
327 key.len = sizeof(folder);
331 chash_set(imap_hash, &key, &value, NULL);
334 void imap_done(Folder * folder)
336 struct etpan_thread * thread;
342 key.len = sizeof(folder);
344 r = chash_get(imap_hash, &key, &value);
350 etpan_thread_unbind(thread);
352 chash_delete(imap_hash, &key, NULL);
354 debug_print("remove thread");
357 static struct etpan_thread * get_thread(Folder * folder)
359 struct etpan_thread * thread;
364 key.len = sizeof(folder);
366 chash_get(imap_hash, &key, &value);
372 static mailimap * get_imap(Folder * folder)
380 key.len = sizeof(folder);
382 r = chash_get(session_hash, &key, &value);
387 debug_print("found imap %p\n", imap);
391 static gboolean cb_show_error(gpointer data)
393 mainwindow_show_error();
397 static void generic_cb(int cancelled, void * result, void * callback_data)
399 struct etpan_thread_op * op;
401 op = (struct etpan_thread_op *) callback_data;
403 debug_print("generic_cb\n");
404 if (op->imap && op->imap->imap_response_info &&
405 op->imap->imap_response_info->rsp_alert) {
406 log_error(LOG_PROTOCOL, "IMAP4< Alert: %s\n",
407 op->imap->imap_response_info->rsp_alert);
408 g_timeout_add(10, cb_show_error, NULL);
413 static void threaded_run(Folder * folder, void * param, void * result,
414 void (* func)(struct etpan_thread_op * ))
416 struct etpan_thread_op * op;
417 struct etpan_thread * thread;
419 imap_folder_ref(folder);
421 op = etpan_thread_op_new();
423 op->imap = get_imap(folder);
429 op->callback = generic_cb;
430 op->callback_data = op;
435 thread = get_thread(folder);
436 etpan_thread_op_schedule(thread, op);
438 while (!op->finished) {
439 gtk_main_iteration();
442 etpan_thread_op_free(op);
444 imap_folder_unref(folder);
450 struct connect_param {
452 PrefsAccount *account;
457 struct connect_result {
461 #define CHECK_IMAP() { \
462 if (!param->imap) { \
463 result->error = MAILIMAP_ERROR_BAD_STATE; \
468 static void connect_run(struct etpan_thread_op * op)
471 struct connect_param * param;
472 struct connect_result * result;
479 r = mailimap_socket_connect(param->imap,
480 param->server, param->port);
486 int imap_threaded_connect(Folder * folder, const char * server, int port)
488 struct connect_param param;
489 struct connect_result result;
492 mailimap * imap, * oldimap;
494 oldimap = get_imap(folder);
496 imap = mailimap_new(0, NULL);
499 debug_print("deleting old imap %p\n", oldimap);
500 delete_imap(folder, oldimap);
504 key.len = sizeof(folder);
507 chash_set(session_hash, &key, &value, NULL);
510 param.server = server;
514 threaded_run(folder, ¶m, &result, connect_run);
516 debug_print("connect ok %i with imap %p\n", result.error, imap);
521 static int etpan_certificate_check(const unsigned char *certificate, int len, void *data)
524 struct connect_param *param = (struct connect_param *)data;
527 if (certificate == NULL || len < 0) {
528 g_warning("no cert presented.\n");
531 cert = d2i_X509(NULL, (const unsigned char **)&certificate, len);
533 g_warning("IMAP: can't get cert\n");
535 } else if (ssl_certificate_check(cert, NULL,
536 (gchar *)param->server, (gushort)param->port) == TRUE) {
544 struct connect_param *param = (struct connect_param *)data;
545 gnutls_x509_crt cert = NULL;
548 if (certificate == NULL || len < 0) {
549 g_warning("no cert presented.\n");
553 tmp.data = malloc(len);
554 memcpy(tmp.data, certificate, len);
556 gnutls_x509_crt_init(&cert);
557 if (gnutls_x509_crt_import(cert, &tmp, GNUTLS_X509_FMT_DER) < 0) {
558 g_warning("IMAP: can't get cert\n");
560 } else if (ssl_certificate_check(cert, (guint)-1, NULL,
561 (gchar *)param->server, (gushort)param->port) == TRUE) {
562 gnutls_x509_crt_deinit(cert);
565 gnutls_x509_crt_deinit(cert);
572 static void connect_ssl_context_cb(struct mailstream_ssl_context * ssl_context, void * data)
574 #if (defined(USE_OPENSSL) || defined(USE_GNUTLS))
575 PrefsAccount *account = (PrefsAccount *)data;
576 const gchar *cert_path = NULL;
577 const gchar *password = NULL;
580 EVP_PKEY *pkey = NULL;
582 gnutls_x509_crt x509 = NULL;
583 gnutls_x509_privkey pkey = NULL;
586 if (account->in_ssl_client_cert_file && *account->in_ssl_client_cert_file)
587 cert_path = account->in_ssl_client_cert_file;
588 if (account->in_ssl_client_cert_pass && *account->in_ssl_client_cert_pass)
589 password = account->in_ssl_client_cert_pass;
591 if (mailstream_ssl_set_client_certificate_data(ssl_context, NULL, 0) < 0 ||
592 mailstream_ssl_set_client_private_key_data(ssl_context, NULL, 0) < 0)
593 debug_print("Impossible to set the client certificate.\n");
594 x509 = ssl_certificate_get_x509_from_pem_file(cert_path);
595 pkey = ssl_certificate_get_pkey_from_pem_file(cert_path);
596 if (!(x509 && pkey)) {
597 /* try pkcs12 format */
598 ssl_certificate_get_x509_and_pkey_from_p12_file(cert_path, password, &x509, &pkey);
601 unsigned char *x509_der = NULL, *pkey_der = NULL;
602 size_t x509_len, pkey_len;
605 x509_len = (size_t)i2d_X509(x509, &x509_der);
606 pkey_len = (size_t)i2d_PrivateKey(pkey, &pkey_der);
608 x509_len = (size_t)gnutls_i2d_X509(x509, &x509_der);
609 pkey_len = (size_t)gnutls_i2d_PrivateKey(pkey, &pkey_der);
611 if (x509_len > 0 && pkey_len > 0) {
612 if (mailstream_ssl_set_client_certificate_data(ssl_context, x509_der, x509_len) < 0 ||
613 mailstream_ssl_set_client_private_key_data(ssl_context, pkey_der, pkey_len) < 0)
614 log_error(LOG_PROTOCOL, "Impossible to set the client certificate.\n");
619 gnutls_x509_crt_deinit(x509);
620 gnutls_x509_privkey_deinit(pkey);
626 static void connect_ssl_run(struct etpan_thread_op * op)
629 struct connect_param * param;
630 struct connect_result * result;
637 r = mailimap_ssl_connect_with_callback(param->imap,
638 param->server, param->port,
639 connect_ssl_context_cb, param->account);
643 int imap_threaded_connect_ssl(Folder * folder, const char * server, int port)
645 struct connect_param param;
646 struct connect_result result;
649 mailimap * imap, * oldimap;
650 unsigned char *certificate = NULL;
653 oldimap = get_imap(folder);
655 imap = mailimap_new(0, NULL);
658 debug_print("deleting old imap %p\n", oldimap);
659 delete_imap(folder, oldimap);
663 key.len = sizeof(folder);
666 chash_set(session_hash, &key, &value, NULL);
669 param.server = server;
671 param.account = folder->account;
674 threaded_run(folder, ¶m, &result, connect_ssl_run);
676 if ((result.error == MAILIMAP_NO_ERROR_AUTHENTICATED ||
677 result.error == MAILIMAP_NO_ERROR_NON_AUTHENTICATED) && !etpan_skip_ssl_cert_check) {
678 cert_len = (int)mailstream_ssl_get_certificate(imap->imap_stream, &certificate);
679 if (etpan_certificate_check(certificate, cert_len, ¶m) < 0)
684 debug_print("connect %d with imap %p\n", result.error, imap);
695 struct mailimap_capability_data *caps;
698 static void capability_run(struct etpan_thread_op * op)
701 struct capa_param * param;
702 struct capa_result * result;
703 struct mailimap_capability_data *caps;
710 r = mailimap_capability(param->imap, &caps);
713 result->caps = (r == 0 ? caps : NULL);
717 struct mailimap_capability_data * imap_threaded_capability(Folder *folder, int *ok)
719 struct capa_param param;
720 struct capa_result result;
723 imap = get_imap(folder);
727 threaded_run(folder, ¶m, &result, capability_run);
729 debug_print("capa %d\n", result.error);
738 struct disconnect_param {
742 struct disconnect_result {
746 static void disconnect_run(struct etpan_thread_op * op)
749 struct disconnect_param * param;
750 struct disconnect_result * result;
757 r = mailimap_logout(param->imap);
762 void imap_threaded_disconnect(Folder * folder)
764 struct connect_param param;
765 struct connect_result result;
768 imap = get_imap(folder);
770 debug_print("was disconnected\n");
776 threaded_run(folder, ¶m, &result, disconnect_run);
778 if (imap == get_imap(folder)) {
779 debug_print("deleting old imap %p\n", imap);
780 delete_imap(folder, imap);
782 debug_print("imap already deleted %p\n", imap);
785 debug_print("disconnect ok\n");
792 const char * wildcard;
801 static void list_run(struct etpan_thread_op * op)
803 struct list_param * param;
804 struct list_result * result;
815 if (param->base == NULL || param->wildcard == NULL) {
818 debug_print("no base or wildcard (%p %p)\n", param->base, param->wildcard);
822 r = mailimap_lsub(param->imap, param->base,
823 param->wildcard, &list);
825 r = mailimap_list(param->imap, param->base,
826 param->wildcard, &list);
829 debug_print("imap list run - end\n");
832 int imap_threaded_list(Folder * folder, const char * base,
833 const char * wildcard,
836 struct list_param param;
837 struct list_result result;
839 debug_print("imap list - begin\n");
841 param.imap = get_imap(folder);
843 param.wildcard = wildcard;
844 param.sub_only = FALSE;
846 threaded_run(folder, ¶m, &result, list_run);
848 * p_result = result.list;
850 debug_print("imap list - end %p\n", result.list);
855 int imap_threaded_lsub(Folder * folder, const char * base,
856 const char * wildcard,
859 struct list_param param;
860 struct list_result result;
862 debug_print("imap lsub - begin\n");
864 param.imap = get_imap(folder);
866 param.wildcard = wildcard;
867 param.sub_only = TRUE;
869 threaded_run(folder, ¶m, &result, list_run);
871 * p_result = result.list;
873 debug_print("imap lsub - end %p\n", result.list);
878 struct subscribe_param {
884 struct subscribe_result {
888 static void subscribe_run(struct etpan_thread_op * op)
890 struct subscribe_param * param;
891 struct subscribe_result * result;
899 if (param->mb == NULL) {
901 debug_print("no mb\n");
904 if (param->subscribe)
905 r = mailimap_subscribe(param->imap, param->mb);
907 r = mailimap_unsubscribe(param->imap, param->mb);
909 debug_print("imap %ssubscribe run - end %d\n", param->subscribe?"":"un", r);
912 int imap_threaded_subscribe(Folder * folder, const char * mb,
915 struct subscribe_param param;
916 struct subscribe_result result;
918 debug_print("imap list - begin\n");
920 param.imap = get_imap(folder);
922 param.subscribe = subscribe;
924 threaded_run(folder, ¶m, &result, subscribe_run);
932 const char * password;
937 struct login_result {
941 static void login_run(struct etpan_thread_op * op)
943 struct login_param * param;
944 struct login_result * result;
946 #ifdef DISABLE_LOG_DURING_LOGIN
955 #ifdef DISABLE_LOG_DURING_LOGIN
956 old_debug = mailstream_debug;
957 mailstream_debug = 0;
959 if (!strcmp(param->type, "LOGIN"))
960 r = mailimap_login(param->imap,
961 param->login, param->password);
962 else if (!strcmp(param->type, "GSSAPI"))
963 r = mailimap_authenticate(param->imap,
964 param->type, param->server, NULL, NULL,
965 param->login, param->login,
966 param->password, NULL);
968 r = mailimap_authenticate(param->imap,
969 param->type, NULL, NULL, NULL,
970 param->login, param->login,
971 param->password, NULL);
972 #ifdef DISABLE_LOG_DURING_LOGIN
973 mailstream_debug = old_debug;
977 if (param->imap->imap_response)
978 imap_logger_cmd(0, param->imap->imap_response, strlen(param->imap->imap_response));
979 debug_print("imap login run - end %i\n", r);
982 int imap_threaded_login(Folder * folder,
983 const char * login, const char * password,
986 struct login_param param;
987 struct login_result result;
989 debug_print("imap login - begin\n");
991 param.imap = get_imap(folder);
993 param.password = password;
995 if (folder && folder->account)
996 param.server = folder->account->recv_server;
1000 threaded_run(folder, ¶m, &result, login_run);
1002 debug_print("imap login - end\n");
1004 return result.error;
1008 struct status_param {
1011 struct mailimap_status_att_list * status_att_list;
1014 struct status_result {
1016 struct mailimap_mailbox_data_status * data_status;
1019 static void status_run(struct etpan_thread_op * op)
1021 struct status_param * param;
1022 struct status_result * result;
1026 result = op->result;
1030 r = mailimap_status(param->imap, param->mb,
1031 param->status_att_list,
1032 &result->data_status);
1035 debug_print("imap status run - end %i\n", r);
1038 int imap_threaded_status(Folder * folder, const char * mb,
1039 struct mailimap_mailbox_data_status ** data_status,
1042 struct status_param param;
1043 struct status_result result;
1044 struct mailimap_status_att_list * status_att_list;
1046 debug_print("imap status - begin\n");
1048 status_att_list = mailimap_status_att_list_new_empty();
1049 if (mask & 1 << 0) {
1050 mailimap_status_att_list_add(status_att_list,
1051 MAILIMAP_STATUS_ATT_MESSAGES);
1053 if (mask & 1 << 1) {
1054 mailimap_status_att_list_add(status_att_list,
1055 MAILIMAP_STATUS_ATT_RECENT);
1057 if (mask & 1 << 2) {
1058 mailimap_status_att_list_add(status_att_list,
1059 MAILIMAP_STATUS_ATT_UIDNEXT);
1061 if (mask & 1 << 3) {
1062 mailimap_status_att_list_add(status_att_list,
1063 MAILIMAP_STATUS_ATT_UIDVALIDITY);
1065 if (mask & 1 << 4) {
1066 mailimap_status_att_list_add(status_att_list,
1067 MAILIMAP_STATUS_ATT_UNSEEN);
1069 param.imap = get_imap(folder);
1071 param.status_att_list = status_att_list;
1073 threaded_run(folder, ¶m, &result, status_run);
1075 debug_print("imap status - end\n");
1077 * data_status = result.data_status;
1079 mailimap_status_att_list_free(status_att_list);
1081 return result.error;
1090 struct noop_result {
1094 static void noop_run(struct etpan_thread_op * op)
1096 struct noop_param * param;
1097 struct noop_result * result;
1101 result = op->result;
1105 r = mailimap_noop(param->imap);
1108 debug_print("imap noop run - end %i\n", r);
1111 int imap_threaded_noop(Folder * folder, unsigned int * p_exists,
1112 unsigned int *p_recent,
1113 unsigned int *p_expunge,
1114 unsigned int *p_unseen,
1115 unsigned int *p_uidnext,
1116 unsigned int *p_uidval)
1118 struct noop_param param;
1119 struct noop_result result;
1122 debug_print("imap noop - begin\n");
1124 imap = get_imap(folder);
1127 threaded_run(folder, ¶m, &result, noop_run);
1129 if (result.error == 0 && imap && imap->imap_selection_info != NULL) {
1130 * p_exists = imap->imap_selection_info->sel_exists;
1131 * p_recent = imap->imap_selection_info->sel_recent;
1132 * p_unseen = imap->imap_selection_info->sel_unseen;
1133 * p_uidnext = imap->imap_selection_info->sel_uidnext;
1134 * p_uidval = imap->imap_selection_info->sel_uidvalidity;
1142 if (result.error == 0 && imap && imap->imap_response_info != NULL &&
1143 imap->imap_response_info->rsp_expunged != NULL) {
1144 * p_expunge = clist_count(imap->imap_response_info->rsp_expunged);
1148 debug_print("imap noop - end [EXISTS %d RECENT %d EXPUNGE %d UNSEEN %d UIDNEXT %d UIDVAL %d]\n",
1149 *p_exists, *p_recent, *p_expunge, *p_unseen,
1150 *p_uidnext, *p_uidval);
1152 return result.error;
1156 struct starttls_result {
1160 static void starttls_run(struct etpan_thread_op * op)
1162 struct connect_param * param;
1163 struct starttls_result * result;
1167 result = op->result;
1171 r = mailimap_starttls(param->imap);
1174 debug_print("imap starttls run - end %i\n", r);
1177 mailimap *imap = param->imap;
1178 mailstream_low *plain_low = NULL;
1179 mailstream_low *tls_low = NULL;
1182 plain_low = mailstream_get_low(imap->imap_stream);
1183 fd = mailstream_low_get_fd(plain_low);
1185 debug_print("imap starttls run - can't get fd\n");
1186 result->error = MAILIMAP_ERROR_STREAM;
1190 tls_low = mailstream_low_tls_open_with_callback(fd, connect_ssl_context_cb, param->account);
1191 if (tls_low == NULL) {
1192 debug_print("imap starttls run - can't tls_open\n");
1193 result->error = MAILIMAP_ERROR_STREAM;
1196 mailstream_low_free(plain_low);
1197 mailstream_set_low(imap->imap_stream, tls_low);
1201 int imap_threaded_starttls(Folder * folder, const gchar *host, int port)
1203 struct connect_param param;
1204 struct starttls_result result;
1206 unsigned char *certificate;
1208 debug_print("imap starttls - begin\n");
1210 param.imap = get_imap(folder);
1211 param.server = host;
1213 param.account = folder->account;
1215 threaded_run(folder, ¶m, &result, starttls_run);
1217 debug_print("imap starttls - end\n");
1219 if (result.error == 0 && param.imap && !etpan_skip_ssl_cert_check) {
1220 cert_len = (int)mailstream_ssl_get_certificate(param.imap->imap_stream, &certificate);
1221 if (etpan_certificate_check(certificate, cert_len, ¶m) < 0)
1222 result.error = MAILIMAP_ERROR_STREAM;
1226 return result.error;
1231 struct create_param {
1236 struct create_result {
1240 static void create_run(struct etpan_thread_op * op)
1242 struct create_param * param;
1243 struct create_result * result;
1247 result = op->result;
1251 r = mailimap_create(param->imap, param->mb);
1254 debug_print("imap create run - end %i\n", r);
1257 int imap_threaded_create(Folder * folder, const char * mb)
1259 struct create_param param;
1260 struct create_result result;
1262 debug_print("imap create - begin\n");
1264 param.imap = get_imap(folder);
1267 threaded_run(folder, ¶m, &result, create_run);
1269 debug_print("imap create - end\n");
1271 return result.error;
1277 struct rename_param {
1280 const char * new_name;
1283 struct rename_result {
1287 static void rename_run(struct etpan_thread_op * op)
1289 struct rename_param * param;
1290 struct rename_result * result;
1294 result = op->result;
1298 r = mailimap_rename(param->imap, param->mb, param->new_name);
1301 debug_print("imap rename run - end %i\n", r);
1304 int imap_threaded_rename(Folder * folder,
1305 const char * mb, const char * new_name)
1307 struct rename_param param;
1308 struct rename_result result;
1310 debug_print("imap rename - begin\n");
1312 param.imap = get_imap(folder);
1314 param.new_name = new_name;
1316 threaded_run(folder, ¶m, &result, rename_run);
1318 debug_print("imap rename - end\n");
1320 return result.error;
1326 struct delete_param {
1331 struct delete_result {
1335 static void delete_run(struct etpan_thread_op * op)
1337 struct delete_param * param;
1338 struct delete_result * result;
1342 result = op->result;
1346 r = mailimap_delete(param->imap, param->mb);
1349 debug_print("imap delete run - end %i\n", r);
1352 int imap_threaded_delete(Folder * folder, const char * mb)
1354 struct delete_param param;
1355 struct delete_result result;
1357 debug_print("imap delete - begin\n");
1359 param.imap = get_imap(folder);
1362 threaded_run(folder, ¶m, &result, delete_run);
1364 debug_print("imap delete - end\n");
1366 return result.error;
1371 struct select_param {
1376 struct select_result {
1380 static void select_run(struct etpan_thread_op * op)
1382 struct select_param * param;
1383 struct select_result * result;
1387 result = op->result;
1391 r = mailimap_select(param->imap, param->mb);
1394 debug_print("imap select run - end %i\n", r);
1397 int imap_threaded_select(Folder * folder, const char * mb,
1398 gint * exists, gint * recent, gint * unseen,
1399 guint32 * uid_validity,gint *can_create_flags,
1402 struct select_param param;
1403 struct select_result result;
1406 debug_print("imap select - begin\n");
1408 imap = get_imap(folder);
1412 threaded_run(folder, ¶m, &result, select_run);
1414 if (result.error != MAILIMAP_NO_ERROR)
1415 return result.error;
1417 if (!imap || imap->imap_selection_info == NULL)
1418 return MAILIMAP_ERROR_PARSE;
1420 * exists = imap->imap_selection_info->sel_exists;
1421 * recent = imap->imap_selection_info->sel_recent;
1422 * unseen = imap->imap_selection_info->sel_unseen;
1423 * uid_validity = imap->imap_selection_info->sel_uidvalidity;
1424 * can_create_flags = FALSE;
1426 if (imap->imap_selection_info->sel_perm_flags) {
1427 GSList *t_flags = NULL;
1428 clistiter *cur = NULL;
1429 if (imap->imap_selection_info->sel_perm_flags)
1430 cur = clist_begin(imap->imap_selection_info->sel_perm_flags);
1432 for (; cur; cur = clist_next(cur)) {
1433 struct mailimap_flag_perm *flag = (struct mailimap_flag_perm *)clist_content(cur);
1434 if (flag->fl_type == MAILIMAP_FLAG_PERM_ALL)
1435 *can_create_flags = TRUE;
1436 else if (flag->fl_flag &&
1437 flag->fl_flag->fl_type == 6 &&
1438 !strcmp(flag->fl_flag->fl_data.fl_extension, "*"))
1439 *can_create_flags = TRUE;
1440 if (flag->fl_flag && ok_flags) {
1441 MsgPermFlags c_flag = 0;
1442 switch (flag->fl_flag->fl_type) {
1443 case MAILIMAP_FLAG_ANSWERED:
1444 c_flag = IMAP_FLAG_ANSWERED;
1446 case MAILIMAP_FLAG_FLAGGED:
1447 c_flag = IMAP_FLAG_FLAGGED;
1449 case MAILIMAP_FLAG_DELETED:
1450 c_flag = IMAP_FLAG_DELETED;
1452 case MAILIMAP_FLAG_DRAFT:
1453 c_flag = IMAP_FLAG_DRAFT;
1455 case MAILIMAP_FLAG_SEEN:
1456 c_flag = IMAP_FLAG_SEEN;
1458 case MAILIMAP_FLAG_KEYWORD:
1459 if (!strcasecmp(flag->fl_flag->fl_data.fl_keyword, "$Forwarded"))
1460 c_flag = IMAP_FLAG_FORWARDED;
1461 if (!strcasecmp(flag->fl_flag->fl_data.fl_keyword, "Junk"))
1462 c_flag = IMAP_FLAG_SPAM;
1463 if (!strcasecmp(flag->fl_flag->fl_data.fl_keyword, "NonJunk") ||
1464 !strcasecmp(flag->fl_flag->fl_data.fl_keyword, "NoJunk") ||
1465 !strcasecmp(flag->fl_flag->fl_data.fl_keyword, "NotJunk"))
1466 c_flag = IMAP_FLAG_HAM;
1472 t_flags = g_slist_prepend(t_flags,
1473 GUINT_TO_POINTER(c_flag));
1478 *ok_flags = t_flags;
1480 debug_print("imap select - end\n");
1482 return result.error;
1485 static void close_run(struct etpan_thread_op * op)
1487 struct select_param * param;
1488 struct select_result * result;
1492 result = op->result;
1496 r = mailimap_close(param->imap);
1499 debug_print("imap close run - end %i\n", r);
1502 int imap_threaded_close(Folder * folder)
1504 struct select_param param;
1505 struct select_result result;
1508 debug_print("imap close - begin\n");
1510 imap = get_imap(folder);
1513 threaded_run(folder, ¶m, &result, close_run);
1515 if (result.error != MAILIMAP_NO_ERROR)
1516 return result.error;
1518 debug_print("imap close - end\n");
1520 return result.error;
1523 struct examine_param {
1528 struct examine_result {
1532 static void examine_run(struct etpan_thread_op * op)
1534 struct examine_param * param;
1535 struct examine_result * result;
1539 result = op->result;
1543 r = mailimap_examine(param->imap, param->mb);
1546 debug_print("imap examine run - end %i\n", r);
1549 int imap_threaded_examine(Folder * folder, const char * mb,
1550 gint * exists, gint * recent, gint * unseen,
1551 guint32 * uid_validity)
1553 struct examine_param param;
1554 struct examine_result result;
1557 debug_print("imap examine - begin\n");
1559 imap = get_imap(folder);
1563 threaded_run(folder, ¶m, &result, examine_run);
1565 if (result.error != MAILIMAP_NO_ERROR)
1566 return result.error;
1568 if (!imap || imap->imap_selection_info == NULL)
1569 return MAILIMAP_ERROR_PARSE;
1571 * exists = imap->imap_selection_info->sel_exists;
1572 * recent = imap->imap_selection_info->sel_recent;
1573 * unseen = imap->imap_selection_info->sel_unseen;
1574 * uid_validity = imap->imap_selection_info->sel_uidvalidity;
1576 debug_print("imap examine - end\n");
1578 return result.error;
1584 struct search_param {
1587 struct mailimap_set * set;
1590 struct search_result {
1592 clist * search_result;
1595 static struct mailimap_set_item *sc_mailimap_set_item_copy(struct mailimap_set_item *orig)
1597 return mailimap_set_item_new(orig->set_first, orig->set_last);
1600 static struct mailimap_set *sc_mailimap_set_copy(struct mailimap_set *orig)
1602 clist *list = orig ? orig->set_list : NULL;
1603 clist *newlist = clist_new();
1608 for (cur = clist_begin(list); cur; cur = clist_next(cur))
1609 clist_append(newlist,
1610 sc_mailimap_set_item_copy(
1611 (struct mailimap_set_item *)clist_content(cur)));
1612 return mailimap_set_new(newlist);
1615 static void search_run(struct etpan_thread_op * op)
1617 struct search_param * param;
1618 struct search_result * result;
1620 struct mailimap_search_key * key = NULL;
1621 struct mailimap_search_key * uid_key = NULL;
1622 struct mailimap_search_key * search_type_key;
1623 clist * search_result;
1626 result = op->result;
1630 /* we copy the mailimap_set because freeing the key is recursive */
1631 if (param->set != NULL) {
1632 uid_key = mailimap_search_key_new_uid(sc_mailimap_set_copy(param->set));
1633 } else if (param->type == IMAP_SEARCH_TYPE_SIMPLE) {
1634 uid_key = mailimap_search_key_new_all();
1636 search_type_key = NULL;
1637 switch (param->type) {
1638 case IMAP_SEARCH_TYPE_SIMPLE:
1639 search_type_key = NULL;
1642 case IMAP_SEARCH_TYPE_SEEN:
1643 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SEEN,
1644 NULL, NULL, NULL, NULL, NULL,
1645 NULL, NULL, NULL, NULL, NULL,
1646 NULL, NULL, NULL, NULL, 0,
1647 NULL, NULL, NULL, NULL, NULL,
1648 NULL, 0, NULL, NULL, NULL);
1651 case IMAP_SEARCH_TYPE_UNSEEN:
1652 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN,
1653 NULL, NULL, NULL, NULL, NULL,
1654 NULL, NULL, NULL, NULL, NULL,
1655 NULL, NULL, NULL, NULL, 0,
1656 NULL, NULL, NULL, NULL, NULL,
1657 NULL, 0, NULL, NULL, NULL);
1660 case IMAP_SEARCH_TYPE_ANSWERED:
1661 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ANSWERED,
1662 NULL, NULL, NULL, NULL, NULL,
1663 NULL, NULL, NULL, NULL, NULL,
1664 NULL, NULL, NULL, NULL, 0,
1665 NULL, NULL, NULL, NULL, NULL,
1666 NULL, 0, NULL, NULL, NULL);
1669 case IMAP_SEARCH_TYPE_FLAGGED:
1670 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FLAGGED,
1671 NULL, NULL, NULL, NULL, NULL,
1672 NULL, NULL, NULL, NULL, NULL,
1673 NULL, NULL, NULL, NULL, 0,
1674 NULL, NULL, NULL, NULL, NULL,
1675 NULL, 0, NULL, NULL, NULL);
1677 case IMAP_SEARCH_TYPE_DELETED:
1678 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_DELETED,
1679 NULL, NULL, NULL, NULL, NULL,
1680 NULL, NULL, NULL, NULL, NULL,
1681 NULL, NULL, NULL, NULL, 0,
1682 NULL, NULL, NULL, NULL, NULL,
1683 NULL, 0, NULL, NULL, NULL);
1685 case IMAP_SEARCH_TYPE_FORWARDED:
1686 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_KEYWORD,
1687 NULL, NULL, NULL, NULL, NULL,
1688 strdup("$Forwarded"), NULL, NULL, NULL, NULL,
1689 NULL, NULL, NULL, NULL, 0,
1690 NULL, NULL, NULL, NULL, NULL,
1691 NULL, 0, NULL, NULL, NULL);
1693 case IMAP_SEARCH_TYPE_SPAM:
1694 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_KEYWORD,
1695 NULL, NULL, NULL, NULL, NULL,
1696 strdup("Junk"), NULL, NULL, NULL, NULL,
1697 NULL, NULL, NULL, NULL, 0,
1698 NULL, NULL, NULL, NULL, NULL,
1699 NULL, 0, NULL, NULL, NULL);
1703 if (search_type_key != NULL) {
1704 if (param->set != NULL) {
1705 key = mailimap_search_key_new_multiple_empty();
1706 mailimap_search_key_multiple_add(key, search_type_key);
1707 mailimap_search_key_multiple_add(key, uid_key);
1709 key = search_type_key;
1711 } else if (uid_key != NULL) {
1716 g_warning("no key!");
1717 result = op->result;
1719 result->search_result = NULL;
1721 mailstream_logger = imap_logger_uid;
1723 r = mailimap_uid_search(param->imap, NULL, key, &search_result);
1725 mailstream_logger = imap_logger_cmd;
1727 /* free the key (with the imapset) */
1728 mailimap_search_key_free(key);
1731 result->search_result = search_result;
1733 debug_print("imap search run - end %i\n", result->error);
1736 int imap_threaded_search(Folder * folder, int search_type,
1737 struct mailimap_set * set, clist ** search_result)
1739 struct search_param param;
1740 struct search_result result;
1743 debug_print("imap search - begin\n");
1745 imap = get_imap(folder);
1748 param.type = search_type;
1750 threaded_run(folder, ¶m, &result, search_run);
1752 if (result.error != MAILIMAP_NO_ERROR)
1753 return result.error;
1755 debug_print("imap search - end\n");
1757 * search_result = result.search_result;
1759 return result.error;
1764 static int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
1768 struct mailimap_msg_att_dynamic ** patt_dyn);
1771 result_to_uid_list(clist * fetch_result, carray ** result)
1773 clistiter * cur = NULL;
1778 tab = carray_new(128);
1780 res = MAILIMAP_ERROR_MEMORY;
1785 cur = clist_begin(fetch_result);
1787 for(; cur != NULL ; cur = clist_next(cur)) {
1788 struct mailimap_msg_att * msg_att;
1792 msg_att = clist_content(cur);
1795 imap_get_msg_att_info(msg_att, &uid, NULL, NULL, NULL);
1797 puid = malloc(sizeof(* puid));
1799 res = MAILIMAP_ERROR_MEMORY;
1804 r = carray_add(tab, puid, NULL);
1807 res = MAILIMAP_ERROR_MEMORY;
1814 return MAILIMAP_NO_ERROR;
1817 imap_fetch_uid_list_free(tab);
1822 static int imap_get_messages_list(mailimap * imap,
1823 uint32_t first_index,
1828 struct mailimap_fetch_att * fetch_att;
1829 struct mailimap_fetch_type * fetch_type;
1830 struct mailimap_set * set;
1831 clist * fetch_result;
1834 set = mailimap_set_new_interval(first_index, 0);
1836 res = MAILIMAP_ERROR_MEMORY;
1840 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
1841 if (fetch_type == NULL) {
1842 res = MAILIMAP_ERROR_MEMORY;
1846 fetch_att = mailimap_fetch_att_new_uid();
1847 if (fetch_att == NULL) {
1848 res = MAILIMAP_ERROR_MEMORY;
1849 goto free_fetch_type;
1852 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1853 if (r != MAILIMAP_NO_ERROR) {
1854 mailimap_fetch_att_free(fetch_att);
1855 res = MAILIMAP_ERROR_MEMORY;
1856 goto free_fetch_type;
1859 mailstream_logger = imap_logger_fetch;
1861 r = mailimap_uid_fetch(imap, set,
1862 fetch_type, &fetch_result);
1864 mailstream_logger = imap_logger_cmd;
1865 mailimap_fetch_type_free(fetch_type);
1866 mailimap_set_free(set);
1868 if (r != MAILIMAP_NO_ERROR) {
1874 r = result_to_uid_list(fetch_result, &env_list);
1875 mailimap_fetch_list_free(fetch_result);
1877 * result = env_list;
1879 return MAILIMAP_NO_ERROR;
1882 mailimap_fetch_type_free(fetch_type);
1884 mailimap_set_free(set);
1892 struct fetch_uid_param {
1894 uint32_t first_index;
1897 struct fetch_uid_result {
1899 carray * fetch_result;
1902 static void fetch_uid_run(struct etpan_thread_op * op)
1904 struct fetch_uid_param * param;
1905 struct fetch_uid_result * result;
1906 carray * fetch_result;
1910 result = op->result;
1914 fetch_result = NULL;
1915 mailstream_logger = imap_logger_noop;
1916 log_print(LOG_PROTOCOL, "IMAP4- [fetching UIDs...]\n");
1918 r = imap_get_messages_list(param->imap, param->first_index,
1921 mailstream_logger = imap_logger_cmd;
1924 result->fetch_result = fetch_result;
1925 debug_print("imap fetch_uid run - end %i\n", r);
1928 int imap_threaded_fetch_uid(Folder * folder, uint32_t first_index,
1929 carray ** fetch_result)
1931 struct fetch_uid_param param;
1932 struct fetch_uid_result result;
1935 debug_print("imap fetch_uid - begin\n");
1937 imap = get_imap(folder);
1939 param.first_index = first_index;
1941 threaded_run(folder, ¶m, &result, fetch_uid_run);
1943 if (result.error != MAILIMAP_NO_ERROR)
1944 return result.error;
1946 debug_print("imap fetch_uid - end\n");
1948 * fetch_result = result.fetch_result;
1950 return result.error;
1954 void imap_fetch_uid_list_free(carray * uid_list)
1958 for(i = 0 ; i < carray_count(uid_list) ; i ++) {
1961 puid = carray_get(uid_list, i);
1964 carray_free(uid_list);
1970 static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, GSList **tags);
1973 result_to_uid_flags_list(clist * fetch_result, carray ** result)
1975 clistiter * cur = NULL;
1979 GSList *tags = NULL;
1981 tab = carray_new(128);
1983 res = MAILIMAP_ERROR_MEMORY;
1988 cur = clist_begin(fetch_result);
1990 for(; cur != NULL ; cur = clist_next(cur)) {
1991 struct mailimap_msg_att * msg_att;
1994 struct mailimap_msg_att_dynamic * att_dyn;
2000 msg_att = clist_content(cur);
2004 imap_get_msg_att_info(msg_att, &uid, NULL, NULL, &att_dyn);
2007 if (att_dyn == NULL)
2010 flags = imap_flags_to_flags(att_dyn, &tags);
2012 puid = malloc(sizeof(* puid));
2014 res = MAILIMAP_ERROR_MEMORY;
2019 r = carray_add(tab, puid, NULL);
2022 res = MAILIMAP_ERROR_MEMORY;
2025 pflags = malloc(sizeof(* pflags));
2026 if (pflags == NULL) {
2027 res = MAILIMAP_ERROR_MEMORY;
2031 r = carray_add(tab, pflags, NULL);
2034 res = MAILIMAP_ERROR_MEMORY;
2037 r = carray_add(tab, tags, NULL);
2040 res = MAILIMAP_ERROR_MEMORY;
2047 return MAILIMAP_NO_ERROR;
2050 imap_fetch_uid_flags_list_free(tab);
2051 slist_free_strings(tags);
2057 static int imap_get_messages_flags_list(mailimap * imap,
2058 uint32_t first_index,
2063 struct mailimap_fetch_att * fetch_att;
2064 struct mailimap_fetch_type * fetch_type;
2065 struct mailimap_set * set;
2066 clist * fetch_result;
2069 set = mailimap_set_new_interval(first_index, 0);
2071 res = MAILIMAP_ERROR_MEMORY;
2075 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
2076 if (fetch_type == NULL) {
2077 res = MAILIMAP_ERROR_MEMORY;
2081 fetch_att = mailimap_fetch_att_new_flags();
2082 if (fetch_att == NULL) {
2083 res = MAILIMAP_ERROR_MEMORY;
2084 goto free_fetch_type;
2087 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2088 if (r != MAILIMAP_NO_ERROR) {
2089 mailimap_fetch_att_free(fetch_att);
2090 res = MAILIMAP_ERROR_MEMORY;
2091 goto free_fetch_type;
2094 fetch_att = mailimap_fetch_att_new_uid();
2095 if (fetch_att == NULL) {
2096 res = MAILIMAP_ERROR_MEMORY;
2097 goto free_fetch_type;
2100 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2101 if (r != MAILIMAP_NO_ERROR) {
2102 mailimap_fetch_att_free(fetch_att);
2103 res = MAILIMAP_ERROR_MEMORY;
2104 goto free_fetch_type;
2107 mailstream_logger = imap_logger_fetch;
2109 r = mailimap_uid_fetch(imap, set,
2110 fetch_type, &fetch_result);
2112 mailstream_logger = imap_logger_cmd;
2113 mailimap_fetch_type_free(fetch_type);
2114 mailimap_set_free(set);
2116 if (r != MAILIMAP_NO_ERROR) {
2122 r = result_to_uid_flags_list(fetch_result, &env_list);
2123 mailimap_fetch_list_free(fetch_result);
2125 * result = env_list;
2127 return MAILIMAP_NO_ERROR;
2130 mailimap_fetch_type_free(fetch_type);
2132 mailimap_set_free(set);
2139 static void fetch_uid_flags_run(struct etpan_thread_op * op)
2141 struct fetch_uid_param * param;
2142 struct fetch_uid_result * result;
2143 carray * fetch_result;
2147 result = op->result;
2151 fetch_result = NULL;
2152 r = imap_get_messages_flags_list(param->imap, param->first_index,
2156 result->fetch_result = fetch_result;
2157 debug_print("imap fetch_uid run - end %i\n", r);
2160 int imap_threaded_fetch_uid_flags(Folder * folder, uint32_t first_index,
2161 carray ** fetch_result)
2163 struct fetch_uid_param param;
2164 struct fetch_uid_result result;
2167 debug_print("imap fetch_uid - begin\n");
2169 imap = get_imap(folder);
2171 param.first_index = first_index;
2173 mailstream_logger = imap_logger_noop;
2174 log_print(LOG_PROTOCOL, "IMAP4- [fetching flags...]\n");
2176 threaded_run(folder, ¶m, &result, fetch_uid_flags_run);
2178 mailstream_logger = imap_logger_cmd;
2181 if (result.error != MAILIMAP_NO_ERROR)
2182 return result.error;
2184 debug_print("imap fetch_uid - end\n");
2186 * fetch_result = result.fetch_result;
2188 return result.error;
2192 void imap_fetch_uid_flags_list_free(carray * uid_flags_list)
2196 for(i = 0 ; i < carray_count(uid_flags_list) ; i += 3) {
2199 data = carray_get(uid_flags_list, i);
2201 data = carray_get(uid_flags_list, i + 1);
2204 carray_free(uid_flags_list);
2209 static int imap_fetch(mailimap * imap,
2212 size_t * result_len)
2215 struct mailimap_set * set;
2216 struct mailimap_fetch_att * fetch_att;
2217 struct mailimap_fetch_type * fetch_type;
2218 clist * fetch_result;
2219 struct mailimap_msg_att * msg_att;
2220 struct mailimap_msg_att_item * msg_att_item;
2225 struct mailimap_section * section;
2227 set = mailimap_set_new_single(msg_index);
2229 res = MAILIMAP_ERROR_MEMORY;
2233 section = mailimap_section_new(NULL);
2234 if (section == NULL) {
2235 res = MAILIMAP_ERROR_MEMORY;
2239 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
2240 if (fetch_att == NULL) {
2241 mailimap_section_free(section);
2242 res = MAILIMAP_ERROR_MEMORY;
2246 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
2247 if (fetch_type == NULL) {
2248 res = MAILIMAP_ERROR_MEMORY;
2249 goto free_fetch_att;
2252 mailstream_logger = imap_logger_fetch;
2254 r = mailimap_uid_fetch(imap, set,
2255 fetch_type, &fetch_result);
2257 mailstream_logger = imap_logger_cmd;
2259 mailimap_fetch_type_free(fetch_type);
2260 mailimap_set_free(set);
2263 case MAILIMAP_NO_ERROR:
2269 if (fetch_result == NULL || clist_begin(fetch_result) == NULL) {
2270 mailimap_fetch_list_free(fetch_result);
2271 return MAILIMAP_ERROR_FETCH;
2274 msg_att = clist_begin(fetch_result)->data;
2279 if (msg_att->att_list)
2280 cur = clist_begin(msg_att->att_list);
2284 for(; cur != NULL ; cur = clist_next(cur)) {
2285 msg_att_item = clist_content(cur);
2287 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
2288 if (msg_att_item->att_data.att_static->att_type ==
2289 MAILIMAP_MSG_ATT_BODY_SECTION) {
2290 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
2292 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
2294 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
2299 mailimap_fetch_list_free(fetch_result);
2302 return MAILIMAP_ERROR_FETCH;
2305 * result_len = text_length;
2307 return MAILIMAP_NO_ERROR;
2310 mailimap_fetch_att_free(fetch_att);
2312 mailimap_set_free(set);
2317 static int imap_fetch_header(mailimap * imap,
2320 size_t * result_len)
2323 struct mailimap_set * set;
2324 struct mailimap_fetch_att * fetch_att;
2325 struct mailimap_fetch_type * fetch_type;
2326 clist * fetch_result;
2327 struct mailimap_msg_att * msg_att;
2328 struct mailimap_msg_att_item * msg_att_item;
2333 struct mailimap_section * section;
2335 set = mailimap_set_new_single(msg_index);
2337 res = MAILIMAP_ERROR_MEMORY;
2341 section = mailimap_section_new_header();
2342 if (section == NULL) {
2343 res = MAILIMAP_ERROR_MEMORY;
2347 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
2348 if (fetch_att == NULL) {
2349 mailimap_section_free(section);
2350 res = MAILIMAP_ERROR_MEMORY;
2354 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
2355 if (fetch_type == NULL) {
2356 res = MAILIMAP_ERROR_MEMORY;
2357 goto free_fetch_att;
2360 mailstream_logger = imap_logger_fetch;
2362 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
2364 mailstream_logger = imap_logger_cmd;
2365 mailimap_fetch_type_free(fetch_type);
2366 mailimap_set_free(set);
2369 case MAILIMAP_NO_ERROR:
2375 if (fetch_result == NULL || clist_begin(fetch_result) == NULL) {
2376 mailimap_fetch_list_free(fetch_result);
2377 return MAILIMAP_ERROR_FETCH;
2380 msg_att = clist_begin(fetch_result)->data;
2385 if (msg_att->att_list)
2386 cur = clist_begin(msg_att->att_list);
2390 for(; cur != NULL ; cur = clist_next(cur)) {
2391 msg_att_item = clist_content(cur);
2393 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
2394 if (msg_att_item->att_data.att_static->att_type ==
2395 MAILIMAP_MSG_ATT_BODY_SECTION) {
2396 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
2397 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
2399 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
2404 mailimap_fetch_list_free(fetch_result);
2407 return MAILIMAP_ERROR_FETCH;
2410 * result_len = text_length;
2412 return MAILIMAP_NO_ERROR;
2415 mailimap_fetch_att_free(fetch_att);
2417 mailimap_set_free(set);
2424 struct fetch_content_param {
2427 const char * filename;
2431 struct fetch_content_result {
2435 static void fetch_content_run(struct etpan_thread_op * op)
2437 struct fetch_content_param * param;
2438 struct fetch_content_result * result;
2440 size_t content_size;
2446 result = op->result;
2452 if (param->with_body)
2453 r = imap_fetch(param->imap, param->msg_index,
2454 &content, &content_size);
2456 r = imap_fetch_header(param->imap, param->msg_index,
2457 &content, &content_size);
2461 if (r == MAILIMAP_NO_ERROR) {
2462 fd = g_open(param->filename, O_RDWR | O_CREAT, 0600);
2464 result->error = MAILIMAP_ERROR_FETCH;
2468 f = fdopen(fd, "wb");
2470 result->error = MAILIMAP_ERROR_FETCH;
2474 r = fwrite(content, 1, content_size, f);
2475 if (r < content_size) {
2476 result->error = MAILIMAP_ERROR_FETCH;
2482 result->error = MAILIMAP_ERROR_FETCH;
2493 claws_unlink(param->filename);
2496 /* mmap_string_unref is a simple free in libetpan
2497 * when it has MMAP_UNAVAILABLE defined */
2498 if (mmap_string_unref(content) != 0)
2502 debug_print("imap fetch_content run - end %i\n", result->error);
2505 int imap_threaded_fetch_content(Folder * folder, uint32_t msg_index,
2507 const char * filename)
2509 struct fetch_content_param param;
2510 struct fetch_content_result result;
2513 debug_print("imap fetch_content - begin\n");
2515 imap = get_imap(folder);
2517 param.msg_index = msg_index;
2518 param.filename = filename;
2519 param.with_body = with_body;
2521 threaded_run(folder, ¶m, &result, fetch_content_run);
2523 if (result.error != MAILIMAP_NO_ERROR)
2524 return result.error;
2526 debug_print("imap fetch_content - end\n");
2528 return result.error;
2533 static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, GSList **s_tags)
2538 GSList *tags = NULL;
2542 flag_list = att_dyn->att_list;
2543 if (flag_list == NULL)
2546 for(cur = clist_begin(flag_list) ; cur != NULL ;
2547 cur = clist_next(cur)) {
2548 struct mailimap_flag_fetch * flag_fetch;
2550 flag_fetch = clist_content(cur);
2551 if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT)
2554 switch (flag_fetch->fl_flag->fl_type) {
2555 case MAILIMAP_FLAG_ANSWERED:
2556 flags |= MSG_REPLIED;
2558 case MAILIMAP_FLAG_FLAGGED:
2559 flags |= MSG_MARKED;
2561 case MAILIMAP_FLAG_DELETED:
2562 flags |= MSG_DELETED;
2564 case MAILIMAP_FLAG_SEEN:
2565 flags &= ~MSG_UNREAD;
2568 case MAILIMAP_FLAG_KEYWORD:
2569 if (!strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "$Forwarded"))
2570 flags |= MSG_FORWARDED;
2571 else if (!strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "Junk"))
2573 else if (!strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "NonJunk") ||
2574 !strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "NoJunk") ||
2575 !strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "NotJunk"))
2578 tags = g_slist_prepend(tags, g_strdup(flag_fetch->fl_flag->fl_data.fl_keyword));
2588 static int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
2592 struct mailimap_msg_att_dynamic ** patt_dyn)
2594 clistiter * item_cur;
2598 struct mailimap_msg_att_dynamic * att_dyn;
2605 if (msg_att->att_list)
2606 item_cur = clist_begin(msg_att->att_list);
2609 for(; item_cur != NULL ; item_cur = clist_next(item_cur)) {
2610 struct mailimap_msg_att_item * item;
2612 item = clist_content(item_cur);
2614 switch (item->att_type) {
2615 case MAILIMAP_MSG_ATT_ITEM_STATIC:
2616 switch (item->att_data.att_static->att_type) {
2617 case MAILIMAP_MSG_ATT_UID:
2618 uid = item->att_data.att_static->att_data.att_uid;
2621 case MAILIMAP_MSG_ATT_BODY_SECTION:
2622 if (headers == NULL) {
2623 headers = item->att_data.att_static->att_data.att_body_section->sec_body_part;
2626 case MAILIMAP_MSG_ATT_RFC822_SIZE:
2627 ref_size = item->att_data.att_static->att_data.att_rfc822_size;
2632 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
2633 if (att_dyn == NULL) {
2634 att_dyn = item->att_data.att_dyn;
2642 if (pheaders != NULL)
2643 * pheaders = headers;
2644 if (pref_size != NULL)
2645 * pref_size = ref_size;
2646 if (patt_dyn != NULL)
2647 * patt_dyn = att_dyn;
2649 return MAIL_NO_ERROR;
2652 static struct imap_fetch_env_info *
2653 fetch_to_env_info(struct mailimap_msg_att * msg_att, GSList **tags)
2655 struct imap_fetch_env_info * info;
2659 struct mailimap_msg_att_dynamic * att_dyn;
2661 imap_get_msg_att_info(msg_att, &uid, &headers, &size,
2666 info = malloc(sizeof(* info));
2668 info->headers = strdup(headers);
2670 info->flags = imap_flags_to_flags(att_dyn, tags);
2676 imap_fetch_result_to_envelop_list(clist * fetch_result,
2677 carray ** p_env_list)
2684 env_list = carray_new(16);
2687 for(cur = clist_begin(fetch_result) ; cur != NULL ;
2688 cur = clist_next(cur)) {
2689 struct mailimap_msg_att * msg_att;
2690 struct imap_fetch_env_info * env_info;
2691 GSList *tags = NULL;
2693 msg_att = clist_content(cur);
2695 env_info = fetch_to_env_info(msg_att, &tags);
2697 return MAILIMAP_ERROR_MEMORY;
2698 carray_add(env_list, env_info, NULL);
2699 carray_add(env_list, tags, NULL);
2701 * p_env_list = env_list;
2703 * p_env_list = NULL;
2706 return MAIL_NO_ERROR;
2709 static int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type)
2711 struct mailimap_fetch_att * fetch_att;
2715 struct mailimap_header_list * imap_hdrlist;
2716 struct mailimap_section * section;
2718 hdrlist = clist_new();
2720 header = strdup("Date");
2721 r = clist_append(hdrlist, header);
2722 header = strdup("From");
2723 r = clist_append(hdrlist, header);
2724 header = strdup("To");
2725 r = clist_append(hdrlist, header);
2726 header = strdup("Cc");
2727 r = clist_append(hdrlist, header);
2728 header = strdup("Subject");
2729 r = clist_append(hdrlist, header);
2730 header = strdup("Message-ID");
2731 r = clist_append(hdrlist, header);
2732 header = strdup("References");
2733 r = clist_append(hdrlist, header);
2734 header = strdup("In-Reply-To");
2735 r = clist_append(hdrlist, header);
2737 imap_hdrlist = mailimap_header_list_new(hdrlist);
2738 section = mailimap_section_new_header_fields(imap_hdrlist);
2739 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
2740 mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2742 return MAIL_NO_ERROR;
2745 static int imap_add_header_fetch_att(struct mailimap_fetch_type * fetch_type)
2747 struct mailimap_fetch_att * fetch_att;
2748 struct mailimap_section * section;
2750 section = mailimap_section_new_header();
2751 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
2752 mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2754 return MAIL_NO_ERROR;
2758 imap_get_envelopes_list(mailimap * imap, struct mailimap_set * set,
2759 carray ** p_env_list)
2761 struct mailimap_fetch_att * fetch_att;
2762 struct mailimap_fetch_type * fetch_type;
2764 clist * fetch_result;
2766 carray * env_list = NULL;
2770 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
2773 fetch_att = mailimap_fetch_att_new_uid();
2774 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2777 fetch_att = mailimap_fetch_att_new_flags();
2778 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2781 fetch_att = mailimap_fetch_att_new_rfc822_size();
2782 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2786 key.len = sizeof(imap);
2787 r = chash_get(courier_workaround_hash, &key, &value);
2789 r = imap_add_envelope_fetch_att(fetch_type);
2791 r = imap_add_header_fetch_att(fetch_type);
2793 mailstream_logger = imap_logger_fetch;
2795 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
2797 mailstream_logger = imap_logger_cmd;
2799 case MAILIMAP_NO_ERROR:
2802 mailimap_fetch_type_free(fetch_type);
2803 debug_print("uid_fetch: %d\n", r);
2807 if (fetch_result == NULL || clist_begin(fetch_result) == NULL) {
2808 res = MAILIMAP_ERROR_FETCH;
2809 debug_print("clist_begin = NULL\n");
2813 r = imap_fetch_result_to_envelop_list(fetch_result, &env_list);
2814 mailimap_fetch_list_free(fetch_result);
2816 if (r != MAILIMAP_NO_ERROR) {
2817 mailimap_fetch_type_free(fetch_type);
2818 res = MAILIMAP_ERROR_MEMORY;
2819 debug_print("fetch_result_to_envelop_list: %d\n", res);
2823 mailimap_fetch_type_free(fetch_type);
2825 * p_env_list = env_list;
2827 return MAILIMAP_NO_ERROR;
2833 struct fetch_env_param {
2835 struct mailimap_set * set;
2838 struct fetch_env_result {
2839 carray * fetch_env_result;
2843 static void fetch_env_run(struct etpan_thread_op * op)
2845 struct fetch_env_param * param;
2846 struct fetch_env_result * result;
2851 result = op->result;
2856 r = imap_get_envelopes_list(param->imap, param->set,
2860 result->fetch_env_result = env_list;
2862 debug_print("imap fetch_env run - end %i\n", r);
2865 int imap_threaded_fetch_env(Folder * folder, struct mailimap_set * set,
2866 carray ** p_env_list)
2868 struct fetch_env_param param;
2869 struct fetch_env_result result;
2872 debug_print("imap fetch_env - begin\n");
2874 imap = get_imap(folder);
2878 threaded_run(folder, ¶m, &result, fetch_env_run);
2880 if (result.error != MAILIMAP_NO_ERROR) {
2886 key.len = sizeof(imap);
2887 r = chash_get(courier_workaround_hash, &key, &value);
2891 chash_set(courier_workaround_hash, &key, &value, NULL);
2893 threaded_run(folder, ¶m, &result, fetch_env_run);
2897 if (result.error != MAILIMAP_NO_ERROR)
2898 return result.error;
2900 debug_print("imap fetch_env - end\n");
2902 * p_env_list = result.fetch_env_result;
2904 return result.error;
2907 void imap_fetch_env_free(carray * env_list)
2911 for(i = 0 ; i < carray_count(env_list) ; i += 2) {
2912 struct imap_fetch_env_info * env_info;
2914 env_info = carray_get(env_list, i);
2915 free(env_info->headers);
2918 carray_free(env_list);
2925 struct append_param {
2927 const char * mailbox;
2928 const char * filename;
2929 struct mailimap_flag_list * flag_list;
2932 struct append_result {
2937 static void append_run(struct etpan_thread_op * op)
2939 struct append_param * param;
2940 struct append_result * result;
2945 struct stat stat_buf;
2948 guint32 uid = 0, val = 0;
2951 result = op->result;
2956 r = stat(param->filename, &stat_buf);
2958 result->error = MAILIMAP_ERROR_APPEND;
2961 size = stat_buf.st_size;
2963 fd = g_open(param->filename, O_RDONLY, 0);
2965 result->error = MAILIMAP_ERROR_APPEND;
2969 data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
2970 if (data == (void *) MAP_FAILED) {
2972 result->error = MAILIMAP_ERROR_APPEND;
2976 data = file_read_to_str_no_recode(param->filename);
2978 result->error = MAILIMAP_ERROR_APPEND;
2981 size = strlen(data);
2983 mailstream_logger = imap_logger_append;
2985 r = mailimap_uidplus_append(param->imap, param->mailbox,
2986 param->flag_list, NULL,
2987 data, size, &val, &uid);
2989 mailstream_logger = imap_logger_cmd;
3000 debug_print("imap append run - end %i uid %d\n", r, uid);
3003 int imap_threaded_append(Folder * folder, const char * mailbox,
3004 const char * filename,
3005 struct mailimap_flag_list * flag_list,
3008 struct append_param param;
3009 struct append_result result;
3012 debug_print("imap append - begin\n");
3014 imap = get_imap(folder);
3016 param.mailbox = mailbox;
3017 param.filename = filename;
3018 param.flag_list = flag_list;
3020 threaded_run(folder, ¶m, &result, append_run);
3022 if (result.error != MAILIMAP_NO_ERROR)
3023 return result.error;
3025 debug_print("imap append - end\n");
3029 return result.error;
3035 struct expunge_param {
3039 struct expunge_result {
3043 static void expunge_run(struct etpan_thread_op * op)
3045 struct expunge_param * param;
3046 struct expunge_result * result;
3050 result = op->result;
3054 r = mailimap_expunge(param->imap);
3057 debug_print("imap expunge run - end %i\n", r);
3060 int imap_threaded_expunge(Folder * folder)
3062 struct expunge_param param;
3063 struct expunge_result result;
3065 debug_print("imap expunge - begin\n");
3067 param.imap = get_imap(folder);
3069 threaded_run(folder, ¶m, &result, expunge_run);
3071 debug_print("imap expunge - end\n");
3073 return result.error;
3079 struct mailimap_set * set;
3083 struct copy_result {
3085 struct mailimap_set *source;
3086 struct mailimap_set *dest;
3089 static void copy_run(struct etpan_thread_op * op)
3091 struct copy_param * param;
3092 struct copy_result * result;
3095 struct mailimap_set *source = NULL, *dest = NULL;
3098 result = op->result;
3102 r = mailimap_uidplus_uid_copy(param->imap, param->set, param->mb,
3103 &val, &source, &dest);
3107 result->source = source;
3108 result->dest = dest;
3110 result->source = NULL;
3111 result->dest = NULL;
3113 debug_print("imap copy run - end %i\n", r);
3116 int imap_threaded_copy(Folder * folder, struct mailimap_set * set,
3117 const char * mb, struct mailimap_set **source,
3118 struct mailimap_set **dest)
3120 struct copy_param param;
3121 struct copy_result result;
3124 debug_print("imap copy - begin\n");
3126 imap = get_imap(folder);
3131 threaded_run(folder, ¶m, &result, copy_run);
3135 if (result.error != MAILIMAP_NO_ERROR)
3136 return result.error;
3138 *source = result.source;
3139 *dest = result.dest;
3141 debug_print("imap copy - end\n");
3143 return result.error;
3148 struct store_param {
3150 struct mailimap_set * set;
3151 struct mailimap_store_att_flags * store_att_flags;
3154 struct store_result {
3158 static void store_run(struct etpan_thread_op * op)
3160 struct store_param * param;
3161 struct store_result * result;
3165 result = op->result;
3169 r = mailimap_uid_store(param->imap, param->set,
3170 param->store_att_flags);
3174 debug_print("imap store run - end %i\n", r);
3177 int imap_threaded_store(Folder * folder, struct mailimap_set * set,
3178 struct mailimap_store_att_flags * store_att_flags)
3180 struct store_param param;
3181 struct store_result result;
3184 debug_print("imap store - begin\n");
3186 imap = get_imap(folder);
3189 param.store_att_flags = store_att_flags;
3191 threaded_run(folder, ¶m, &result, store_run);
3193 if (result.error != MAILIMAP_NO_ERROR)
3194 return result.error;
3196 debug_print("imap store - end\n");
3198 return result.error;
3202 #define ENV_BUFFER_SIZE 512
3204 static void do_exec_command(int fd, const char * command,
3205 const char * servername, uint16_t port)
3209 char env_buffer[ENV_BUFFER_SIZE];
3213 /* Fork again to become a child of init rather than
3214 the etpan client. */
3219 g_setenv("ETPANSERVER", servername, TRUE);
3221 g_unsetenv("ETPANSERVER");
3226 snprintf(porttext, sizeof(porttext), "%d", port);
3227 g_setenv("ETPANPORT", porttext, TRUE);
3230 g_unsetenv("ETPANPORT");
3233 /* Not a lot we can do if there's an error other than bail. */
3234 if (dup2(fd, 0) == -1)
3236 if (dup2(fd, 1) == -1)
3239 /* Should we close stderr and reopen /dev/null? */
3241 maxopen = sysconf(_SC_OPEN_MAX);
3242 for (i=3; i < maxopen; i++)
3246 /* Detach from the controlling tty if we have one. Otherwise,
3247 SSH might do something stupid like trying to use it instead
3248 of running $SSH_ASKPASS. Doh. */
3249 fd = g_open("/dev/tty", O_RDONLY, 0);
3251 ioctl(fd, TIOCNOTTY, NULL);
3254 #endif /* TIOCNOTTY */
3256 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
3258 /* Eep. Shouldn't reach this */
3262 static int subcommand_connect(const char *command,
3263 const char *servername, uint16_t port)
3265 /* SEB unsupported on Windows */
3269 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds))
3274 do_exec_command(sockfds[1], command, servername, port);
3276 else if (childpid == -1) {
3284 /* Reap child, leaving grandchild process to run */
3285 waitpid(childpid, NULL, 0);
3290 static int socket_connect_cmd(mailimap * imap, const char * command,
3291 const char * server, int port)
3297 fd = subcommand_connect(command, server, port);
3299 return MAILIMAP_ERROR_STREAM;
3301 s = mailstream_socket_open(fd);
3304 return MAILIMAP_ERROR_STREAM;
3307 r = mailimap_connect(imap, s);
3308 if (r != MAILIMAP_NO_ERROR_AUTHENTICATED
3309 && r != MAILIMAP_NO_ERROR_NON_AUTHENTICATED) {
3310 mailstream_close(s);
3312 imap->imap_stream = NULL;
3321 struct connect_cmd_param {
3323 const char * command;
3324 const char * server;
3328 struct connect_cmd_result {
3332 static void connect_cmd_run(struct etpan_thread_op * op)
3335 struct connect_cmd_param * param;
3336 struct connect_cmd_result * result;
3339 result = op->result;
3343 r = socket_connect_cmd(param->imap, param->command,
3344 param->server, param->port);
3350 int imap_threaded_connect_cmd(Folder * folder, const char * command,
3351 const char * server, int port)
3353 struct connect_cmd_param param;
3354 struct connect_cmd_result result;
3357 mailimap * imap, * oldimap;
3359 oldimap = get_imap(folder);
3361 imap = mailimap_new(0, NULL);
3364 debug_print("deleting old imap %p\n", oldimap);
3365 delete_imap(folder, oldimap);
3369 key.len = sizeof(folder);
3372 chash_set(session_hash, &key, &value, NULL);
3375 param.command = command;
3376 param.server = server;
3379 threaded_run(folder, ¶m, &result, connect_cmd_run);
3381 debug_print("connect_cmd ok %i with imap %p\n", result.error, imap);
3383 return result.error;
3385 #endif /* G_OS_WIN32 */
3387 void imap_threaded_cancel(Folder * folder)
3391 imap = get_imap(folder);
3392 if (imap->imap_stream != NULL)
3393 mailstream_cancel(imap->imap_stream);
3398 void imap_main_init(void)
3401 void imap_main_done(gboolean have_connectivity)
3404 void imap_main_set_timeout(int sec)
3408 void imap_threaded_cancel(Folder * folder);