#ifdef HAVE_LIBETPAN
#include "imap-thread.h"
-
+#include <imap.h>
#include <sys/types.h>
#include <sys/stat.h>
+#if (defined (__NetBSD__) || defined (__FreeBSD__))
+#include <sys/socket.h>
+#endif
#include <fcntl.h>
#include <sys/mman.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;
return TRUE;
}
+void imap_logger(int direction, const char * str, size_t size)
+{
+ gchar buf[512];
+ strncpy(buf, str, size > 510 ? 510:size);
+ 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
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();
etpan_thread_manager_free(thread_manager);
+ chash_free(courier_workaround_hash);
chash_free(session_hash);
chash_free(imap_hash);
}
struct etpan_thread * thread;
int finished;
+ imap_folder_ref(folder);
+
op = etpan_thread_op_new();
op->param = param;
op->result = result;
}
etpan_thread_op_free(op);
+
+ imap_folder_unref(folder);
}
threaded_run(folder, ¶m, &result, connect_ssl_run);
- debug_print("connect ok\n");
+ debug_print("connect %d\n", result.error);
return result.error;
}
+
+struct capa_param {
+ mailimap * imap;
+};
+
+struct capa_result {
+ int error;
+ struct mailimap_capability_data *caps;
+};
+
+static void capability_run(struct etpan_thread_op * op)
+{
+ int r;
+ struct capa_param * param;
+ struct capa_result * result;
+ struct mailimap_capability_data *caps;
+
+ param = op->param;
+ result = op->result;
+
+ r = mailimap_capability(param->imap, &caps);
+
+ result->error = r;
+ result->caps = (r == 0 ? caps : NULL);
+}
+
+
+struct mailimap_capability_data * imap_threaded_capability(Folder *folder)
+{
+ struct capa_param param;
+ struct capa_result result;
+ mailimap *imap;
+
+ imap = get_imap(folder);
+
+ param.imap = imap;
+
+ threaded_run(folder, ¶m, &result, capability_run);
+
+ debug_print("capa ok\n");
+
+ return result.caps;
+
+}
struct disconnect_param {
mailimap * imap;
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");
mailimap * imap;
const char * login;
const char * password;
+ const char * type;
};
struct login_result {
struct login_param * param;
struct login_result * result;
int r;
+#ifdef DISABLE_LOG_DURING_LOGIN
+ int old_debug;
+#endif
param = op->param;
- r = mailimap_login(param->imap,
+
+#ifdef DISABLE_LOG_DURING_LOGIN
+ old_debug = mailstream_debug;
+ mailstream_debug = 0;
+#endif
+ if (!strcmp(param->type, "LOGIN"))
+ r = mailimap_login(param->imap,
param->login, param->password);
+ else
+ r = mailimap_authenticate(param->imap,
+ param->type, NULL, NULL, NULL,
+ param->login, param->login,
+ param->password, NULL);
+#ifdef DISABLE_LOG_DURING_LOGIN
+ mailstream_debug = old_debug;
+#endif
result = op->result;
result->error = r;
}
int imap_threaded_login(Folder * folder,
- const char * login, const char * password)
+ const char * login, const char * password,
+ const char * type)
{
struct login_param param;
struct login_result result;
param.imap = get_imap(folder);
param.login = login;
param.password = password;
-
+ param.type = type;
+
threaded_run(folder, ¶m, &result, login_run);
debug_print("imap login - end\n");
}
int imap_threaded_status(Folder * folder, const char * mb,
- struct mailimap_mailbox_data_status ** data_status)
+ struct mailimap_mailbox_data_status ** data_status,
+ guint mask)
{
struct status_param param;
struct status_result result;
debug_print("imap status - begin\n");
status_att_list = mailimap_status_att_list_new_empty();
- mailimap_status_att_list_add(status_att_list,
+ if (mask & 1 << 0) {
+ mailimap_status_att_list_add(status_att_list,
MAILIMAP_STATUS_ATT_MESSAGES);
- mailimap_status_att_list_add(status_att_list,
+ }
+ if (mask & 1 << 1) {
+ mailimap_status_att_list_add(status_att_list,
MAILIMAP_STATUS_ATT_RECENT);
- mailimap_status_att_list_add(status_att_list,
+ }
+ if (mask & 1 << 2) {
+ mailimap_status_att_list_add(status_att_list,
MAILIMAP_STATUS_ATT_UIDNEXT);
- mailimap_status_att_list_add(status_att_list,
+ }
+ if (mask & 1 << 3) {
+ mailimap_status_att_list_add(status_att_list,
MAILIMAP_STATUS_ATT_UIDVALIDITY);
- mailimap_status_att_list_add(status_att_list,
+ }
+ if (mask & 1 << 4) {
+ mailimap_status_att_list_add(status_att_list,
MAILIMAP_STATUS_ATT_UNSEEN);
-
+ }
param.imap = get_imap(folder);
param.mb = mb;
param.status_att_list = status_att_list;
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 = MAILIMAP_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 = MAILIMAP_ERROR_STREAM;
+ return;
+ }
+ mailstream_low_free(plain_low);
+ mailstream_set_low(imap->imap_stream, tls_low);
+ }
}
int imap_threaded_starttls(Folder * folder)
NULL, NULL, NULL, NULL, NULL,
NULL, 0, NULL, NULL, NULL);
break;
+ case IMAP_SEARCH_TYPE_DELETED:
+ search_type_key = mailimap_search_key_new(MAILIMAP_SEARCH_KEY_DELETED,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, 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) {
mailimap * imap;
debug_print("imap search - begin\n");
-
+
imap = get_imap(folder);
param.imap = imap;
param.set = set;
param = op->param;
+ fetch_result = NULL;
r = imap_get_messages_list(param->imap, param->first_index,
&fetch_result);
r = fclose(f);
if (r == EOF) {
- unlink(param->filename);
+ g_unlink(param->filename);
goto close;
}
goto free;
close:
close(fd);
unlink:
- unlink(param->filename);
+ g_unlink(param->filename);
free:
if (mmap_string_unref(content) != 0)
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)
clist * fetch_result;
int r;
carray * env_list;
+ chashdatum key;
+ chashdatum value;
fetch_type = mailimap_fetch_type_new_fetch_att_list_empty();
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);
param = op->param;
+ env_list = NULL;
r = imap_get_envelopes_list(param->imap, param->set,
&env_list);
threaded_run(folder, ¶m, &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, ¶m, &result, fetch_env_run);
+ }
+ }
+
if (result.error != MAILIMAP_NO_ERROR)
return result.error;
}
+#define ENV_BUFFER_SIZE 512
static void do_exec_command(int fd, const char * command,
const char * servername, uint16_t port)
{
int i, maxopen;
-
+#ifdef SOLARIS
+ char env_buffer[ENV_BUFFER_SIZE];
+#endif
+
if (fork() > 0) {
/* Fork again to become a child of init rather than
the etpan client. */
exit(0);
}
+#ifdef SOLARIS
+ if (servername)
+ snprintf(env_buffer, ENV_BUFFER_SIZE,
+ "ETPANSERVER=%s", servername);
+ else
+ snprintf(env_buffer, ENV_BUFFER_SIZE, "ETPANSERVER=");
+ putenv(env_buffer);
+#else
if (servername)
setenv("ETPANSERVER", servername, 1);
else
unsetenv("ETPANSERVER");
+#endif
+#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);
}
else {
unsetenv("ETPANPORT");
}
-
+#endif
+
/* Not a lot we can do if there's an error other than bail. */
if (dup2(fd, 0) == -1)
exit(1);