2005-07-18 [colin] 1.9.12cvs78
[claws.git] / src / etpan / imap-thread.c
index 1054bf4b4e85a1ecdadf62ec1e86fd109e362aeb..71e0da9ca5340d0619fe2806528318a40d151329 100644 (file)
@@ -5,7 +5,7 @@
 #ifdef HAVE_LIBETPAN
 
 #include "imap-thread.h"
-
+#include <imap.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <sys/wait.h>
 
 #include <gtk/gtk.h>
+#include <log.h>
 #include "etpan-thread-manager.h"
+#include "utils.h"
+
+#define DISABLE_LOG_DURING_LOGIN
 
 static struct etpan_thread_manager * thread_manager = NULL;
+static chash * courier_workaround_hash = NULL;
 static chash * imap_hash = NULL;
 static chash * session_hash = NULL;
 static guint thread_manager_signal = 0;
@@ -31,6 +36,25 @@ static gboolean thread_manager_event(GIOChannel * source,
        return TRUE;
 }
 
+void imap_logger(int direction, const char * str, size_t size) 
+{
+       gchar buf[512];
+       strncpy(buf, str, 511);
+       buf[511] = '\0';
+       if (size < 511)
+               buf[size] = '\0';
+       if (!strncmp(buf, "<<<<<<<", 7) 
+       ||  !strncmp(buf, ">>>>>>>", 7) 
+       ||  buf[0] == '\r' ||  buf[0] == '\n')
+               return;
+
+       while (strstr(buf, "\r"))
+               *strstr(buf, "\r") = ' ';
+       while (strstr(buf, "\n"))
+               *strstr(buf, "\n") = ' ';
+
+       log_print("IMAP4%c %s\n", direction?'>':'<', buf);
+}
 
 #define ETPAN_DEFAULT_NETWORK_TIMEOUT 60
 
@@ -40,12 +64,13 @@ void imap_main_init(void)
        
        mailstream_network_delay.tv_sec = ETPAN_DEFAULT_NETWORK_TIMEOUT;
        mailstream_network_delay.tv_usec = 0;
-
-#if 0
+       
        mailstream_debug = 1;
-#endif
+       mailstream_logger = imap_logger;
+
        imap_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
        session_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
+       courier_workaround_hash = chash_new(CHASH_COPYKEY, CHASH_DEFAULTSIZE);
        
        thread_manager = etpan_thread_manager_new();
        
@@ -75,6 +100,7 @@ void imap_main_done(void)
        
        etpan_thread_manager_free(thread_manager);
        
+       chash_free(courier_workaround_hash);
        chash_free(session_hash);
        chash_free(imap_hash);
 }
@@ -171,6 +197,8 @@ static void threaded_run(Folder * folder, void * param, void * result,
        struct etpan_thread * thread;
        int finished;
        
+       imap_folder_ref(folder);
+
        op = etpan_thread_op_new();
        op->param = param;
        op->result = result;
@@ -191,6 +219,8 @@ static void threaded_run(Folder * folder, void * param, void * result,
        }
        
        etpan_thread_op_free(op);
+
+       imap_folder_unref(folder);
 }
 
 
@@ -338,6 +368,10 @@ void imap_threaded_disconnect(Folder * folder)
        value.len = 0;
        chash_delete(session_hash, &key, NULL);
        
+       key.data = &imap;
+       key.len = sizeof(imap);
+       chash_delete(courier_workaround_hash, &key, NULL);
+       
        mailimap_free(imap);
        
        debug_print("disconnect ok\n");
@@ -412,11 +446,24 @@ static void login_run(struct etpan_thread_op * op)
        struct login_param * param;
        struct login_result * result;
        int r;
+#ifdef DISABLE_LOG_DURING_LOGIN
+       int old_debug;
+#endif
        
        param = op->param;
+       
+#ifdef DISABLE_LOG_DURING_LOGIN
+       old_debug = mailstream_debug;
+       mailstream_debug = 0;
+#endif
+       
        r = mailimap_login(param->imap,
                           param->login, param->password);
        
+#ifdef DISABLE_LOG_DURING_LOGIN
+       mailstream_debug = old_debug;
+#endif
+       
        result = op->result;
        result->error = r;
        debug_print("imap login run - end %i\n", r);
@@ -574,6 +621,29 @@ static void starttls_run(struct etpan_thread_op * op)
        result = op->result;
        result->error = r;
        debug_print("imap starttls run - end %i\n", r);
+       
+       if (r == 0) {
+               mailimap *imap = param->imap;
+               mailstream_low *plain_low = NULL;
+               mailstream_low *tls_low = NULL;
+               int fd = -1;
+               
+               plain_low = mailstream_get_low(imap->imap_stream);
+               fd = mailstream_low_get_fd(plain_low);
+               if (fd == -1) {
+                       debug_print("imap starttls run - can't get fd\n");
+                       result->error = MAIL_ERROR_STREAM;
+                       return;
+               }
+               tls_low = mailstream_low_ssl_open(fd);
+               if (tls_low == NULL) {
+                       debug_print("imap starttls run - can't ssl_open\n");
+                       result->error = MAIL_ERROR_STREAM;
+                       return;
+               }
+               mailstream_low_free(plain_low);
+               mailstream_set_low(imap->imap_stream, tls_low);
+       }
 }
 
 int imap_threaded_starttls(Folder * folder)
@@ -1110,6 +1180,7 @@ static void fetch_uid_run(struct etpan_thread_op * op)
        
        param = op->param;
        
+       fetch_result = NULL;
        r = imap_get_messages_list(param->imap, param->first_index,
                                   &fetch_result);
        
@@ -1651,6 +1722,18 @@ int imap_add_envelope_fetch_att(struct mailimap_fetch_type * fetch_type)
        return MAIL_NO_ERROR;
 }
 
+int imap_add_header_fetch_att(struct mailimap_fetch_type * fetch_type)
+{
+       struct mailimap_fetch_att * fetch_att;
+       struct mailimap_section * section;
+       
+       section = mailimap_section_new_header();
+       fetch_att = mailimap_fetch_att_new_body_peek_section(section);
+       mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
+       
+       return MAIL_NO_ERROR;
+}
+
 static int
 imap_get_envelopes_list(mailimap * imap, struct mailimap_set * set,
                        carray ** p_env_list)
@@ -1661,6 +1744,8 @@ imap_get_envelopes_list(mailimap * imap, struct mailimap_set * set,
        clist * fetch_result;
        int r;
        carray * env_list;
+       chashdatum key;
+       chashdatum value;
        
        fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
   
@@ -1677,7 +1762,13 @@ imap_get_envelopes_list(mailimap * imap, struct mailimap_set * set,
        r = mailimap_fetch_type_new_fetch_att_list_add(fetch_type, fetch_att);
   
        /* headers */
-       r = imap_add_envelope_fetch_att(fetch_type);
+       key.data = &imap;
+       key.len = sizeof(imap);
+       r = chash_get(courier_workaround_hash, &key, &value);
+       if (r < 0)
+               r = imap_add_envelope_fetch_att(fetch_type);
+       else
+               r = imap_add_header_fetch_att(fetch_type);
        
        r = mailimap_uid_fetch(imap, set, fetch_type, &fetch_result);
        
@@ -1732,6 +1823,7 @@ static void fetch_env_run(struct etpan_thread_op * op)
        
        param = op->param;
        
+       env_list = NULL;
        r = imap_get_envelopes_list(param->imap, param->set,
                                    &env_list);
        
@@ -1757,6 +1849,23 @@ int imap_threaded_fetch_env(Folder * folder, struct mailimap_set * set,
        
        threaded_run(folder, &param, &result, fetch_env_run);
        
+       if (result.error != MAILIMAP_NO_ERROR) {
+               chashdatum key;
+               chashdatum value;
+               int r;
+               
+               key.data = &imap;
+               key.len = sizeof(imap);
+               r = chash_get(courier_workaround_hash, &key, &value);
+               if (r < 0) {
+                       value.data = NULL;
+                       value.len = 0;
+                       chash_set(courier_workaround_hash, &key, &value, NULL);
+                       
+                       threaded_run(folder, &param, &result, fetch_env_run);
+               }
+       }
+       
        if (result.error != MAILIMAP_NO_ERROR)
                return result.error;