2008-09-01 [colin] 3.5.0cvs88
[claws.git] / src / etpan / imap-thread.c
index 7596b3e33f279fd94a4c36a96b95991ad61c195a..30f3a6014ae3a2e924c5157da02ba2b8af160f81 100644 (file)
@@ -40,6 +40,7 @@
 #include "etpan-thread-manager.h"
 #include "utils.h"
 #include "mainwindow.h"
+#include "ssl.h"
 #include "ssl_certificate.h"
 #include "socket.h"
 #include "remotefolder.h"
@@ -287,6 +288,7 @@ void imap_main_set_timeout(int sec)
 
 void imap_main_done(void)
 {
+       imap_disconnect_all();
        etpan_thread_manager_stop(thread_manager);
 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
        return;
@@ -437,6 +439,7 @@ static void threaded_run(Folder * folder, void * param, void * result,
 
 struct connect_param {
        mailimap * imap;
+       PrefsAccount *account;
        const char * server;
        int port;
 };
@@ -556,6 +559,60 @@ static int etpan_certificate_check(const unsigned char *certificate, int len, vo
        return 0;
 }
 
+static void connect_ssl_context_cb(struct mailstream_ssl_context * ssl_context, void * data)
+{
+#if (defined(USE_OPENSSL) || defined(USE_GNUTLS))
+       PrefsAccount *account = (PrefsAccount *)data;
+       const gchar *cert_path = NULL;
+       const gchar *password = NULL;
+#ifdef USE_OPENSSL
+       X509 *x509 = NULL;
+       EVP_PKEY *pkey = NULL;
+#else
+       gnutls_x509_crt x509 = NULL;
+       gnutls_x509_privkey pkey = NULL;
+#endif
+
+       if (account->in_ssl_client_cert_file && *account->in_ssl_client_cert_file)
+               cert_path = account->in_ssl_client_cert_file;
+       if (account->in_ssl_client_cert_pass && *account->in_ssl_client_cert_pass)
+               password = account->in_ssl_client_cert_pass;
+       
+       if (mailstream_ssl_set_client_certificate_data(ssl_context, NULL, 0) < 0 ||
+           mailstream_ssl_set_client_private_key_data(ssl_context, NULL, 0) < 0)
+               debug_print("Impossible to set the client certificate.\n");
+       x509 = ssl_certificate_get_x509_from_pem_file(cert_path);
+       pkey = ssl_certificate_get_pkey_from_pem_file(cert_path);
+       if (!(x509 && pkey)) {
+               /* try pkcs12 format */
+               ssl_certificate_get_x509_and_pkey_from_p12_file(cert_path, password, &x509, &pkey);
+       }
+       if (x509 && pkey) {
+               unsigned char *x509_der = NULL, *pkey_der = NULL;
+               size_t x509_len, pkey_len;
+               
+#ifndef USE_GNUTLS
+               x509_len = (size_t)i2d_X509(x509, &x509_der);
+               pkey_len = (size_t)i2d_PrivateKey(pkey, &pkey_der);
+#else
+               x509_len = (size_t)gnutls_i2d_X509(x509, &x509_der);
+               pkey_len = (size_t)gnutls_i2d_PrivateKey(pkey, &pkey_der);
+#endif
+               if (x509_len > 0 && pkey_len > 0) {
+                       if (mailstream_ssl_set_client_certificate_data(ssl_context, x509_der, x509_len) < 0 ||
+                           mailstream_ssl_set_client_private_key_data(ssl_context, pkey_der, pkey_len) < 0) 
+                               log_error(LOG_PROTOCOL, "Impossible to set the client certificate.\n");
+                       g_free(x509_der);
+                       g_free(pkey_der);
+               }
+#ifdef USE_GNUTLS
+               gnutls_x509_crt_deinit(x509);
+               gnutls_x509_privkey_deinit(pkey);
+#endif
+       }
+#endif
+}
+
 static void connect_ssl_run(struct etpan_thread_op * op)
 {
        int r;
@@ -567,8 +624,9 @@ static void connect_ssl_run(struct etpan_thread_op * op)
        
        CHECK_IMAP();
 
-       r = mailimap_ssl_connect(param->imap,
-                                param->server, param->port);
+       r = mailimap_ssl_connect_with_callback(param->imap,
+                                               param->server, param->port,
+                                               connect_ssl_context_cb, param->account);
        result->error = r;
 }
 
@@ -600,7 +658,8 @@ int imap_threaded_connect_ssl(Folder * folder, const char * server, int port)
        param.imap = imap;
        param.server = server;
        param.port = port;
-       
+       param.account = folder->account;
+
        refresh_resolvers();
        threaded_run(folder, &param, &result, connect_ssl_run);
 
@@ -1118,7 +1177,7 @@ static void starttls_run(struct etpan_thread_op * op)
                        return;
                }
 
-               tls_low = mailstream_low_tls_open(fd);
+               tls_low = mailstream_low_tls_open_with_callback(fd, connect_ssl_context_cb, param->account);
                if (tls_low == NULL) {
                        debug_print("imap starttls run - can't tls_open\n");
                        result->error = MAILIMAP_ERROR_STREAM;
@@ -1141,7 +1200,8 @@ int imap_threaded_starttls(Folder * folder, const gchar *host, int port)
        param.imap = get_imap(folder);
        param.server = host;
        param.port = port;
-       
+       param.account = folder->account;
+
        threaded_run(folder, &param, &result, starttls_run);
        
        debug_print("imap starttls - end\n");
@@ -1386,6 +1446,12 @@ int imap_threaded_select(Folder * folder, const char * mb,
                                case MAILIMAP_FLAG_KEYWORD:
                                        if (!strcasecmp(flag->fl_flag->fl_data.fl_keyword, "$Forwarded"))
                                                c_flag = IMAP_FLAG_FORWARDED;
+                                       if (!strcasecmp(flag->fl_flag->fl_data.fl_keyword, "Junk"))
+                                               c_flag = IMAP_FLAG_SPAM;
+                                       if (!strcasecmp(flag->fl_flag->fl_data.fl_keyword, "NonJunk") ||
+                                           !strcasecmp(flag->fl_flag->fl_data.fl_keyword, "NoJunk") ||
+                                           !strcasecmp(flag->fl_flag->fl_data.fl_keyword, "NotJunk"))
+                                               c_flag = IMAP_FLAG_HAM;
                                        break;
                                default:
                                        break;
@@ -1612,6 +1678,14 @@ static void search_run(struct etpan_thread_op * op)
                                                          NULL, NULL, NULL, NULL, NULL,
                                                          NULL, 0, NULL, NULL, NULL);
                break;
+       case IMAP_SEARCH_TYPE_SPAM:
+               search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_KEYWORD,
+                                                         NULL, NULL, NULL, NULL, NULL,
+                                                         strdup("Junk"), NULL, NULL, NULL, NULL,
+                                                         NULL, NULL, NULL, NULL, 0,
+                                                         NULL, NULL, NULL, NULL, NULL,
+                                                         NULL, 0, NULL, NULL, NULL);
+               break;
        }
        
        if (search_type_key != NULL) {
@@ -2392,7 +2466,7 @@ static void fetch_content_run(struct etpan_thread_op * op)
        close:
                close(fd);
        unlink:
-               g_unlink(param->filename);
+               claws_unlink(param->filename);
        
        free:
                /* mmap_string_unref is a simple free in libetpan
@@ -2470,6 +2544,12 @@ static int imap_flags_to_flags(struct mailimap_msg_att_dynamic * att_dyn, GSList
                        case MAILIMAP_FLAG_KEYWORD:
                                if (!strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "$Forwarded"))
                                        flags |= MSG_FORWARDED;
+                               else if (!strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "Junk")) 
+                                       flags |= MSG_SPAM;
+                               else if (!strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "NonJunk") ||
+                                        !strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "NoJunk") ||
+                                        !strcasecmp(flag_fetch->fl_flag->fl_data.fl_keyword, "NotJunk")) 
+                                       flags &= ~MSG_SPAM;
                                else if (s_tags)
                                        tags = g_slist_prepend(tags, g_strdup(flag_fetch->fl_flag->fl_data.fl_keyword));
                                break;
@@ -3105,37 +3185,20 @@ static void do_exec_command(int fd, const char * command,
                exit(0);
        }
   
-#ifdef SOLARIS
        if (servername)
-               snprintf(env_buffer, ENV_BUFFER_SIZE,
-                        "ETPANSERVER=%s", servername);
+               g_setenv("ETPANSERVER", servername, TRUE);
        else
-               snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANSERVER=");
-       putenv(env_buffer);
-#else
-       if (servername)
-               setenv("ETPANSERVER", servername, 1);
-       else
-               unsetenv("ETPANSERVER");
-#endif
+               g_unsetenv("ETPANSERVER");
   
-#ifdef SOLARIS
-       if (port)
-               snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANPORT=%d", port);
-       else
-               snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANPORT=");
-       putenv(env_buffer);
-#else
        if (port) {
                char porttext[20];
                
                snprintf(porttext, sizeof(porttext), "%d", port);
-               setenv("ETPANPORT", porttext, 1);
+               g_setenv("ETPANPORT", porttext, TRUE);
        }
        else {
-               unsetenv("ETPANPORT");
+               g_unsetenv("ETPANPORT");
        }
-#endif
                
        /* Not a lot we can do if there's an error other than bail. */
        if (dup2(fd, 0) == -1)