Skip to content

Instantly share code, notes, and snippets.

@mrvdb
Created December 20, 2012 13:24
Show Gist options
  • Save mrvdb/4345314 to your computer and use it in GitHub Desktop.
Save mrvdb/4345314 to your computer and use it in GitHub Desktop.
Index: src/compose.c
===================================================================
RCS file: /home/claws-mail/claws/src/compose.c,v
retrieving revision 1.382.2.560
diff -u -r1.382.2.560 compose.c
--- src/compose.c 20 Sep 2010 14:05:40 -0000 1.382.2.560
+++ src/compose.c 19 Nov 2010 21:34:00 -0000
@@ -5034,6 +5034,16 @@
inc_unlock();
toolbar_main_set_sensitive(mainwin);
main_window_set_menu_sensitive(mainwin);
+ /*
+ * IMAP IDLE loose ability to receive status messages from server
+ * therefore we do a folderview_check_new if folder is an IMAP
+ * folder and IMAP IDLE is active since calling folderview_check_new
+ * reenables the ability to receive status messages from server again
+ */
+ if (FOLDER_TYPE(folder->folder) == F_IMAP &&
+ folder->folder->account->use_imap_idle)
+ folderview_check_new(folder->folder);
+
return 0;
bail:
Index: src/folder.c
===================================================================
RCS file: /home/claws-mail/claws/src/folder.c,v
retrieving revision 1.213.2.197
diff -u -r1.213.2.197 folder.c
--- src/folder.c 3 Oct 2010 11:46:24 -0000 1.213.2.197
+++ src/folder.c 19 Nov 2010 21:34:00 -0000
@@ -205,6 +205,12 @@
folder->draft = NULL;
folder->queue = NULL;
folder->trash = NULL;
+ /* imap idle */
+ folder->idle_active = FALSE;
+ folder->cb_active = FALSE;
+ folder->ioc = NULL;
+ folder->ioc_id = 0;
+ folder->timer_id = 0;
}
static void reset_parent_type(FolderItem *item, gpointer data) {
Index: src/folder.h
===================================================================
RCS file: /home/claws-mail/claws/src/folder.h,v
retrieving revision 1.87.2.62
diff -u -r1.87.2.62 folder.h
--- src/folder.h 3 Oct 2010 11:46:24 -0000 1.87.2.62
+++ src/folder.h 19 Nov 2010 21:34:01 -0000
@@ -158,6 +158,13 @@
gpointer data;
GHashTable *newsart;
+
+ /* imap idle */
+ gboolean idle_active;
+ gboolean cb_active;
+ GIOChannel* ioc;
+ guint ioc_id;
+ guint timer_id;
};
struct _FolderClass
Index: src/imap.c
===================================================================
RCS file: /home/claws-mail/claws/src/imap.c,v
retrieving revision 1.179.2.252
diff -u -r1.179.2.252 imap.c
--- src/imap.c 3 Oct 2010 11:46:24 -0000 1.179.2.252
+++ src/imap.c 19 Nov 2010 21:34:01 -0000
@@ -5888,3 +5888,17 @@
*dst = '\0';
return res;
}
+
+gboolean imap_idle_cb(Folder* folder)
+{
+ guint new_msgs = 0;
+
+ g_return_val_if_fail(folder != NULL, FALSE);
+
+ debug_print("%s: Updating folder message cache\n", folder->name);
+
+ new_msgs = folderview_check_new(folder);
+ debug_print("%s: RECENT [%d]\n", folder->name, new_msgs);
+
+ return TRUE;
+}
Index: src/imap.h
===================================================================
RCS file: /home/claws-mail/claws/src/imap.h,v
retrieving revision 1.34.2.22
diff -u -r1.34.2.22 imap.h
--- src/imap.h 20 Feb 2010 18:16:44 -0000 1.34.2.22
+++ src/imap.h 19 Nov 2010 21:34:01 -0000
@@ -47,4 +47,6 @@
char* imap_modified_utf7_to_utf8(const char *mbox, gboolean change_spaces);
char* imap_utf8_to_modified_utf7(const char *src, gboolean change_spaces);
+gboolean imap_idle_cb(Folder* folder);
+
#endif /* __IMAP_H__ */
Index: src/prefs_account.c
===================================================================
RCS file: /home/claws-mail/claws/src/prefs_account.c,v
retrieving revision 1.105.2.161
diff -u -r1.105.2.161 prefs_account.c
--- src/prefs_account.c 30 Sep 2010 07:27:00 -0000 1.105.2.161
+++ src/prefs_account.c 19 Nov 2010 21:34:01 -0000
@@ -154,6 +154,7 @@
GtkWidget *maxarticle_label;
GtkWidget *maxarticle_spinbtn;
GtkObject *maxarticle_spinbtn_adj;
+ GtkWidget *imap_idle_checkbtn;
} ReceivePage;
typedef struct SendPage
@@ -496,6 +497,10 @@
&receive_page.imap_use_trash_checkbtn,
prefs_set_data_from_toggle, prefs_set_toggle},
+ {"use_imap_idle", "TRUE", &tmp_ac_prefs.use_imap_idle, P_BOOL,
+ &receive_page.imap_idle_checkbtn,
+ prefs_set_data_from_toggle, prefs_set_toggle},
+
{NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
};
@@ -1361,6 +1366,7 @@
GtkWidget *local_inbox_label;
GtkWidget *local_inbox_entry;
GtkWidget *local_inbox_btn;
+ GtkWidget *imap_idle_checkbtn;
GtkWidget *optmenu;
GtkListStore *menu;
@@ -1583,6 +1589,17 @@
CLAWS_SET_TIP(imap_use_trash_checkbtn,
_("Moves deleted mails to trash instead of using the \\Deleted flag without expunging."));
+ hbox1 = gtk_hbox_new (FALSE, 8);
+ gtk_widget_show (hbox1);
+ gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, FALSE, 4);
+
+ PACK_CHECK_BUTTON
+ (hbox1, imap_idle_checkbtn, (_("Use IMAP IDLE (Push Mail)")));
+ CLAWS_SET_TIP(imap_idle_checkbtn,
+ _("If the server supports IMAP IDLE use this instead of polling the server. "
+ "A timer will periodically renew the connection to avoid the server closing down "
+ "in case of no activity."));
+
PACK_CHECK_BUTTON (vbox1, filter_on_recv_checkbtn,
_("Filter messages on receiving"));
@@ -1623,7 +1640,8 @@
page->local_inbox_entry = local_inbox_entry;
page->local_inbox_btn = local_inbox_btn;
- page->recvatgetall_checkbtn = recvatgetall_checkbtn;
+ page->recvatgetall_checkbtn = recvatgetall_checkbtn;
+ page->imap_idle_checkbtn = imap_idle_checkbtn;
page->frame_maxarticle = frame2;
page->maxarticle_spinbtn = maxarticle_spinbtn;
@@ -4148,6 +4166,7 @@
gtk_widget_hide(receive_page.subsonly_checkbtn);
gtk_widget_hide(receive_page.low_bandwidth_checkbtn);
gtk_widget_hide(receive_page.imap_use_trash_checkbtn);
+ gtk_widget_hide(receive_page.imap_idle_checkbtn);
break;
case A_LOCAL:
gtk_widget_show(send_page.msgid_checkbtn);
@@ -4243,6 +4262,7 @@
gtk_widget_hide(receive_page.subsonly_checkbtn);
gtk_widget_hide(receive_page.low_bandwidth_checkbtn);
gtk_widget_hide(receive_page.imap_use_trash_checkbtn);
+ gtk_widget_hide(receive_page.imap_idle_checkbtn);
break;
case A_IMAP4:
#ifndef HAVE_LIBETPAN
@@ -4306,6 +4326,7 @@
prefs_account_filter_on_recv_toggled
(GTK_TOGGLE_BUTTON(receive_page.filter_on_recv_checkbtn), NULL);
gtk_widget_set_sensitive(receive_page.recvatgetall_checkbtn, TRUE);
+ gtk_widget_set_sensitive(receive_page.imap_idle_checkbtn, TRUE);
gtk_widget_set_sensitive(basic_page.smtpserv_entry, TRUE);
gtk_widget_set_sensitive(basic_page.smtpserv_label, TRUE);
@@ -4347,6 +4368,7 @@
gtk_widget_show(receive_page.subsonly_checkbtn);
gtk_widget_show(receive_page.low_bandwidth_checkbtn);
gtk_widget_show(receive_page.imap_use_trash_checkbtn);
+ gtk_widget_show(receive_page.imap_idle_checkbtn);
break;
case A_NONE:
gtk_widget_show(send_page.msgid_checkbtn);
@@ -4440,6 +4462,7 @@
gtk_widget_hide(receive_page.subsonly_checkbtn);
gtk_widget_hide(receive_page.low_bandwidth_checkbtn);
gtk_widget_hide(receive_page.imap_use_trash_checkbtn);
+ gtk_widget_hide(receive_page.imap_idle_checkbtn);
break;
case A_POP3:
default:
@@ -4539,6 +4562,7 @@
gtk_widget_hide(receive_page.subsonly_checkbtn);
gtk_widget_hide(receive_page.low_bandwidth_checkbtn);
gtk_widget_hide(receive_page.imap_use_trash_checkbtn);
+ gtk_widget_hide(receive_page.imap_idle_checkbtn);
break;
}
Index: src/prefs_account.h
===================================================================
RCS file: /home/claws-mail/claws/src/prefs_account.h,v
retrieving revision 1.49.2.44
diff -u -r1.49.2.44 prefs_account.h
--- src/prefs_account.h 12 Jun 2009 10:02:10 -0000 1.49.2.44
+++ src/prefs_account.h 19 Nov 2010 21:34:01 -0000
@@ -86,7 +86,7 @@
gchar *in_ssl_client_cert_pass;
gboolean use_nonblocking_ssl;
-
+
/* Receive */
gboolean use_apop_auth;
gboolean rmmail;
@@ -104,6 +104,8 @@
gint imap_auth_type;
+ gboolean use_imap_idle;
+
/* Send */
gboolean gen_msgid;
gboolean add_customhdr;
Index: src/summaryview.c
===================================================================
RCS file: /home/claws-mail/claws/src/summaryview.c,v
retrieving revision 1.395.2.425
diff -u -r1.395.2.425 summaryview.c
--- src/summaryview.c 2 Oct 2010 15:02:52 -0000 1.395.2.425
+++ src/summaryview.c 19 Nov 2010 21:34:02 -0000
@@ -4300,6 +4300,15 @@
summary_delete(summaryview);
else
summary_move_selected_to(summaryview, to_folder);
+ /*
+ * IMAP IDLE loose ability to receive status messages from server
+ * therefore we do a folderview_check_new if folder is an IMAP
+ * folder and IMAP IDLE is active since calling folderview_check_new
+ * reenables the ability to receive status messages from server again
+ */
+ if (FOLDER_TYPE(summaryview->folder_item->folder) == F_IMAP &&
+ summaryview->folder_item->folder->account->use_imap_idle)
+ folderview_check_new(summaryview->folder_item->folder);
}
Index: src/etpan/imap-thread.c
===================================================================
RCS file: /home/claws-mail/claws/src/etpan/Attic/imap-thread.c,v
retrieving revision 1.1.4.112
diff -u -r1.1.4.112 imap-thread.c
--- src/etpan/imap-thread.c 2 Oct 2010 15:02:53 -0000 1.1.4.112
+++ src/etpan/imap-thread.c 19 Nov 2010 21:34:02 -0000
@@ -35,6 +35,7 @@
#include <sys/mman.h>
#include <sys/wait.h>
#endif
+#include <glib.h>
#include <gtk/gtk.h>
#include <log.h>
#include "etpan-thread-manager.h"
@@ -44,8 +45,13 @@
#include "ssl_certificate.h"
#include "socket.h"
#include "remotefolder.h"
+#include "imap.h"
#define DISABLE_LOG_DURING_LOGIN
+#define INTERVAL 120 /* interval in seconds between IMAP IDLE renewal */
+
+static void imap_threaded_idle_disable(Folder* folder);
+static void imap_threaded_idle_enable(Folder* folder);
static struct etpan_thread_manager * thread_manager = NULL;
static chash * courier_workaround_hash = NULL;
@@ -59,6 +65,9 @@
chashdatum key;
chashdatum value;
+ /* Terminate IMAP IDLE */
+ imap_threaded_idle_disable(folder);
+
key.data = &folder;
key.len = sizeof(folder);
value.data = imap;
@@ -385,9 +394,231 @@
imap = value.data;
debug_print("found imap %p\n", imap);
+
return imap;
}
+/* to be removed when Hoa releases the new version of libetpan */
+static long
+get_idle_delay(mailimap * session)
+{
+ time_t current_time;
+ time_t next_date;
+
+ current_time = time(NULL);
+ next_date = session->imap_idle_timestamp + session->imap_idle_maxdelay;
+
+ if (current_time >= next_date)
+ return 0;
+
+ return next_date - current_time;
+}
+
+static void imap_threaded_idle_destroy_cb(gpointer data)
+{
+ Folder* folder = (Folder *) data;
+ mailimap* imap;
+
+ g_return_if_fail(folder != NULL);
+
+ debug_print("%s: Calling mailimap_idle_done\n", folder->name);
+
+ imap = get_imap(folder);
+ g_return_if_fail(imap != NULL);
+
+ if (folder->idle_active && ! folder->cb_active) {
+ debug_print("%s: mailimap_idle_done [%p]\n", folder->name, imap);
+ mailimap_idle_done(imap);
+ folder->idle_active = FALSE;
+ }
+ folder->cb_active = FALSE;
+}
+
+static gboolean imap_threaded_idle_cb(GIOChannel* gio,
+ GIOCondition condition,
+ gpointer data)
+{
+ GIOStatus ret;
+ GError* err = NULL;
+ gchar* msg = NULL;
+ gsize len;
+ gboolean keep_going = FALSE;
+
+ Folder* folder = (Folder *) data;
+ g_return_val_if_fail(folder != NULL, FALSE);
+
+ if (condition & G_IO_HUP || condition & G_IO_ERR || condition & G_IO_NVAL) {
+ debug_print("%s: Error in channel\n", folder->name);
+ return FALSE;
+ }
+
+ mailimap* imap = get_imap(folder);
+ g_return_val_if_fail(imap != NULL, FALSE);
+
+ ret = g_io_channel_read_line(gio, &msg, &len, NULL, &err);
+ if (ret == G_IO_STATUS_ERROR) {
+ debug_print("%s -> Error reading: %s\n", folder->name, err->message);
+ g_error_free(err);
+ err = NULL;
+ keep_going = FALSE;
+ }
+ else if (ret == G_IO_STATUS_EOF) {
+ debug_print("%s: EOF on channel detected\n", folder->name);
+ keep_going = FALSE;
+ }
+ else {
+ debug_print("%s: IMAP4< %s\n", folder->name, msg);
+ keep_going = imap_idle_cb(folder);
+ if (keep_going)
+ folder->cb_active = TRUE;
+ else
+ folder->cb_active = FALSE;
+ }
+
+ debug_print("%s: Response: %s\n", folder->name, (keep_going) ? "TRUE" : "FALSE");
+ return keep_going;
+}
+
+static gboolean imap_threaded_handle_imap_idle(Folder* folder, mailimap* imap)
+{
+ int result;
+ gboolean response = FALSE;
+ int sock;
+ long delay = 60L * IDLE_DELAY;
+
+ g_return_val_if_fail(folder != NULL, FALSE);
+
+ sock = mailimap_idle_get_fd(imap);
+ if (sock < 1) {
+ debug_print("%s: no socket\n", folder->name);
+ return FALSE;
+ }
+
+ folder->ioc = g_io_channel_unix_new(sock);
+ if (folder->ioc) {
+ g_io_channel_set_encoding(folder->ioc, NULL, NULL);
+ g_io_channel_set_flags(folder->ioc, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_close_on_unref(folder->ioc, FALSE);
+ result = mailimap_idle(imap);
+ debug_print("%s->%s\n", folder->name, imap->imap_response);
+ if (result != MAILIMAP_NO_ERROR) {
+ if (imap->imap_response) {
+ debug_print("%s->%s\n", folder->name, imap->imap_response);
+ }
+ if (folder->ioc->ref_count > 1)
+ g_io_channel_unref(folder->ioc);
+ response = FALSE;
+ debug_print("%s: Switching to IDLE failed\n", folder->name);
+ }
+ else {
+ mailimap_idle_set_delay(imap, delay);
+ folder->ioc_id = g_io_add_watch_full(folder->ioc, G_PRIORITY_LOW,
+ G_IO_IN | G_IO_HUP, imap_threaded_idle_cb, folder,
+ imap_threaded_idle_destroy_cb);
+ response = TRUE;
+ }
+ g_io_channel_unref(folder->ioc);
+ }
+ debug_print("%s: Response: %s\n", folder->name, (response) ? "TRUE" : "FALSE");
+ return response;
+}
+
+static gboolean imap_threaded_idle_update_status(gpointer data)
+{
+ Folder* folder = (Folder *) data;
+ g_return_val_if_fail(folder != NULL, FALSE);
+
+ mailimap* imap = get_imap(folder);
+ g_return_val_if_fail(imap != NULL, FALSE);
+
+ debug_print("Update status for IMAP IDLE connections\n");
+ /* Is it time to refresh IDLE */
+ if (get_idle_delay(imap) + 10 < INTERVAL) {
+ debug_print("%s: Refreshing IDLE [%p]\n", folder->name, imap);
+ mailimap_idle_done(imap);
+ mailimap_idle(imap);
+ }
+
+ return TRUE;
+}
+
+static void imap_threaded_idle_disable(Folder* folder)
+{
+ mailimap* imap;
+
+ g_return_if_fail(folder != NULL);
+
+ if ((! folder->idle_active || folder->ioc_id == 0 ) && ! folder->ioc)
+ return;
+
+ imap = get_imap(folder);
+
+ if (! imap)
+ return;
+
+ debug_print("%s: Disable IMAP IDLE\n", folder->name);
+
+ if (folder->ioc_id > 0 ) {
+ debug_print("%s: Calling g_source_remove: %d\n", folder->name, folder->ioc_id);
+ g_source_remove(folder->ioc_id);
+ folder->cb_active = FALSE;
+ folder->ioc_id = 0;
+ }
+ folder->idle_active = FALSE;
+ if (folder->timer_id > 0) {
+ debug_print("%s: Destroying timer\n", folder->name);
+ g_source_remove(folder->timer_id);
+ folder->timer_id = 0;
+ }
+}
+
+static void imap_threaded_idle_enable(Folder* folder)
+{
+ mailimap * imap;
+
+ g_return_if_fail(folder != NULL);
+
+ if (folder->idle_active) {
+ g_warning("%s: idle already active!!!", folder->name);
+ return;
+ }
+
+ imap = get_imap(folder);
+
+ if (! imap)
+ return;
+
+ if (! mailimap_has_idle(imap) || ! folder->account->use_imap_idle)
+ return;
+
+ /* IDLE only allowed while in SELECT or LOGIN state */
+ if (imap->imap_state < MAILIMAP_STATE_AUTHENTICATED ||
+ imap->imap_state > MAILIMAP_STATE_SELECTED)
+ return;
+
+ debug_print("%s: Enable IMAP IDLE\n", folder->name);
+
+ gboolean r = imap_threaded_handle_imap_idle(folder, imap);
+ if (r) {
+ folder->idle_active = TRUE;
+ }
+ else {
+ debug_print("%s: Enable IMAP IDLE failed\n", folder->name);
+ folder->idle_active = FALSE;
+ folder->ioc_id = 0;
+ }
+
+ if (folder->idle_active) {
+#if GLIB_CHECK_VERSION(2,14,0)
+ folder->timer_id = g_timeout_add_seconds(
+ INTERVAL, imap_threaded_idle_update_status, folder);
+#else
+ folder->timer_id = g_timeout_add(
+ INTERVAL * 1000, imap_threaded_idle_update_status, folder);
+#endif
+ }
+}
+
static gboolean cb_show_error(gpointer data)
{
mainwindow_show_error();
@@ -418,6 +649,8 @@
imap_folder_ref(folder);
+ imap_threaded_idle_disable(folder);
+
op = etpan_thread_op_new();
op->imap = get_imap(folder);
@@ -441,6 +674,8 @@
etpan_thread_op_free(op);
+ imap_threaded_idle_enable(folder);
+
imap_folder_unref(folder);
}
@@ -681,6 +916,7 @@
if (certificate)
free(certificate);
}
+
debug_print("connect %d with imap %p\n", result.error, imap);
return result.error;
@@ -3387,7 +3623,9 @@
void imap_threaded_cancel(Folder * folder)
{
mailimap * imap;
-
+
+ debug_print("%s: cancel called\n", folder->name);
+
imap = get_imap(folder);
if (imap->imap_stream != NULL)
mailstream_cancel(imap->imap_stream);
Index: src/etpan/imap-thread.h
===================================================================
RCS file: /home/claws-mail/claws/src/etpan/Attic/imap-thread.h,v
retrieving revision 1.1.4.27
diff -u -r1.1.4.27 imap-thread.h
--- src/etpan/imap-thread.h 20 Feb 2010 18:16:45 -0000 1.1.4.27
+++ src/etpan/imap-thread.h 19 Nov 2010 21:34:02 -0000
@@ -25,6 +25,7 @@
#include "folder.h"
#define IMAP_SET_MAX_COUNT 500
+#define IDLE_DELAY 29 /* delay in minuts */
typedef enum
{
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment