2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2005-2011 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"
49 #define DISABLE_LOG_DURING_LOGIN
51 static struct etpan_thread_manager * thread_manager = NULL;
52 static chash * courier_workaround_hash = NULL;
53 static chash * imap_hash = NULL;
54 static chash * session_hash = NULL;
55 static guint thread_manager_signal = 0;
56 static GIOChannel * io_channel = NULL;
58 static void delete_imap(Folder *folder, mailimap *imap)
64 key.len = sizeof(folder);
67 chash_delete(session_hash, &key, NULL);
70 key.len = sizeof(imap);
71 chash_delete(courier_workaround_hash, &key, NULL);
72 if (imap && imap->imap_stream) {
73 /* we don't want libetpan to logout */
74 mailstream_close(imap->imap_stream);
75 imap->imap_stream = NULL;
77 debug_print("removing mailimap %p\n", imap);
81 static gboolean thread_manager_event(GIOChannel * source,
82 GIOCondition condition,
89 if (condition & G_IO_IN)
90 g_io_channel_read_chars(source, &ch, 1, &bytes_read, NULL);
92 etpan_thread_manager_loop(thread_manager);
97 static void imap_logger_noop(int direction, const char * str, size_t size)
102 static void imap_logger_cmd(int direction, const char * str, size_t size)
109 log_print(LOG_PROTOCOL, "IMAP4%c [CMD data - %zd bytes]\n", direction?'>':'<', size);
112 buf = malloc(size+1);
113 memset(buf, 0, size+1);
114 strncpy(buf, str, size);
117 if (!strncmp(buf, "<<<<<<<", 7)
118 || !strncmp(buf, ">>>>>>>", 7)) {
122 while (strstr(buf, "\r"))
123 *strstr(buf, "\r") = ' ';
124 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
125 buf[strlen(buf)-1] = '\0';
127 lines = g_strsplit(buf, "\n", -1);
129 while (lines[i] && *lines[i]) {
130 log_print(LOG_PROTOCOL, "IMAP4%c %s\n", direction?'>':'<', lines[i]);
137 static void imap_logger_fetch(int direction, const char * str, size_t size)
143 if (size > 128 && !direction) {
144 log_print(LOG_PROTOCOL, "IMAP4%c [FETCH data - %zd bytes]\n", direction?'>':'<', size);
148 buf = malloc(size+1);
149 memset(buf, 0, size+1);
150 strncpy(buf, str, size);
152 if (!strncmp(buf, "<<<<<<<", 7)
153 || !strncmp(buf, ">>>>>>>", 7)) {
157 while (strstr(buf, "\r"))
158 *strstr(buf, "\r") = ' ';
159 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
160 buf[strlen(buf)-1] = '\0';
162 lines = g_strsplit(buf, "\n", -1);
164 if (direction != 0 || (buf[0] == '*' && buf[1] == ' ') || size < 32) {
165 while (lines[i] && *lines[i]) {
166 log_print(LOG_PROTOCOL, "IMAP4%c %s\n", direction?'>':'<', lines[i]);
170 log_print(LOG_PROTOCOL, "IMAP4%c [data - %zd bytes]\n", direction?'>':'<', size);
176 static void imap_logger_uid(int direction, const char * str, size_t size)
183 log_print(LOG_PROTOCOL, "IMAP4%c [UID data - %zd bytes]\n", direction?'>':'<', size);
186 buf = malloc(size+1);
187 memset(buf, 0, size+1);
188 strncpy(buf, str, size);
190 if (!strncmp(buf, "<<<<<<<", 7)
191 || !strncmp(buf, ">>>>>>>", 7)) {
195 while (strstr(buf, "\r"))
196 *strstr(buf, "\r") = ' ';
197 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
198 buf[strlen(buf)-1] = '\0';
200 lines = g_strsplit(buf, "\n", -1);
202 while (lines[i] && *lines[i]) {
203 int llen = strlen(lines[i]);
205 log_print(LOG_PROTOCOL, "IMAP4%c %s\n", direction?'>':'<', lines[i]);
208 strncpy2(tmp, lines[i], 63);
209 log_print(LOG_PROTOCOL, "IMAP4%c %s[... - %d bytes more]\n", direction?'>':'<', tmp,
218 static void imap_logger_append(int direction, const char * str, size_t size)
225 log_print(LOG_PROTOCOL, "IMAP4%c [APPEND data - %zd bytes]\n", direction?'>':'<', size);
227 } else if (direction == 0 && size > 64) {
228 log_print(LOG_PROTOCOL, "IMAP4%c [APPEND data - %zd bytes]\n", direction?'>':'<', size);
231 buf = malloc(size+1);
232 memset(buf, 0, size+1);
233 strncpy(buf, str, size);
235 if (!strncmp(buf, "<<<<<<<", 7)
236 || !strncmp(buf, ">>>>>>>", 7)) {
240 while (strstr(buf, "\r"))
241 *strstr(buf, "\r") = ' ';
242 while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
243 buf[strlen(buf)-1] = '\0';
245 lines = g_strsplit(buf, "\n", -1);
247 if (direction == 0 || (buf[0] == '*' && buf[1] == ' ') || size < 64) {
248 while (lines[i] && *lines[i]) {
249 log_print(LOG_PROTOCOL, "IMAP4%c %s\n", direction?'>':'<', lines[i]);
253 log_print(LOG_PROTOCOL, "IMAP4%c [data - %zd bytes]\n", direction?'>':'<', size);
259 #define ETPAN_DEFAULT_NETWORK_TIMEOUT 60
260 gboolean etpan_skip_ssl_cert_check = FALSE;
261 extern void mailsasl_ref(void);
263 void imap_main_init(gboolean skip_ssl_cert_check)
265 int fd_thread_manager;
267 etpan_skip_ssl_cert_check = skip_ssl_cert_check;
268 mailstream_network_delay.tv_sec = ETPAN_DEFAULT_NETWORK_TIMEOUT;
269 mailstream_network_delay.tv_usec = 0;
271 mailstream_debug = 1;
272 mailstream_logger = imap_logger_cmd;
275 imap_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
276 session_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
277 courier_workaround_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
279 thread_manager = etpan_thread_manager_new();
281 fd_thread_manager = etpan_thread_manager_get_fd(thread_manager);
284 io_channel = g_io_channel_unix_new(fd_thread_manager);
286 io_channel = g_io_channel_win32_new_fd(fd_thread_manager);
288 thread_manager_signal = g_io_add_watch_full(io_channel, 0, G_IO_IN,
289 thread_manager_event,
294 void imap_main_set_timeout(int sec)
296 mailstream_network_delay.tv_sec = sec;
297 mailstream_network_delay.tv_usec = 0;
300 void imap_main_done(gboolean have_connectivity)
302 imap_disconnect_all(have_connectivity);
303 etpan_thread_manager_stop(thread_manager);
304 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
307 etpan_thread_manager_join(thread_manager);
309 g_source_remove(thread_manager_signal);
310 g_io_channel_unref(io_channel);
312 etpan_thread_manager_free(thread_manager);
314 chash_free(courier_workaround_hash);
315 chash_free(session_hash);
316 chash_free(imap_hash);
319 void imap_init(Folder * folder)
321 struct etpan_thread * thread;
325 thread = etpan_thread_manager_get_thread(thread_manager);
328 key.len = sizeof(folder);
332 chash_set(imap_hash, &key, &value, NULL);
335 void imap_done(Folder * folder)
337 struct etpan_thread * thread;
343 key.len = sizeof(folder);
345 r = chash_get(imap_hash, &key, &value);
351 etpan_thread_unbind(thread);
353 chash_delete(imap_hash, &key, NULL);
355 debug_print("remove thread");
358 static struct etpan_thread * get_thread(Folder * folder)
360 struct etpan_thread * thread;
365 key.len = sizeof(folder);
367 chash_get(imap_hash, &key, &value);
373 static mailimap * get_imap(Folder * folder)
381 key.len = sizeof(folder);
383 r = chash_get(session_hash, &key, &value);
388 debug_print("found imap %p\n", imap);
392 static gboolean cb_show_error(gpointer data)
394 mainwindow_show_error();
398 static void generic_cb(int cancelled, void * result, void * callback_data)
400 struct etpan_thread_op * op;
402 op = (struct etpan_thread_op *) callback_data;
404 debug_print("generic_cb\n");
405 if (op->imap && op->imap->imap_response_info &&
406 op->imap->imap_response_info->rsp_alert) {
407 log_error(LOG_PROTOCOL, "IMAP4< Alert: %s\n",
408 op->imap->imap_response_info->rsp_alert);
409 g_timeout_add(10, cb_show_error, NULL);
414 static void threaded_run(Folder * folder, void * param, void * result,
415 void (* func)(struct etpan_thread_op * ))
417 struct etpan_thread_op * op;
418 struct etpan_thread * thread;
420 imap_folder_ref(folder);
422 op = etpan_thread_op_new();
424 op->imap = get_imap(folder);
430 op->callback = generic_cb;
431 op->callback_data = op;
436 thread = get_thread(folder);
437 etpan_thread_op_schedule(thread, op);
439 while (!op->finished) {
440 gtk_main_iteration();
443 etpan_thread_op_free(op);
445 imap_folder_unref(folder);
451 struct connect_param {
453 PrefsAccount *account;
458 struct connect_result {
462 #define CHECK_IMAP() { \
463 if (!param->imap) { \
464 result->error = MAILIMAP_ERROR_BAD_STATE; \
469 static void connect_run(struct etpan_thread_op * op)
472 struct connect_param * param;
473 struct connect_result * result;
480 r = mailimap_socket_connect(param->imap,
481 param->server, param->port);
487 int imap_threaded_connect(Folder * folder, const char * server, int port)
489 struct connect_param param;
490 struct connect_result result;
493 mailimap * imap, * oldimap;
495 oldimap = get_imap(folder);
497 imap = mailimap_new(0, NULL);
500 debug_print("deleting old imap %p\n", oldimap);
501 delete_imap(folder, oldimap);
505 key.len = sizeof(folder);
508 chash_set(session_hash, &key, &value, NULL);
511 param.server = server;
515 threaded_run(folder, ¶m, &result, connect_run);
517 debug_print("connect ok %i with imap %p\n", result.error, imap);
522 static int etpan_certificate_check(const unsigned char *certificate, int len, void *data)
525 struct connect_param *param = (struct connect_param *)data;
528 if (certificate == NULL || len < 0) {
529 g_warning("no cert presented.\n");
532 cert = d2i_X509(NULL, (const unsigned char **)&certificate, len);
534 g_warning("IMAP: can't get cert\n");
536 } else if (ssl_certificate_check(cert, NULL,
537 (gchar *)param->server, (gushort)param->port) == TRUE) {
545 struct connect_param *param = (struct connect_param *)data;
546 gnutls_x509_crt cert = NULL;
549 if (certificate == NULL || len < 0) {
550 g_warning("no cert presented.\n");
554 tmp.data = malloc(len);
555 memcpy(tmp.data, certificate, len);
557 gnutls_x509_crt_init(&cert);
558 if (gnutls_x509_crt_import(cert, &tmp, GNUTLS_X509_FMT_DER) < 0) {
559 g_warning("IMAP: can't get cert\n");
561 } else if (ssl_certificate_check(cert, (guint)-1, NULL,
562 (gchar *)param->server, (gushort)param->port) == TRUE) {
563 gnutls_x509_crt_deinit(cert);
566 gnutls_x509_crt_deinit(cert);
573 static void connect_ssl_context_cb(struct mailstream_ssl_context * ssl_context, void * data)
575 #if (defined(USE_OPENSSL) || defined(USE_GNUTLS))
576 PrefsAccount *account = (PrefsAccount *)data;
577 const gchar *cert_path = NULL;
578 const gchar *password = NULL;
581 EVP_PKEY *pkey = NULL;
583 gnutls_x509_crt x509 = NULL;
584 gnutls_x509_privkey pkey = NULL;
587 if (account->in_ssl_client_cert_file && *account->in_ssl_client_cert_file)
588 cert_path = account->in_ssl_client_cert_file;
589 if (account->in_ssl_client_cert_pass && *account->in_ssl_client_cert_pass)
590 password = account->in_ssl_client_cert_pass;
592 if (mailstream_ssl_set_client_certificate_data(ssl_context, NULL, 0) < 0 ||
593 mailstream_ssl_set_client_private_key_data(ssl_context, NULL, 0) < 0)
594 debug_print("Impossible to set the client certificate.\n");
595 x509 = ssl_certificate_get_x509_from_pem_file(cert_path);
596 pkey = ssl_certificate_get_pkey_from_pem_file(cert_path);
597 if (!(x509 && pkey)) {
598 /* try pkcs12 format */
599 ssl_certificate_get_x509_and_pkey_from_p12_file(cert_path, password, &x509, &pkey);
602 unsigned char *x509_der = NULL, *pkey_der = NULL;
603 size_t x509_len, pkey_len;
606 x509_len = (size_t)i2d_X509(x509, &x509_der);
607 pkey_len = (size_t)i2d_PrivateKey(pkey, &pkey_der);
609 x509_len = (size_t)gnutls_i2d_X509(x509, &x509_der);
610 pkey_len = (size_t)gnutls_i2d_PrivateKey(pkey, &pkey_der);
612 if (x509_len > 0 && pkey_len > 0) {
613 if (mailstream_ssl_set_client_certificate_data(ssl_context, x509_der, x509_len) < 0 ||
614 mailstream_ssl_set_client_private_key_data(ssl_context, pkey_der, pkey_len) < 0)
615 log_error(LOG_PROTOCOL, "Impossible to set the client certificate.\n");
620 gnutls_x509_crt_deinit(x509);
621 gnutls_x509_privkey_deinit(pkey);
627 static void connect_ssl_run(struct etpan_thread_op * op)
630 struct connect_param * param;
631 struct connect_result * result;
638 r = mailimap_ssl_connect_with_callback(param->imap,
639 param->server, param->port,
640 connect_ssl_context_cb, param->account);
644 int imap_threaded_connect_ssl(Folder * folder, const char * server, int port)
646 struct connect_param param;
647 struct connect_result result;
650 mailimap * imap, * oldimap;
651 unsigned char *certificate = NULL;
654 oldimap = get_imap(folder);
656 imap = mailimap_new(0, NULL);
659 debug_print("deleting old imap %p\n", oldimap);
660 delete_imap(folder, oldimap);
664 key.len = sizeof(folder);
667 chash_set(session_hash, &key, &value, NULL);
670 param.server = server;
672 param.account = folder->account;
675 threaded_run(folder, ¶m, &result, connect_ssl_run);
677 if ((result.error == MAILIMAP_NO_ERROR_AUTHENTICATED ||
678 result.error == MAILIMAP_NO_ERROR_NON_AUTHENTICATED) && !etpan_skip_ssl_cert_check) {
679 cert_len = (int)mailstream_ssl_get_certificate(imap->imap_stream, &certificate);
680 if (etpan_certificate_check(certificate, cert_len, ¶m) < 0)
685 debug_print("connect %d with imap %p\n", result.error, imap);
696 struct mailimap_capability_data *caps;
699 static void capability_run(struct etpan_thread_op * op)
702 struct capa_param * param;
703 struct capa_result * result;
704 struct mailimap_capability_data *caps;
711 r = mailimap_capability(param->imap, &caps);
714 result->caps = (r == 0 ? caps : NULL);
718 struct mailimap_capability_data * imap_threaded_capability(Folder *folder, int *ok)
720 struct capa_param param;
721 struct capa_result result;
724 imap = get_imap(folder);
728 threaded_run(folder, ¶m, &result, capability_run);
730 debug_print("capa %d\n", result.error);
739 struct disconnect_param {
743 struct disconnect_result {
747 static void disconnect_run(struct etpan_thread_op * op)
750 struct disconnect_param * param;
751 struct disconnect_result * result;
758 r = mailimap_logout(param->imap);
763 void imap_threaded_disconnect(Folder * folder)
765 struct connect_param param;
766 struct connect_result result;
769 imap = get_imap(folder);
771 debug_print("was disconnected\n");
777 threaded_run(folder, ¶m, &result, disconnect_run);
779 if (imap == get_imap(folder)) {
780 debug_print("deleting old imap %p\n", imap);
781 delete_imap(folder, imap);
783 debug_print("imap already deleted %p\n", imap);
786 debug_print("disconnect ok\n");
793 const char * wildcard;
802 static void list_run(struct etpan_thread_op * op)
804 struct list_param * param;
805 struct list_result * result;
816 if (param->base == NULL || param->wildcard == NULL) {
819 debug_print("no base or wildcard (%p %p)\n", param->base, param->wildcard);
823 r = mailimap_lsub(param->imap, param->base,
824 param->wildcard, &list);
826 r = mailimap_list(param->imap, param->base,
827 param->wildcard, &list);
830 debug_print("imap list run - end\n");
833 int imap_threaded_list(Folder * folder, const char * base,
834 const char * wildcard,
837 struct list_param param;
838 struct list_result result;
840 debug_print("imap list - begin\n");
842 param.imap = get_imap(folder);
844 param.wildcard = wildcard;
845 param.sub_only = FALSE;
847 threaded_run(folder, ¶m, &result, list_run);
849 * p_result = result.list;
851 debug_print("imap list - end %p\n", result.list);
856 int imap_threaded_lsub(Folder * folder, const char * base,
857 const char * wildcard,
860 struct list_param param;
861 struct list_result result;
863 debug_print("imap lsub - begin\n");
865 param.imap = get_imap(folder);
867 param.wildcard = wildcard;
868 param.sub_only = TRUE;
870 threaded_run(folder, ¶m, &result, list_run);
872 * p_result = result.list;
874 debug_print("imap lsub - end %p\n", result.list);
879 struct subscribe_param {
885 struct subscribe_result {
889 static void subscribe_run(struct etpan_thread_op * op)
891 struct subscribe_param * param;
892 struct subscribe_result * result;
900 if (param->mb == NULL) {
902 debug_print("no mb\n");
905 if (param->subscribe)
906 r = mailimap_subscribe(param->imap, param->mb);
908 r = mailimap_unsubscribe(param->imap, param->mb);
910 debug_print("imap %ssubscribe run - end %d\n", param->subscribe?"":"un", r);
913 int imap_threaded_subscribe(Folder * folder, const char * mb,
916 struct subscribe_param param;
917 struct subscribe_result result;
919 debug_print("imap list - begin\n");
921 param.imap = get_imap(folder);
923 param.subscribe = subscribe;
925 threaded_run(folder, ¶m, &result, subscribe_run);
933 const char * password;
938 struct login_result {
942 static void login_run(struct etpan_thread_op * op)
944 struct login_param * param;
945 struct login_result * result;
947 #ifdef DISABLE_LOG_DURING_LOGIN
956 #ifdef DISABLE_LOG_DURING_LOGIN
957 old_debug = mailstream_debug;
958 mailstream_debug = 0;
960 if (!strcmp(param->type, "LOGIN"))
961 r = mailimap_login(param->imap,
962 param->login, param->password);
963 else if (!strcmp(param->type, "GSSAPI"))
964 r = mailimap_authenticate(param->imap,
965 param->type, param->server, NULL, NULL,
966 param->login, param->login,
967 param->password, NULL);
969 r = mailimap_authenticate(param->imap,
970 param->type, NULL, NULL, NULL,
971 param->login, param->login,
972 param->password, NULL);
973 #ifdef DISABLE_LOG_DURING_LOGIN
974 mailstream_debug = old_debug;
978 if (param->imap->imap_response)
979 imap_logger_cmd(0, param->imap->imap_response, strlen(param->imap->imap_response));
980 debug_print("imap login run - end %i\n", r);
983 int imap_threaded_login(Folder * folder,
984 const char * login, const char * password,
987 struct login_param param;
988 struct login_result result;
990 debug_print("imap login - begin\n");
992 param.imap = get_imap(folder);
994 param.password = password;
996 if (folder && folder->account)
997 param.server = folder->account->recv_server;
1001 threaded_run(folder, ¶m, &result, login_run);
1003 debug_print("imap login - end\n");
1005 return result.error;
1009 struct status_param {
1012 struct mailimap_status_att_list * status_att_list;
1015 struct status_result {
1017 struct mailimap_mailbox_data_status * data_status;
1020 static void status_run(struct etpan_thread_op * op)
1022 struct status_param * param;
1023 struct status_result * result;
1027 result = op->result;
1031 r = mailimap_status(param->imap, param->mb,
1032 param->status_att_list,
1033 &result->data_status);
1036 debug_print("imap status run - end %i\n", r);
1039 int imap_threaded_status(Folder * folder, const char * mb,
1040 struct mailimap_mailbox_data_status ** data_status,
1043 struct status_param param;
1044 struct status_result result;
1045 struct mailimap_status_att_list * status_att_list;
1047 debug_print("imap status - begin\n");
1049 status_att_list = mailimap_status_att_list_new_empty();
1050 if (mask & 1 << 0) {
1051 mailimap_status_att_list_add(status_att_list,
1052 MAILIMAP_STATUS_ATT_MESSAGES);
1054 if (mask & 1 << 1) {
1055 mailimap_status_att_list_add(status_att_list,
1056 MAILIMAP_STATUS_ATT_RECENT);
1058 if (mask & 1 << 2) {
1059 mailimap_status_att_list_add(status_att_list,
1060 MAILIMAP_STATUS_ATT_UIDNEXT);
1062 if (mask & 1 << 3) {
1063 mailimap_status_att_list_add(status_att_list,
1064 MAILIMAP_STATUS_ATT_UIDVALIDITY);
1066 if (mask & 1 << 4) {
1067 mailimap_status_att_list_add(status_att_list,
1068 MAILIMAP_STATUS_ATT_UNSEEN);
1070 param.imap = get_imap(folder);
1072 param.status_att_list = status_att_list;
1074 threaded_run(folder, ¶m, &result, status_run);
1076 debug_print("imap status - end\n");
1078 * data_status = result.data_status;
1080 mailimap_status_att_list_free(status_att_list);
1082 return result.error;
1091 struct noop_result {
1095 static void noop_run(struct etpan_thread_op * op)
1097 struct noop_param * param;
1098 struct noop_result * result;
1102 result = op->result;
1106 r = mailimap_noop(param->imap);
1109 debug_print("imap noop run - end %i\n", r);
1112 int imap_threaded_noop(Folder * folder, unsigned int * p_exists,
1113 unsigned int *p_recent,
1114 unsigned int *p_expunge,
1115 unsigned int *p_unseen,
1116 unsigned int *p_uidnext,
1117 unsigned int *p_uidval)
1119 struct noop_param param;
1120 struct noop_result result;
1123 debug_print("imap noop - begin\n");
1125 imap = get_imap(folder);
1128 threaded_run(folder, ¶m, &result, noop_run);
1130 if (result.error == 0 && imap && imap->imap_selection_info != NULL) {
1131 * p_exists = imap->imap_selection_info->sel_exists;
1132 * p_recent = imap->imap_selection_info->sel_recent;
1133 * p_unseen = imap->imap_selection_info->sel_unseen;
1134 * p_uidnext = imap->imap_selection_info->sel_uidnext;
1135 * p_uidval = imap->imap_selection_info->sel_uidvalidity;
1143 if (result.error == 0 && imap && imap->imap_response_info != NULL &&
1144 imap->imap_response_info->rsp_expunged != NULL) {
1145 * p_expunge = clist_count(imap->imap_response_info->rsp_expunged);
1149 debug_print("imap noop - end [EXISTS %d RECENT %d EXPUNGE %d UNSEEN %d UIDNEXT %d UIDVAL %d]\n",
1150 *p_exists, *p_recent, *p_expunge, *p_unseen,
1151 *p_uidnext, *p_uidval);
1153 return result.error;
1157 struct starttls_result {
1161 static void starttls_run(struct etpan_thread_op * op)
1163 struct connect_param * param;
1164 struct starttls_result * result;
1168 result = op->result;
1172 r = mailimap_starttls(param->imap);
1175 debug_print("imap starttls run - end %i\n", r);
1178 mailimap *imap = param->imap;
1179 mailstream_low *plain_low = NULL;
1180 mailstream_low *tls_low = NULL;
1183 plain_low = mailstream_get_low(imap->imap_stream);
1184 fd = mailstream_low_get_fd(plain_low);
1186 debug_print("imap starttls run - can't get fd\n");
1187 result->error = MAILIMAP_ERROR_STREAM;
1191 tls_low = mailstream_low_tls_open_with_callback(fd, connect_ssl_context_cb, param->account);
1192 if (tls_low == NULL) {
1193 debug_print("imap starttls run - can't tls_open\n");
1194 result->error = MAILIMAP_ERROR_STREAM;
1197 mailstream_low_free(plain_low);
1198 mailstream_set_low(imap->imap_stream, tls_low);
1202 int imap_threaded_starttls(Folder * folder, const gchar *host, int port)
1204 struct connect_param param;
1205 struct starttls_result result;
1207 unsigned char *certificate = NULL;
1209 debug_print("imap starttls - begin\n");
1211 param.imap = get_imap(folder);
1212 param.server = host;
1214 param.account = folder->account;
1216 threaded_run(folder, ¶m, &result, starttls_run);
1218 debug_print("imap starttls - end\n");
1220 if (result.error == 0 && param.imap && !etpan_skip_ssl_cert_check) {
1221 cert_len = (int)mailstream_ssl_get_certificate(param.imap->imap_stream, &certificate);
1222 if (etpan_certificate_check(certificate, cert_len, ¶m) < 0)
1223 result.error = MAILIMAP_ERROR_STREAM;
1227 return result.error;
1232 struct create_param {
1237 struct create_result {
1241 static void create_run(struct etpan_thread_op * op)
1243 struct create_param * param;
1244 struct create_result * result;
1248 result = op->result;
1252 r = mailimap_create(param->imap, param->mb);
1255 debug_print("imap create run - end %i\n", r);
1258 int imap_threaded_create(Folder * folder, const char * mb)
1260 struct create_param param;
1261 struct create_result result;
1263 debug_print("imap create - begin\n");
1265 param.imap = get_imap(folder);
1268 threaded_run(folder, ¶m, &result, create_run);
1270 debug_print("imap create - end\n");
1272 return result.error;
1278 struct rename_param {
1281 const char * new_name;
1284 struct rename_result {
1288 static void rename_run(struct etpan_thread_op * op)
1290 struct rename_param * param;
1291 struct rename_result * result;
1295 result = op->result;
1299 r = mailimap_rename(param->imap, param->mb, param->new_name);
1302 debug_print("imap rename run - end %i\n", r);
1305 int imap_threaded_rename(Folder * folder,
1306 const char * mb, const char * new_name)
1308 struct rename_param param;
1309 struct rename_result result;
1311 debug_print("imap rename - begin\n");
1313 param.imap = get_imap(folder);
1315 param.new_name = new_name;
1317 threaded_run(folder, ¶m, &result, rename_run);
1319 debug_print("imap rename - end\n");
1321 return result.error;
1327 struct delete_param {
1332 struct delete_result {
1336 static void delete_run(struct etpan_thread_op * op)
1338 struct delete_param * param;
1339 struct delete_result * result;
1343 result = op->result;
1347 r = mailimap_delete(param->imap, param->mb);
1350 debug_print("imap delete run - end %i\n", r);
1353 int imap_threaded_delete(Folder * folder, const char * mb)
1355 struct delete_param param;
1356 struct delete_result result;
1358 debug_print("imap delete - begin\n");
1360 param.imap = get_imap(folder);
1363 threaded_run(folder, ¶m, &result, delete_run);
1365 debug_print("imap delete - end\n");
1367 return result.error;
1372 struct select_param {
1377 struct select_result {
1381 static void select_run(struct etpan_thread_op * op)
1383 struct select_param * param;
1384 struct select_result * result;
1388 result = op->result;
1392 r = mailimap_select(param->imap, param->mb);
1395 debug_print("imap select run - end %i\n", r);
1398 int imap_threaded_select(Folder * folder, const char * mb,
1399 gint * exists, gint * recent, gint * unseen,
1400 guint32 * uid_validity,gint *can_create_flags,
1403 struct select_param param;
1404 struct select_result result;
1407 debug_print("imap select - begin\n");
1409 imap = get_imap(folder);
1413 threaded_run(folder, ¶m, &result, select_run);
1415 if (result.error != MAILIMAP_NO_ERROR)
1416 return result.error;
1418 if (!imap || imap->imap_selection_info == NULL)
1419 return MAILIMAP_ERROR_PARSE;
1421 * exists = imap->imap_selection_info->sel_exists;
1422 * recent = imap->imap_selection_info->sel_recent;
1423 * unseen = imap->imap_selection_info->sel_unseen;
1424 * uid_validity = imap->imap_selection_info->sel_uidvalidity;
1425 * can_create_flags = FALSE;
1427 if (imap->imap_selection_info->sel_perm_flags) {
1428 GSList *t_flags = NULL;
1429 clistiter *cur = NULL;
1430 if (imap->imap_selection_info->sel_perm_flags)
1431 cur = clist_begin(imap->imap_selection_info->sel_perm_flags);
1433 for (; cur; cur = clist_next(cur)) {
1434 struct mailimap_flag_perm *flag = (struct mailimap_flag_perm *)clist_content(cur);
1435 if (flag->fl_type == MAILIMAP_FLAG_PERM_ALL)
1436 *can_create_flags = TRUE;
1437 else if (flag->fl_flag &&
1438 flag->fl_flag->fl_type == 6 &&
1439 !strcmp(flag->fl_flag->fl_data.fl_extension, "*"))
1440 *can_create_flags = TRUE;
1441 if (flag->fl_flag && ok_flags) {
1442 MsgPermFlags c_flag = 0;
1443 switch (flag->fl_flag->fl_type) {
1444 case MAILIMAP_FLAG_ANSWERED:
1445 c_flag = IMAP_FLAG_ANSWERED;
1447 case MAILIMAP_FLAG_FLAGGED:
1448 c_flag = IMAP_FLAG_FLAGGED;
1450 case MAILIMAP_FLAG_DELETED:
1451 c_flag = IMAP_FLAG_DELETED;
1453 case MAILIMAP_FLAG_DRAFT:
1454 c_flag = IMAP_FLAG_DRAFT;
1456 case MAILIMAP_FLAG_SEEN:
1457 c_flag = IMAP_FLAG_SEEN;
1459 case MAILIMAP_FLAG_KEYWORD:
1460 if (!strcasecmp(flag->fl_flag->fl_data.fl_keyword, RTAG_FORWARDED))
1461 c_flag = IMAP_FLAG_FORWARDED;
1462 if (!strcasecmp(flag->fl_flag->fl_data.fl_keyword, RTAG_JUNK))
1463 c_flag = IMAP_FLAG_SPAM;
1464 if (!strcasecmp(flag->fl_flag->fl_data.fl_keyword, RTAG_NON_JUNK) ||
1465 !strcasecmp(flag->fl_flag->fl_data.fl_keyword, RTAG_NO_JUNK) ||
1466 !strcasecmp(flag->fl_flag->fl_data.fl_keyword, RTAG_NOT_JUNK))
1467 c_flag = IMAP_FLAG_HAM;
1473 t_flags = g_slist_prepend(t_flags,
1474 GUINT_TO_POINTER(c_flag));
1479 *ok_flags = t_flags;
1481 debug_print("imap select - end\n");
1483 return result.error;
1486 static void close_run(struct etpan_thread_op * op)
1488 struct select_param * param;
1489 struct select_result * result;
1493 result = op->result;
1497 r = mailimap_close(param->imap);
1500 debug_print("imap close run - end %i\n", r);
1503 int imap_threaded_close(Folder * folder)
1505 struct select_param param;
1506 struct select_result result;
1509 debug_print("imap close - begin\n");
1511 imap = get_imap(folder);
1514 threaded_run(folder, ¶m, &result, close_run);
1516 if (result.error != MAILIMAP_NO_ERROR)
1517 return result.error;
1519 debug_print("imap close - end\n");
1521 return result.error;
1524 struct examine_param {
1529 struct examine_result {
1533 static void examine_run(struct etpan_thread_op * op)
1535 struct examine_param * param;
1536 struct examine_result * result;
1540 result = op->result;
1544 r = mailimap_examine(param->imap, param->mb);
1547 debug_print("imap examine run - end %i\n", r);
1550 int imap_threaded_examine(Folder * folder, const char * mb,
1551 gint * exists, gint * recent, gint * unseen,
1552 guint32 * uid_validity)
1554 struct examine_param param;
1555 struct examine_result result;
1558 debug_print("imap examine - begin\n");
1560 imap = get_imap(folder);
1564 threaded_run(folder, ¶m, &result, examine_run);
1566 if (result.error != MAILIMAP_NO_ERROR)
1567 return result.error;
1569 if (!imap || imap->imap_selection_info == NULL)
1570 return MAILIMAP_ERROR_PARSE;
1572 * exists = imap->imap_selection_info->sel_exists;
1573 * recent = imap->imap_selection_info->sel_recent;
1574 * unseen = imap->imap_selection_info->sel_unseen;
1575 * uid_validity = imap->imap_selection_info->sel_uidvalidity;
1577 debug_print("imap examine - end\n");
1579 return result.error;
1585 struct search_param {
1588 struct mailimap_set * set;
1591 struct search_result {
1593 clist * search_result;
1596 static struct mailimap_set_item *sc_mailimap_set_item_copy(struct mailimap_set_item *orig)
1598 return mailimap_set_item_new(orig->set_first, orig->set_last);
1601 static struct mailimap_set *sc_mailimap_set_copy(struct mailimap_set *orig)
1603 clist *list = orig ? orig->set_list : NULL;
1604 clist *newlist = clist_new();
1609 for (cur = clist_begin(list); cur; cur = clist_next(cur))
1610 clist_append(newlist,
1611 sc_mailimap_set_item_copy(
1612 (struct mailimap_set_item *)clist_content(cur)));
1613 return mailimap_set_new(newlist);
1616 static void search_run(struct etpan_thread_op * op)
1618 struct search_param * param;
1619 struct search_result * result;
1621 struct mailimap_search_key * key = NULL;
1622 struct mailimap_search_key * uid_key = NULL;
1623 struct mailimap_search_key * search_type_key;
1624 clist * search_result;
1627 result = op->result;
1631 /* we copy the mailimap_set because freeing the key is recursive */
1632 if (param->set != NULL) {
1633 uid_key = mailimap_search_key_new_uid(sc_mailimap_set_copy(param->set));
1634 } else if (param->type == IMAP_SEARCH_TYPE_SIMPLE) {
1635 uid_key = mailimap_search_key_new_all();
1637 search_type_key = NULL;
1638 switch (param->type) {
1639 case IMAP_SEARCH_TYPE_SIMPLE:
1640 search_type_key = NULL;
1643 case IMAP_SEARCH_TYPE_SEEN:
1644 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_SEEN,
1645 NULL, NULL, NULL, NULL, NULL,
1646 NULL, NULL, NULL, NULL, NULL,
1647 NULL, NULL, NULL, NULL, 0,
1648 NULL, NULL, NULL, NULL, NULL,
1649 NULL, 0, NULL, NULL, NULL);
1652 case IMAP_SEARCH_TYPE_UNSEEN:
1653 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_UNSEEN,
1654 NULL, NULL, NULL, NULL, NULL,
1655 NULL, NULL, NULL, NULL, NULL,
1656 NULL, NULL, NULL, NULL, 0,
1657 NULL, NULL, NULL, NULL, NULL,
1658 NULL, 0, NULL, NULL, NULL);
1661 case IMAP_SEARCH_TYPE_ANSWERED:
1662 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_ANSWERED,
1663 NULL, NULL, NULL, NULL, NULL,
1664 NULL, NULL, NULL, NULL, NULL,
1665 NULL, NULL, NULL, NULL, 0,
1666 NULL, NULL, NULL, NULL, NULL,
1667 NULL, 0, NULL, NULL, NULL);
1670 case IMAP_SEARCH_TYPE_FLAGGED:
1671 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_FLAGGED,
1672 NULL, NULL, NULL, NULL, NULL,
1673 NULL, NULL, NULL, NULL, NULL,
1674 NULL, NULL, NULL, NULL, 0,
1675 NULL, NULL, NULL, NULL, NULL,
1676 NULL, 0, NULL, NULL, NULL);
1678 case IMAP_SEARCH_TYPE_DELETED:
1679 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_DELETED,
1680 NULL, NULL, NULL, NULL, NULL,
1681 NULL, NULL, NULL, NULL, NULL,
1682 NULL, NULL, NULL, NULL, 0,
1683 NULL, NULL, NULL, NULL, NULL,
1684 NULL, 0, NULL, NULL, NULL);
1686 case IMAP_SEARCH_TYPE_FORWARDED:
1687 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_KEYWORD,
1688 NULL, NULL, NULL, NULL, NULL,
1689 strdup(RTAG_FORWARDED), NULL, NULL, NULL, NULL,
1690 NULL, NULL, NULL, NULL, 0,
1691 NULL, NULL, NULL, NULL, NULL,
1692 NULL, 0, NULL, NULL, NULL);
1694 case IMAP_SEARCH_TYPE_SPAM:
1695 search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_KEYWORD,
1696 NULL, NULL, NULL, NULL, NULL,
1697 strdup(RTAG_JUNK), NULL, NULL, NULL, NULL,
1698 NULL, NULL, NULL, NULL, 0,
1699 NULL, NULL, NULL, NULL, NULL,
1700 NULL, 0, NULL, NULL, NULL);
1704 if (search_type_key != NULL) {
1705 if (param->set != NULL) {
1706 key = mailimap_search_key_new_multiple_empty();
1707 mailimap_search_key_multiple_add(key, search_type_key);
1708 mailimap_search_key_multiple_add(key, uid_key);
1710 key = search_type_key;
1712 } else if (uid_key != NULL) {
1717 g_warning("no key!");
1718 result = op->result;
1720 result->search_result = NULL;
1722 mailstream_logger = imap_logger_uid;
1724 r = mailimap_uid_search(param->imap, NULL, key, &search_result);
1726 mailstream_logger = imap_logger_cmd;
1728 /* free the key (with the imapset) */
1729 mailimap_search_key_free(key);
1732 result->search_result = search_result;
1734 debug_print("imap search run - end %i\n", result->error);
1737 int imap_threaded_search(Folder * folder, int search_type,
1738 struct mailimap_set * set, clist ** search_result)
1740 struct search_param param;
1741 struct search_result result;
1744 debug_print("imap search - begin\n");
1746 imap = get_imap(folder);
1749 param.type = search_type;
1751 threaded_run(folder, ¶m, &result, search_run);
1753 if (result.error != MAILIMAP_NO_ERROR)
1754 return result.error;
1756 debug_print("imap search - end\n");
1758 * search_result = result.search_result;
1760 return result.error;
1765 static int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
1769 struct mailimap_msg_att_dynamic ** patt_dyn);
1772 result_to_uid_list(clist * fetch_result, carray ** result)
1774 clistiter * cur = NULL;
1779 tab = carray_new(128);
1781 res = MAILIMAP_ERROR_MEMORY;
1786 cur = clist_begin(fetch_result);
1788 for(; cur != NULL ; cur = clist_next(cur)) {
1789 struct mailimap_msg_att * msg_att;
1793 msg_att = clist_content(cur);
1796 imap_get_msg_att_info(msg_att, &uid, NULL, NULL, NULL);
1798 puid = malloc(sizeof(* puid));
1800 res = MAILIMAP_ERROR_MEMORY;
1805 r = carray_add(tab, puid, NULL);
1808 res = MAILIMAP_ERROR_MEMORY;
1815 return MAILIMAP_NO_ERROR;
1818 imap_fetch_uid_list_free(tab);
1823 static int imap_get_messages_list(mailimap * imap,
1824 uint32_t first_index,
1829 struct mailimap_fetch_att * fetch_att;
1830 struct mailimap_fetch_type * fetch_type;
1831 struct mailimap_set * set;
1832 clist * fetch_result;
1835 set = mailimap_set_new_interval(first_index, 0);
1837 res = MAILIMAP_ERROR_MEMORY;
1841 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
1842 if (fetch_type == NULL) {
1843 res = MAILIMAP_ERROR_MEMORY;
1847 fetch_att = mailimap_fetch_att_new_uid();
1848 if (fetch_att == NULL) {
1849 res = MAILIMAP_ERROR_MEMORY;
1850 goto free_fetch_type;
1853 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
1854 if (r != MAILIMAP_NO_ERROR) {
1855 mailimap_fetch_att_free(fetch_att);
1856 res = MAILIMAP_ERROR_MEMORY;
1857 goto free_fetch_type;
1860 mailstream_logger = imap_logger_fetch;
1862 r = mailimap_uid_fetch(imap, set,
1863 fetch_type, &fetch_result);
1865 mailstream_logger = imap_logger_cmd;
1866 mailimap_fetch_type_free(fetch_type);
1867 mailimap_set_free(set);
1869 if (r != MAILIMAP_NO_ERROR) {
1875 r = result_to_uid_list(fetch_result, &env_list);
1876 mailimap_fetch_list_free(fetch_result);
1878 * result = env_list;
1880 return MAILIMAP_NO_ERROR;
1883 mailimap_fetch_type_free(fetch_type);
1885 mailimap_set_free(set);
1893 struct fetch_uid_param {
1895 uint32_t first_index;
1898 struct fetch_uid_result {
1900 carray * fetch_result;
1903 static void fetch_uid_run(struct etpan_thread_op * op)
1905 struct fetch_uid_param * param;
1906 struct fetch_uid_result * result;
1907 carray * fetch_result;
1911 result = op->result;
1915 fetch_result = NULL;
1916 mailstream_logger = imap_logger_noop;
1917 log_print(LOG_PROTOCOL, "IMAP4- [fetching UIDs...]\n");
1919 r = imap_get_messages_list(param->imap, param->first_index,
1922 mailstream_logger = imap_logger_cmd;
1925 result->fetch_result = fetch_result;
1926 debug_print("imap fetch_uid run - end %i\n", r);
1929 int imap_threaded_fetch_uid(Folder * folder, uint32_t first_index,
1930 carray ** fetch_result)
1932 struct fetch_uid_param param;
1933 struct fetch_uid_result result;
1936 debug_print("imap fetch_uid - begin\n");
1938 imap = get_imap(folder);
1940 param.first_index = first_index;
1942 threaded_run(folder, ¶m, &result, fetch_uid_run);
1944 if (result.error != MAILIMAP_NO_ERROR)
1945 return result.error;
1947 debug_print("imap fetch_uid - end\n");
1949 * fetch_result = result.fetch_result;
1951 return result.error;
1955 void imap_fetch_uid_list_free(carray * uid_list)
1959 for(i = 0 ; i < carray_count(uid_list) ; i ++) {
1962 puid = carray_get(uid_list, i);
1965 carray_free(uid_list);
1971 static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, GSList **tags);
1974 result_to_uid_flags_list(clist * fetch_result, carray ** result)
1976 clistiter * cur = NULL;
1980 GSList *tags = NULL;
1982 tab = carray_new(128);
1984 res = MAILIMAP_ERROR_MEMORY;
1989 cur = clist_begin(fetch_result);
1991 for(; cur != NULL ; cur = clist_next(cur)) {
1992 struct mailimap_msg_att * msg_att;
1995 struct mailimap_msg_att_dynamic * att_dyn;
2001 msg_att = clist_content(cur);
2005 imap_get_msg_att_info(msg_att, &uid, NULL, NULL, &att_dyn);
2008 if (att_dyn == NULL)
2011 flags = imap_flags_to_flags(att_dyn, &tags);
2013 puid = malloc(sizeof(* puid));
2015 res = MAILIMAP_ERROR_MEMORY;
2020 r = carray_add(tab, puid, NULL);
2023 res = MAILIMAP_ERROR_MEMORY;
2026 pflags = malloc(sizeof(* pflags));
2027 if (pflags == NULL) {
2028 res = MAILIMAP_ERROR_MEMORY;
2032 r = carray_add(tab, pflags, NULL);
2035 res = MAILIMAP_ERROR_MEMORY;
2038 r = carray_add(tab, tags, NULL);
2041 res = MAILIMAP_ERROR_MEMORY;
2048 return MAILIMAP_NO_ERROR;
2051 imap_fetch_uid_flags_list_free(tab);
2052 slist_free_strings(tags);
2058 static int imap_get_messages_flags_list(mailimap * imap,
2059 uint32_t first_index,
2064 struct mailimap_fetch_att * fetch_att;
2065 struct mailimap_fetch_type * fetch_type;
2066 struct mailimap_set * set;
2067 clist * fetch_result;
2070 set = mailimap_set_new_interval(first_index, 0);
2072 res = MAILIMAP_ERROR_MEMORY;
2076 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
2077 if (fetch_type == NULL) {
2078 res = MAILIMAP_ERROR_MEMORY;
2082 fetch_att = mailimap_fetch_att_new_flags();
2083 if (fetch_att == NULL) {
2084 res = MAILIMAP_ERROR_MEMORY;
2085 goto free_fetch_type;
2088 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2089 if (r != MAILIMAP_NO_ERROR) {
2090 mailimap_fetch_att_free(fetch_att);
2091 res = MAILIMAP_ERROR_MEMORY;
2092 goto free_fetch_type;
2095 fetch_att = mailimap_fetch_att_new_uid();
2096 if (fetch_att == NULL) {
2097 res = MAILIMAP_ERROR_MEMORY;
2098 goto free_fetch_type;
2101 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2102 if (r != MAILIMAP_NO_ERROR) {
2103 mailimap_fetch_att_free(fetch_att);
2104 res = MAILIMAP_ERROR_MEMORY;
2105 goto free_fetch_type;
2108 mailstream_logger = imap_logger_fetch;
2110 r = mailimap_uid_fetch(imap, set,
2111 fetch_type, &fetch_result);
2113 mailstream_logger = imap_logger_cmd;
2114 mailimap_fetch_type_free(fetch_type);
2115 mailimap_set_free(set);
2117 if (r != MAILIMAP_NO_ERROR) {
2123 r = result_to_uid_flags_list(fetch_result, &env_list);
2124 mailimap_fetch_list_free(fetch_result);
2126 * result = env_list;
2128 return MAILIMAP_NO_ERROR;
2131 mailimap_fetch_type_free(fetch_type);
2133 mailimap_set_free(set);
2140 static void fetch_uid_flags_run(struct etpan_thread_op * op)
2142 struct fetch_uid_param * param;
2143 struct fetch_uid_result * result;
2144 carray * fetch_result;
2148 result = op->result;
2152 fetch_result = NULL;
2153 r = imap_get_messages_flags_list(param->imap, param->first_index,
2157 result->fetch_result = fetch_result;
2158 debug_print("imap fetch_uid run - end %i\n", r);
2161 int imap_threaded_fetch_uid_flags(Folder * folder, uint32_t first_index,
2162 carray ** fetch_result)
2164 struct fetch_uid_param param;
2165 struct fetch_uid_result result;
2168 debug_print("imap fetch_uid - begin\n");
2170 imap = get_imap(folder);
2172 param.first_index = first_index;
2174 mailstream_logger = imap_logger_noop;
2175 log_print(LOG_PROTOCOL, "IMAP4- [fetching flags...]\n");
2177 threaded_run(folder, ¶m, &result, fetch_uid_flags_run);
2179 mailstream_logger = imap_logger_cmd;
2182 if (result.error != MAILIMAP_NO_ERROR)
2183 return result.error;
2185 debug_print("imap fetch_uid - end\n");
2187 * fetch_result = result.fetch_result;
2189 return result.error;
2193 void imap_fetch_uid_flags_list_free(carray * uid_flags_list)
2197 for(i = 0 ; i < carray_count(uid_flags_list) ; i += 3) {
2200 data = carray_get(uid_flags_list, i);
2202 data = carray_get(uid_flags_list, i + 1);
2205 carray_free(uid_flags_list);
2210 static int imap_fetch(mailimap * imap,
2213 size_t * result_len)
2216 struct mailimap_set * set;
2217 struct mailimap_fetch_att * fetch_att;
2218 struct mailimap_fetch_type * fetch_type;
2219 clist * fetch_result;
2220 struct mailimap_msg_att * msg_att;
2221 struct mailimap_msg_att_item * msg_att_item;
2226 struct mailimap_section * section;
2228 set = mailimap_set_new_single(msg_index);
2230 res = MAILIMAP_ERROR_MEMORY;
2234 section = mailimap_section_new(NULL);
2235 if (section == NULL) {
2236 res = MAILIMAP_ERROR_MEMORY;
2240 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
2241 if (fetch_att == NULL) {
2242 mailimap_section_free(section);
2243 res = MAILIMAP_ERROR_MEMORY;
2247 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
2248 if (fetch_type == NULL) {
2249 res = MAILIMAP_ERROR_MEMORY;
2250 goto free_fetch_att;
2253 mailstream_logger = imap_logger_fetch;
2255 r = mailimap_uid_fetch(imap, set,
2256 fetch_type, &fetch_result);
2258 mailstream_logger = imap_logger_cmd;
2260 mailimap_fetch_type_free(fetch_type);
2261 mailimap_set_free(set);
2264 case MAILIMAP_NO_ERROR:
2270 if (fetch_result == NULL || clist_begin(fetch_result) == NULL) {
2271 mailimap_fetch_list_free(fetch_result);
2272 return MAILIMAP_ERROR_FETCH;
2275 msg_att = clist_begin(fetch_result)->data;
2280 if (msg_att->att_list)
2281 cur = clist_begin(msg_att->att_list);
2285 for(; cur != NULL ; cur = clist_next(cur)) {
2286 msg_att_item = clist_content(cur);
2288 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
2289 if (msg_att_item->att_data.att_static->att_type ==
2290 MAILIMAP_MSG_ATT_BODY_SECTION) {
2291 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
2293 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
2295 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
2300 mailimap_fetch_list_free(fetch_result);
2303 return MAILIMAP_ERROR_FETCH;
2306 * result_len = text_length;
2308 return MAILIMAP_NO_ERROR;
2311 mailimap_fetch_att_free(fetch_att);
2313 mailimap_set_free(set);
2318 static int imap_fetch_header(mailimap * imap,
2321 size_t * result_len)
2324 struct mailimap_set * set;
2325 struct mailimap_fetch_att * fetch_att;
2326 struct mailimap_fetch_type * fetch_type;
2327 clist * fetch_result;
2328 struct mailimap_msg_att * msg_att;
2329 struct mailimap_msg_att_item * msg_att_item;
2334 struct mailimap_section * section;
2336 set = mailimap_set_new_single(msg_index);
2338 res = MAILIMAP_ERROR_MEMORY;
2342 section = mailimap_section_new_header();
2343 if (section == NULL) {
2344 res = MAILIMAP_ERROR_MEMORY;
2348 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
2349 if (fetch_att == NULL) {
2350 mailimap_section_free(section);
2351 res = MAILIMAP_ERROR_MEMORY;
2355 fetch_type = mailimap_fetch_type_new_fetch_att(fetch_att);
2356 if (fetch_type == NULL) {
2357 res = MAILIMAP_ERROR_MEMORY;
2358 goto free_fetch_att;
2361 mailstream_logger = imap_logger_fetch;
2363 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
2365 mailstream_logger = imap_logger_cmd;
2366 mailimap_fetch_type_free(fetch_type);
2367 mailimap_set_free(set);
2370 case MAILIMAP_NO_ERROR:
2376 if (fetch_result == NULL || clist_begin(fetch_result) == NULL) {
2377 mailimap_fetch_list_free(fetch_result);
2378 return MAILIMAP_ERROR_FETCH;
2381 msg_att = clist_begin(fetch_result)->data;
2386 if (msg_att->att_list)
2387 cur = clist_begin(msg_att->att_list);
2391 for(; cur != NULL ; cur = clist_next(cur)) {
2392 msg_att_item = clist_content(cur);
2394 if (msg_att_item->att_type == MAILIMAP_MSG_ATT_ITEM_STATIC) {
2395 if (msg_att_item->att_data.att_static->att_type ==
2396 MAILIMAP_MSG_ATT_BODY_SECTION) {
2397 text = msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part;
2398 msg_att_item->att_data.att_static->att_data.att_body_section->sec_body_part = NULL;
2400 msg_att_item->att_data.att_static->att_data.att_body_section->sec_length;
2405 mailimap_fetch_list_free(fetch_result);
2408 return MAILIMAP_ERROR_FETCH;
2411 * result_len = text_length;
2413 return MAILIMAP_NO_ERROR;
2416 mailimap_fetch_att_free(fetch_att);
2418 mailimap_set_free(set);
2425 struct fetch_content_param {
2428 const char * filename;
2432 struct fetch_content_result {
2436 static void fetch_content_run(struct etpan_thread_op * op)
2438 struct fetch_content_param * param;
2439 struct fetch_content_result * result;
2441 size_t content_size;
2447 result = op->result;
2453 if (param->with_body)
2454 r = imap_fetch(param->imap, param->msg_index,
2455 &content, &content_size);
2457 r = imap_fetch_header(param->imap, param->msg_index,
2458 &content, &content_size);
2462 if (r == MAILIMAP_NO_ERROR) {
2463 fd = g_open(param->filename, O_RDWR | O_CREAT, 0600);
2465 result->error = MAILIMAP_ERROR_FETCH;
2469 f = fdopen(fd, "wb");
2471 result->error = MAILIMAP_ERROR_FETCH;
2475 r = fwrite(content, 1, content_size, f);
2476 if (r < content_size) {
2477 result->error = MAILIMAP_ERROR_FETCH;
2483 result->error = MAILIMAP_ERROR_FETCH;
2494 claws_unlink(param->filename);
2497 /* mmap_string_unref is a simple free in libetpan
2498 * when it has MMAP_UNAVAILABLE defined */
2499 if (mmap_string_unref(content) != 0)
2503 debug_print("imap fetch_content run - end %i\n", result->error);
2506 int imap_threaded_fetch_content(Folder * folder, uint32_t msg_index,
2508 const char * filename)
2510 struct fetch_content_param param;
2511 struct fetch_content_result result;
2514 debug_print("imap fetch_content - begin\n");
2516 imap = get_imap(folder);
2518 param.msg_index = msg_index;
2519 param.filename = filename;
2520 param.with_body = with_body;
2522 threaded_run(folder, ¶m, &result, fetch_content_run);
2524 if (result.error != MAILIMAP_NO_ERROR)
2525 return result.error;
2527 debug_print("imap fetch_content - end\n");
2529 return result.error;
2534 static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, GSList **s_tags)
2539 GSList *tags = NULL;
2543 flag_list = att_dyn->att_list;
2544 if (flag_list == NULL)
2547 for(cur = clist_begin(flag_list) ; cur != NULL ;
2548 cur = clist_next(cur)) {
2549 struct mailimap_flag_fetch * flag_fetch;
2551 flag_fetch = clist_content(cur);
2552 if (flag_fetch->fl_type == MAILIMAP_FLAG_FETCH_RECENT)
2555 switch (flag_fetch->fl_flag->fl_type) {
2556 case MAILIMAP_FLAG_ANSWERED:
2557 flags |= MSG_REPLIED;
2559 case MAILIMAP_FLAG_FLAGGED:
2560 flags |= MSG_MARKED;
2562 case MAILIMAP_FLAG_DELETED:
2563 flags |= MSG_DELETED;
2565 case MAILIMAP_FLAG_SEEN:
2566 flags &= ~MSG_UNREAD;
2569 case MAILIMAP_FLAG_KEYWORD:
2570 if (!strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, RTAG_FORWARDED))
2571 flags |= MSG_FORWARDED;
2572 else if (!strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, RTAG_JUNK))
2574 else if (!strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, RTAG_NON_JUNK) ||
2575 !strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, RTAG_NO_JUNK) ||
2576 !strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, RTAG_NOT_JUNK))
2579 tags = g_slist_prepend(tags, g_strdup(flag_fetch->fl_flag->fl_data.fl_keyword));
2589 static int imap_get_msg_att_info(struct mailimap_msg_att * msg_att,
2593 struct mailimap_msg_att_dynamic ** patt_dyn)
2595 clistiter * item_cur;
2599 struct mailimap_msg_att_dynamic * att_dyn;
2606 if (msg_att->att_list)
2607 item_cur = clist_begin(msg_att->att_list);
2610 for(; item_cur != NULL ; item_cur = clist_next(item_cur)) {
2611 struct mailimap_msg_att_item * item;
2613 item = clist_content(item_cur);
2615 switch (item->att_type) {
2616 case MAILIMAP_MSG_ATT_ITEM_STATIC:
2617 switch (item->att_data.att_static->att_type) {
2618 case MAILIMAP_MSG_ATT_UID:
2619 uid = item->att_data.att_static->att_data.att_uid;
2622 case MAILIMAP_MSG_ATT_BODY_SECTION:
2623 if (headers == NULL) {
2624 headers = item->att_data.att_static->att_data.att_body_section->sec_body_part;
2627 case MAILIMAP_MSG_ATT_RFC822_SIZE:
2628 ref_size = item->att_data.att_static->att_data.att_rfc822_size;
2633 case MAILIMAP_MSG_ATT_ITEM_DYNAMIC:
2634 if (att_dyn == NULL) {
2635 att_dyn = item->att_data.att_dyn;
2643 if (pheaders != NULL)
2644 * pheaders = headers;
2645 if (pref_size != NULL)
2646 * pref_size = ref_size;
2647 if (patt_dyn != NULL)
2648 * patt_dyn = att_dyn;
2650 return MAIL_NO_ERROR;
2653 static struct imap_fetch_env_info *
2654 fetch_to_env_info(struct mailimap_msg_att * msg_att, GSList **tags)
2656 struct imap_fetch_env_info * info;
2660 struct mailimap_msg_att_dynamic * att_dyn;
2662 imap_get_msg_att_info(msg_att, &uid, &headers, &size,
2667 info = malloc(sizeof(* info));
2669 info->headers = strdup(headers);
2671 info->flags = imap_flags_to_flags(att_dyn, tags);
2677 imap_fetch_result_to_envelop_list(clist * fetch_result,
2678 carray ** p_env_list)
2685 env_list = carray_new(16);
2688 for(cur = clist_begin(fetch_result) ; cur != NULL ;
2689 cur = clist_next(cur)) {
2690 struct mailimap_msg_att * msg_att;
2691 struct imap_fetch_env_info * env_info;
2692 GSList *tags = NULL;
2694 msg_att = clist_content(cur);
2696 env_info = fetch_to_env_info(msg_att, &tags);
2698 return MAILIMAP_ERROR_MEMORY;
2699 carray_add(env_list, env_info, NULL);
2700 carray_add(env_list, tags, NULL);
2702 * p_env_list = env_list;
2704 * p_env_list = NULL;
2707 return MAIL_NO_ERROR;
2710 static int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type)
2712 struct mailimap_fetch_att * fetch_att;
2716 struct mailimap_header_list * imap_hdrlist;
2717 struct mailimap_section * section;
2719 hdrlist = clist_new();
2721 header = strdup("Date");
2722 r = clist_append(hdrlist, header);
2723 header = strdup("From");
2724 r = clist_append(hdrlist, header);
2725 header = strdup("To");
2726 r = clist_append(hdrlist, header);
2727 header = strdup("Cc");
2728 r = clist_append(hdrlist, header);
2729 header = strdup("Subject");
2730 r = clist_append(hdrlist, header);
2731 header = strdup("Message-ID");
2732 r = clist_append(hdrlist, header);
2733 header = strdup("References");
2734 r = clist_append(hdrlist, header);
2735 header = strdup("In-Reply-To");
2736 r = clist_append(hdrlist, header);
2738 imap_hdrlist = mailimap_header_list_new(hdrlist);
2739 section = mailimap_section_new_header_fields(imap_hdrlist);
2740 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
2741 mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2743 return MAIL_NO_ERROR;
2746 static int imap_add_header_fetch_att(struct mailimap_fetch_type * fetch_type)
2748 struct mailimap_fetch_att * fetch_att;
2749 struct mailimap_section * section;
2751 section = mailimap_section_new_header();
2752 fetch_att = mailimap_fetch_att_new_body_peek_section(section);
2753 mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2755 return MAIL_NO_ERROR;
2759 imap_get_envelopes_list(mailimap * imap, struct mailimap_set * set,
2760 carray ** p_env_list)
2762 struct mailimap_fetch_att * fetch_att;
2763 struct mailimap_fetch_type * fetch_type;
2765 clist * fetch_result;
2767 carray * env_list = NULL;
2771 fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
2774 fetch_att = mailimap_fetch_att_new_uid();
2775 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2778 fetch_att = mailimap_fetch_att_new_flags();
2779 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2782 fetch_att = mailimap_fetch_att_new_rfc822_size();
2783 r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
2787 key.len = sizeof(imap);
2788 r = chash_get(courier_workaround_hash, &key, &value);
2790 r = imap_add_envelope_fetch_att(fetch_type);
2792 r = imap_add_header_fetch_att(fetch_type);
2794 mailstream_logger = imap_logger_fetch;
2796 r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
2798 mailstream_logger = imap_logger_cmd;
2800 case MAILIMAP_NO_ERROR:
2803 mailimap_fetch_type_free(fetch_type);
2804 debug_print("uid_fetch: %d\n", r);
2808 if (fetch_result == NULL || clist_begin(fetch_result) == NULL) {
2809 res = MAILIMAP_ERROR_FETCH;
2810 debug_print("clist_begin = NULL\n");
2814 r = imap_fetch_result_to_envelop_list(fetch_result, &env_list);
2815 mailimap_fetch_list_free(fetch_result);
2817 if (r != MAILIMAP_NO_ERROR) {
2818 mailimap_fetch_type_free(fetch_type);
2819 res = MAILIMAP_ERROR_MEMORY;
2820 debug_print("fetch_result_to_envelop_list: %d\n", res);
2824 mailimap_fetch_type_free(fetch_type);
2826 * p_env_list = env_list;
2828 return MAILIMAP_NO_ERROR;
2834 struct fetch_env_param {
2836 struct mailimap_set * set;
2839 struct fetch_env_result {
2840 carray * fetch_env_result;
2844 static void fetch_env_run(struct etpan_thread_op * op)
2846 struct fetch_env_param * param;
2847 struct fetch_env_result * result;
2852 result = op->result;
2857 r = imap_get_envelopes_list(param->imap, param->set,
2861 result->fetch_env_result = env_list;
2863 debug_print("imap fetch_env run - end %i\n", r);
2866 int imap_threaded_fetch_env(Folder * folder, struct mailimap_set * set,
2867 carray ** p_env_list)
2869 struct fetch_env_param param;
2870 struct fetch_env_result result;
2873 debug_print("imap fetch_env - begin\n");
2875 imap = get_imap(folder);
2879 threaded_run(folder, ¶m, &result, fetch_env_run);
2881 if (result.error != MAILIMAP_NO_ERROR) {
2887 key.len = sizeof(imap);
2888 r = chash_get(courier_workaround_hash, &key, &value);
2892 chash_set(courier_workaround_hash, &key, &value, NULL);
2894 threaded_run(folder, ¶m, &result, fetch_env_run);
2898 if (result.error != MAILIMAP_NO_ERROR)
2899 return result.error;
2901 debug_print("imap fetch_env - end\n");
2903 * p_env_list = result.fetch_env_result;
2905 return result.error;
2908 void imap_fetch_env_free(carray * env_list)
2912 for(i = 0 ; i < carray_count(env_list) ; i += 2) {
2913 struct imap_fetch_env_info * env_info;
2915 env_info = carray_get(env_list, i);
2916 free(env_info->headers);
2919 carray_free(env_list);
2926 struct append_param {
2928 const char * mailbox;
2929 const char * filename;
2930 struct mailimap_flag_list * flag_list;
2933 struct append_result {
2938 static void append_run(struct etpan_thread_op * op)
2940 struct append_param * param;
2941 struct append_result * result;
2946 struct stat stat_buf;
2949 guint32 uid = 0, val = 0;
2952 result = op->result;
2957 r = stat(param->filename, &stat_buf);
2959 result->error = MAILIMAP_ERROR_APPEND;
2962 size = stat_buf.st_size;
2964 fd = g_open(param->filename, O_RDONLY, 0);
2966 result->error = MAILIMAP_ERROR_APPEND;
2970 data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
2971 if (data == (void *) MAP_FAILED) {
2973 result->error = MAILIMAP_ERROR_APPEND;
2977 data = file_read_to_str_no_recode(param->filename);
2979 result->error = MAILIMAP_ERROR_APPEND;
2982 size = strlen(data);
2984 mailstream_logger = imap_logger_append;
2986 r = mailimap_uidplus_append(param->imap, param->mailbox,
2987 param->flag_list, NULL,
2988 data, size, &val, &uid);
2990 mailstream_logger = imap_logger_cmd;
3001 debug_print("imap append run - end %i uid %d\n", r, uid);
3004 int imap_threaded_append(Folder * folder, const char * mailbox,
3005 const char * filename,
3006 struct mailimap_flag_list * flag_list,
3009 struct append_param param;
3010 struct append_result result;
3013 debug_print("imap append - begin\n");
3015 imap = get_imap(folder);
3017 param.mailbox = mailbox;
3018 param.filename = filename;
3019 param.flag_list = flag_list;
3021 threaded_run(folder, ¶m, &result, append_run);
3023 if (result.error != MAILIMAP_NO_ERROR)
3024 return result.error;
3026 debug_print("imap append - end\n");
3030 return result.error;
3036 struct expunge_param {
3040 struct expunge_result {
3044 static void expunge_run(struct etpan_thread_op * op)
3046 struct expunge_param * param;
3047 struct expunge_result * result;
3051 result = op->result;
3055 r = mailimap_expunge(param->imap);
3058 debug_print("imap expunge run - end %i\n", r);
3061 int imap_threaded_expunge(Folder * folder)
3063 struct expunge_param param;
3064 struct expunge_result result;
3066 debug_print("imap expunge - begin\n");
3068 param.imap = get_imap(folder);
3070 threaded_run(folder, ¶m, &result, expunge_run);
3072 debug_print("imap expunge - end\n");
3074 return result.error;
3080 struct mailimap_set * set;
3084 struct copy_result {
3086 struct mailimap_set *source;
3087 struct mailimap_set *dest;
3090 static void copy_run(struct etpan_thread_op * op)
3092 struct copy_param * param;
3093 struct copy_result * result;
3096 struct mailimap_set *source = NULL, *dest = NULL;
3099 result = op->result;
3103 r = mailimap_uidplus_uid_copy(param->imap, param->set, param->mb,
3104 &val, &source, &dest);
3108 result->source = source;
3109 result->dest = dest;
3111 result->source = NULL;
3112 result->dest = NULL;
3114 debug_print("imap copy run - end %i\n", r);
3117 int imap_threaded_copy(Folder * folder, struct mailimap_set * set,
3118 const char * mb, struct mailimap_set **source,
3119 struct mailimap_set **dest)
3121 struct copy_param param;
3122 struct copy_result result;
3125 debug_print("imap copy - begin\n");
3127 imap = get_imap(folder);
3132 threaded_run(folder, ¶m, &result, copy_run);
3136 if (result.error != MAILIMAP_NO_ERROR)
3137 return result.error;
3139 *source = result.source;
3140 *dest = result.dest;
3142 debug_print("imap copy - end\n");
3144 return result.error;
3149 struct store_param {
3151 struct mailimap_set * set;
3152 struct mailimap_store_att_flags * store_att_flags;
3155 struct store_result {
3159 static void store_run(struct etpan_thread_op * op)
3161 struct store_param * param;
3162 struct store_result * result;
3166 result = op->result;
3170 r = mailimap_uid_store(param->imap, param->set,
3171 param->store_att_flags);
3175 debug_print("imap store run - end %i\n", r);
3178 int imap_threaded_store(Folder * folder, struct mailimap_set * set,
3179 struct mailimap_store_att_flags * store_att_flags)
3181 struct store_param param;
3182 struct store_result result;
3185 debug_print("imap store - begin\n");
3187 imap = get_imap(folder);
3190 param.store_att_flags = store_att_flags;
3192 threaded_run(folder, ¶m, &result, store_run);
3194 if (result.error != MAILIMAP_NO_ERROR)
3195 return result.error;
3197 debug_print("imap store - end\n");
3199 return result.error;
3203 #define ENV_BUFFER_SIZE 512
3205 static void do_exec_command(int fd, const char * command,
3206 const char * servername, uint16_t port)
3210 char env_buffer[ENV_BUFFER_SIZE];
3214 /* Fork again to become a child of init rather than
3215 the etpan client. */
3220 g_setenv("ETPANSERVER", servername, TRUE);
3222 g_unsetenv("ETPANSERVER");
3227 snprintf(porttext, sizeof(porttext), "%d", port);
3228 g_setenv("ETPANPORT", porttext, TRUE);
3231 g_unsetenv("ETPANPORT");
3234 /* Not a lot we can do if there's an error other than bail. */
3235 if (dup2(fd, 0) == -1)
3237 if (dup2(fd, 1) == -1)
3240 /* Should we close stderr and reopen /dev/null? */
3242 maxopen = sysconf(_SC_OPEN_MAX);
3243 for (i=3; i < maxopen; i++)
3247 /* Detach from the controlling tty if we have one. Otherwise,
3248 SSH might do something stupid like trying to use it instead
3249 of running $SSH_ASKPASS. Doh. */
3250 fd = g_open("/dev/tty", O_RDONLY, 0);
3252 ioctl(fd, TIOCNOTTY, NULL);
3255 #endif /* TIOCNOTTY */
3257 execl("/bin/sh", "/bin/sh", "-c", command, NULL);
3259 /* Eep. Shouldn't reach this */
3263 static int subcommand_connect(const char *command,
3264 const char *servername, uint16_t port)
3266 /* SEB unsupported on Windows */
3270 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds))
3275 do_exec_command(sockfds[1], command, servername, port);
3277 else if (childpid == -1) {
3285 /* Reap child, leaving grandchild process to run */
3286 waitpid(childpid, NULL, 0);
3291 static int socket_connect_cmd(mailimap * imap, const char * command,
3292 const char * server, int port)
3298 fd = subcommand_connect(command, server, port);
3300 return MAILIMAP_ERROR_STREAM;
3302 s = mailstream_socket_open(fd);
3305 return MAILIMAP_ERROR_STREAM;
3308 r = mailimap_connect(imap, s);
3309 if (r != MAILIMAP_NO_ERROR_AUTHENTICATED
3310 && r != MAILIMAP_NO_ERROR_NON_AUTHENTICATED) {
3311 mailstream_close(s);
3313 imap->imap_stream = NULL;
3322 struct connect_cmd_param {
3324 const char * command;
3325 const char * server;
3329 struct connect_cmd_result {
3333 static void connect_cmd_run(struct etpan_thread_op * op)
3336 struct connect_cmd_param * param;
3337 struct connect_cmd_result * result;
3340 result = op->result;
3344 r = socket_connect_cmd(param->imap, param->command,
3345 param->server, param->port);
3351 int imap_threaded_connect_cmd(Folder * folder, const char * command,
3352 const char * server, int port)
3354 struct connect_cmd_param param;
3355 struct connect_cmd_result result;
3358 mailimap * imap, * oldimap;
3360 oldimap = get_imap(folder);
3362 imap = mailimap_new(0, NULL);
3365 debug_print("deleting old imap %p\n", oldimap);
3366 delete_imap(folder, oldimap);
3370 key.len = sizeof(folder);
3373 chash_set(session_hash, &key, &value, NULL);
3376 param.command = command;
3377 param.server = server;
3380 threaded_run(folder, ¶m, &result, connect_cmd_run);
3382 debug_print("connect_cmd ok %i with imap %p\n", result.error, imap);
3384 return result.error;
3386 #endif /* G_OS_WIN32 */
3388 void imap_threaded_cancel(Folder * folder)
3392 imap = get_imap(folder);
3393 if (imap->imap_stream != NULL)
3394 mailstream_cancel(imap->imap_stream);
3399 void imap_main_init(void)
3402 void imap_main_done(gboolean have_connectivity)
3405 void imap_main_set_timeout(int sec)
3409 void imap_threaded_cancel(Folder * folder);