[balsa] NetworkManager-glib support.



commit 7c3d2338aaee4c64bc24c8a808ac6a16e7f3d1f1
Author: Pawel Salek <pawsa damage localdomain>
Date:   Wed Nov 11 13:06:59 2009 +0100

    NetworkManager-glib support.
    
    * configure.in: add NetworkManager-glib support.
    * libbalsa/imap-server.c: Disconnect quickly if asked to.
    * libbalsa/imap/imap-commands.c: add private unlocked select command.
    * libbalsa/imap/imap-handle.c: locking changes.
    * libbalsa/imap/imap-handle.h: add ..force_disconnect() prototype.
    * libbalsa/imap/imap_private.h: add select_unlocked() prototype.
    * libbalsa/mailbox.c: stop-gap performance fix.
    * libbalsa/mailbox_imap.[hc]: Add force_disconnect(),reconnect(),is_connected()
    * src/main-window.c: listen to libnm events.

 ChangeLog                     |   13 +++
 configure.in                  |  179 ++++++++++++++++++++---------------------
 libbalsa/imap-server.c        |    4 +-
 libbalsa/imap/imap-commands.c |   23 ++++--
 libbalsa/imap/imap-handle.c   |   55 +++++++------
 libbalsa/imap/imap-handle.h   |    2 +
 libbalsa/imap/imap_private.h  |    5 +-
 libbalsa/mailbox.c            |   10 +++
 libbalsa/mailbox_imap.c       |   39 +++++++++
 libbalsa/mailbox_imap.h       |    3 +
 src/main-window.c             |  110 +++++++++++++++++++++++++
 11 files changed, 317 insertions(+), 126 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 5df0281..bb4bb5a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2009-11-11  Pawel Salek
+
+	* configure.in: add NetworkManager-glib support.
+	* libbalsa/imap-server.c: Disconnect quickly if asked to.
+	* libbalsa/imap/imap-commands.c: add private unlocked select command.
+	* libbalsa/imap/imap-handle.c: locking changes.
+	* libbalsa/imap/imap-handle.h: add ..force_disconnect() prototype.
+	* libbalsa/imap/imap_private.h: add select_unlocked() prototype.
+	* libbalsa/mailbox.c: stop-gap performance fix.
+	* libbalsa/mailbox_imap.[hc]: Add force_disconnect(), reconnect(),
+	is_connected().
+	* src/main-window.c: listen to libnm events.
+
 2009-11-08  Peter Bloomfield
 
 	* libbalsa/imap/imap-tls.c (imap_check_server_identity): openssl
diff --git a/configure.in b/configure.in
index b2e7bed..b3a2f06 100644
--- a/configure.in
+++ b/configure.in
@@ -40,13 +40,6 @@ AC_DEFINE_UNQUOTED(BALSA_VERSION, "$BALSA_VERSION",
 dnl #####################################################################
 dnl 2. Options
 dnl #####################################################################
-AC_ARG_WITH(iconv,      
-        AC_HELP_STRING([--with-iconv=DIR],
-                [Where libiconv is installed]),
-           [if test "$with_iconv" != yes -a "$with_iconv" != no ; then
-                   CPPFLAGS="-I${with_iconv}/include $CPPFLAGS"
-                   LDFLAGS="-liconv -L${with_iconv}/lib $LDFLAGS"
-            fi])
 AC_ARG_WITH([gnome],
         AC_HELP_STRING([--with-gnome],
                 [Use GNOME libraries (default=yes)]),[
@@ -89,13 +82,6 @@ if test x"$use_threads" = xyes; then
         AC_DEFINE(BALSA_USE_THREADS, 1,[Defined when balsa is to use threads.])
 fi
 
-AC_ARG_WITH([ldap],
-        AC_HELP_STRING([--with-ldap=DIR],
-                [Use OpenLDAP if available (default=no)]),[
-	with_ldap=$withval
-],[
-	with_ldap=no
-])
 
 AC_ARG_WITH([gpgme],
    AC_HELP_STRING([--with-gpgme=gpgme-config],
@@ -110,69 +96,75 @@ AC_ARG_WITH([gpg-app],
                   [use PATH as GnuPG application (default=gpg2 if >= 2.0.4, otherwise gpg 1.x)]),
 	          [ gpgapp=$withval ], [ gpgapp=no ])
 
-AC_ARG_WITH([webkit],
-              AC_HELP_STRING([--with-webkit],
-                [Use WebKit if available (default=no)]),[
-	use_webkit=$withval
-],[
-	use_webkit=no
-])
 
-AC_ARG_WITH([macosx-desktop],
-              AC_HELP_STRING([--with-macosx-desktop],
-                [Use Mac OS X Desktop Integration (default=no, extremely experimental)]),[
-	use_igemacint=$withval
-],[
-	use_igemacint=no
-])
+
+AC_ARG_WITH(canberra,
+   AC_HELP_STRING([--with-canberra],
+                  [Use libcanberra-gtk2 for filter sounds (default=no)]),
+                  [with_canberra=$withval],[with_canberra=no])
+
+AC_ARG_WITH(compface,
+   AC_HELP_STRING([--with-compface],
+                  [Enable Compface (default=no)]),
+                  [with_compface=$withval],[with_compface=no])
+
+AC_ARG_WITH(esmtp,
+   AC_HELP_STRING([--with-esmtp=DIR],
+                  [Enable libESMTP (default=yes)]),
+                  [ with_esmtp=$withval ],[ with_esmtp=yes ])
+
+AC_ARG_ENABLE([gregex], 
+   AC_HELP_STRING([--enable-gregex],
+                  [Use GRegex regular expressions if available (default=no)]),
+                  [ check_gregex=$enableval],[ check_gregex=no ])
+
+AC_ARG_WITH(gss,
+   AC_HELP_STRING([--with-gss],
+                  [Enable GSS (default=no)]),
+                  [with_gss=$withval],[with_gss=no])
 
 AC_ARG_WITH([gtkhtml],
-              AC_HELP_STRING([--with-gtkhtml],
-                             [Preferred GtkHTML version, 2 or 3 (default=3)]),[
-	use_gtkhtml=$withval
-],[
-	use_gtkhtml=3
-])
+   AC_HELP_STRING([--with-gtkhtml],
+                  [Preferred GtkHTML version, 2 or 3 (default=3)]),
+		  [use_gtkhtml=$withval],[use_gtkhtml=3])
+
+AC_ARG_WITH([gtksourceview],
+   AC_HELP_STRING([--with-gtksourceview],
+                  [Use GtkSourceView if available (default=no, specify version 1 or 2, yes=2)]),
+		  [with_gtksourceview=$withval],[with_gtksourceview=no])
 
 AC_ARG_WITH([gtkspell],
-        AC_HELP_STRING([--with-gtkspell],
-                [Use GtkSpell if available (default=no)]),[
-	with_gtkspell=$withval
-],[
-	with_gtkspell=no
-])
+   AC_HELP_STRING([--with-gtkspell],
+                  [Use GtkSpell if available (default=no)]),
+		  [with_gtkspell=$withval],[with_gtkspell=no])
 
-AC_ARG_WITH([libnotify],
-        AC_HELP_STRING([--with-libnotify],
-                [Use libnotify if available (default=yes)]),[
-	with_libnotify=$withval
-],[
-	with_libnotify=yes
-])
+AC_ARG_WITH(iconv,      
+   AC_HELP_STRING([--with-iconv=DIR],
+                  [Where libiconv is installed]),
+		  [if test "$with_iconv" != yes -a "$with_iconv" != no ; then
+                   CPPFLAGS="-I${with_iconv}/include $CPPFLAGS"
+                   LDFLAGS="-liconv -L${with_iconv}/lib $LDFLAGS"
+		   fi])
 
-AC_ARG_WITH([gtksourceview],
-        AC_HELP_STRING([--with-gtksourceview],
-                [Use GtkSourceView if available (default=no, specify version 1 or 2, yes=2)]),[
-	with_gtksourceview=$withval
-],[
-	with_gtksourceview=no
-])
+AC_ARG_WITH([ldap],
+   AC_HELP_STRING([--with-ldap=DIR],
+                  [Use OpenLDAP if available (default=no)]),
+		  [with_ldap=$withval],[with_ldap=no])
 
-AC_ARG_WITH([sqlite],
-        AC_HELP_STRING([--with-sqlite=DIR],
-                [Use SQLite for GPE address books (default=no)]),[
-	with_sqlite=$withval
-],[
-	with_sqlite=no
-])
+AC_ARG_WITH([libnotify],
+   AC_HELP_STRING([--with-libnotify],
+                  [Use libnotify if available (default=yes)]),
+		  [with_libnotify=$withval],[with_libnotify=yes])
 
-AC_ARG_WITH([rubrica],
-        AC_HELP_STRING([--with-rubrica],
-                [add Rubrica2 address book support (needs libxml2, default=no)]),[
-	with_rubrica=$withval
-],[
-	with_rubrica=no
-])
+AC_ARG_WITH([macosx-desktop],
+   AC_HELP_STRING([--with-macosx-desktop],
+	          [Use Mac OS X Desktop Integration (default=no, extremely experimental)]),
+		  [use_igemacint=$withval],[use_igemacint=no])
+
+AC_ARG_WITH(nm,
+   AC_HELP_STRING([--with-nm],
+                  [Enable NetworkManager (default=yes)]),
+                  [with_nm=$withval],[with_nm=yes])
 
 AC_ARG_ENABLE([pcre], 
    AC_HELP_STRING([--enable-pcre],
@@ -180,47 +172,38 @@ AC_ARG_ENABLE([pcre],
                   [ check_pcre=$enableval],[ check_pcre=no ])
 
 
-AC_ARG_ENABLE([gregex], 
-   AC_HELP_STRING([--enable-gregex],
-                  [Use GRegex regular expressions if available (default=no)]),
-                  [ check_gregex=$enableval],[ check_gregex=no ])
-
+AC_ARG_WITH([rubrica],
+   AC_HELP_STRING([--with-rubrica],
+                  [add Rubrica2 address book support (needs libxml2, default=no)]),
+		  [with_rubrica=$withval],[with_rubrica=no])
 
-AC_ARG_WITH(esmtp,
-   AC_HELP_STRING([--with-esmtp=DIR],
-                  [Enable libESMTP (default=yes)]),
-                  [ with_esmtp=$withval ],[ with_esmtp=yes ])
+AC_ARG_WITH([sqlite],
+   AC_HELP_STRING([--with-sqlite=DIR],
+                  [Use SQLite for GPE address books (default=no)]),
+                  [with_sqlite=$withval],[with_sqlite=no])
 
 AC_ARG_WITH(ssl,
    AC_HELP_STRING([--with-ssl],
                   [Enable SSL (default=no)]),
                   [ with_ssl=$withval ],[ with_ssl=no ])
 
-AC_ARG_WITH(gss,
-   AC_HELP_STRING([--with-gss],
-                  [Enable GSS (default=no)]),
-                  [with_gss=$withval],[with_gss=no])
-
-AC_ARG_WITH(compface,
-   AC_HELP_STRING([--with-compface],
-                  [Enable Compface (default=no)]),
-                  [with_compface=$withval],[with_compface=no])
-
 AC_ARG_WITH(unique,
    AC_HELP_STRING([--with-unique],
                   [Use libUnique instead of BonoboActivation (default=no)]),
                   [with_unique=$withval],[with_unique=no])
 
-AC_ARG_WITH(canberra,
-   AC_HELP_STRING([--with-canberra],
-                  [Use libcanberra-gtk2 for filter sounds (default=no)]),
-                  [with_canberra=$withval],[with_canberra=no])
+AC_ARG_WITH([webkit],
+   AC_HELP_STRING([--with-webkit],
+                  [Use WebKit if available (default=no)]),
+		  [use_webkit=$withval],[use_webkit=no])
+
 
 AC_ARG_ENABLE(more-warnings,
    AC_HELP_STRING([--enable-more-warnings],
                   [Enable maximum compiler warnings (default=yes)]),
                   [set_more_warnings="$enableval"], [set_more_warnings=yes])
 
+
 dnl ##########################################################################
 dnl Enable touchscreen optimized UI?
 dnl ##########################################################################
@@ -743,6 +726,19 @@ if test x$with_libnotify != xno; then
     BALSA_AB_LIBS="$BALSA_AB_LIBS -lnotify"
 fi
 
+# NetworkManager
+AC_MSG_CHECKING([NetworkManager-glib-devel])
+echo withnm "'$with_nm'"
+if test "$with_nm" != no ; then
+  PKG_CHECK_MODULES(LIBNM_GLIB, [ libnm_glib ])
+  AC_DEFINE(HAVE_LIBNM_GLIB,1,[ Defined if NetworkManager-glib-devel is found.])
+  CFLAGS="$CFLAGS $LIBNM_GLIB_CFLAGS"
+  LIBS="$LIBS $LIBNM_GLIB_LIBS"
+  AC_MSG_RESULT([yes])
+else
+ AC_MSG_RESULT([no])
+fi
+
 # Compface configuration
 #
 AC_MSG_CHECKING([whether to build Compface support])
@@ -1010,6 +1006,7 @@ echo "                  Use LDAP: $with_ldap"
 echo "                   Use GSS: $with_gss"
 echo "                Use SQLite: $with_sqlite"
 echo "                   Use SSL: $with_ssl"
+echo "        Use NetworkManager: $with_nm"
 echo "              Use GtkSpell: $with_gtkspell"
 echo "             Use Libnotify: $with_libnotify"
 echo "         Use GtkSourceView: $with_gtksourceview"
diff --git a/libbalsa/imap-server.c b/libbalsa/imap-server.c
index 4fc78e8..d43b954 100644
--- a/libbalsa/imap-server.c
+++ b/libbalsa/imap-server.c
@@ -362,6 +362,7 @@ lb_imap_server_info_new(LibBalsaServer *server)
 static void
 lb_imap_server_info_free(struct handle_info *info)
 {
+    imap_handle_force_disconnect(info->handle);
     g_object_unref(info->handle);
     g_free(info);
 }
@@ -862,7 +863,8 @@ libbalsa_imap_server_has_persistent_cache(LibBalsaImapServer *srv)
  *
  * Forces a logout on all connections, used when cleaning up.
  **/
-void libbalsa_imap_server_force_disconnect(LibBalsaImapServer *imap_server)
+void
+libbalsa_imap_server_force_disconnect(LibBalsaImapServer *imap_server)
 {
     LOCK_SERVER(imap_server);
     g_list_foreach(imap_server->used_handles,
diff --git a/libbalsa/imap/imap-commands.c b/libbalsa/imap/imap-commands.c
index 4712288..16591f6 100644
--- a/libbalsa/imap/imap-commands.c
+++ b/libbalsa/imap/imap-commands.c
@@ -181,19 +181,18 @@ imap_mbox_handle_noop(ImapMboxHandle *handle)
 /* 6.3.1 SELECT Command
  * readonly_mbox can be NULL. */
 ImapResponse
-imap_mbox_select(ImapMboxHandle* handle, const char *mbox,
-                 gboolean *readonly_mbox)
+imap_mbox_select_unlocked(ImapMboxHandle* handle, const char *mbox,
+                          gboolean *readonly_mbox)
 {
   gchar* cmd, *mbx7;
   ImapResponse rc;
 
   IMAP_REQUIRED_STATE3(handle, IMHS_CONNECTED, IMHS_AUTHENTICATED,
                        IMHS_SELECTED, IMR_BAD);
-  HANDLE_LOCK(handle);
+
   if (handle->state == IMHS_SELECTED && strcmp(handle->mbox, mbox) == 0) {
     if(readonly_mbox)
       *readonly_mbox = handle->readonly_mbox;
-    HANDLE_UNLOCK(handle);
     return IMR_OK;
   }
   imap_mbox_resize_cache(handle, 0);
@@ -219,10 +218,20 @@ imap_mbox_select(ImapMboxHandle* handle, const char *mbox,
     mbox_view_dispose(&handle->mbox_view);
     g_signal_emit_by_name(G_OBJECT(handle), "exists-notify");
   }
-  HANDLE_UNLOCK(handle);
+
   return rc;
 }
 
+ImapResponse
+imap_mbox_select(ImapMboxHandle* handle, const char *mbox,
+                 gboolean *readonly_mbox)
+{
+  ImapResponse rc;
+  HANDLE_LOCK(handle);
+  rc = imap_mbox_select_unlocked(handle, mbox, readonly_mbox);
+  HANDLE_UNLOCK(handle);
+  return rc;
+}
 
 /* 6.3.2 EXAMINE Command */
 ImapResponse
@@ -390,11 +399,11 @@ enum_flag_to_str(ImapMsgFlags flg)
   GString *flags_str = g_string_new("");
   unsigned idx;
 
-  for(idx=0; idx < ELEMENTS(msg_flags); idx++) {
+  for(idx=0; idx < ELEMENTS(imap_msg_flags); idx++) {
     if((flg & (1<<idx)) == 0) continue;
     if(*flags_str->str) g_string_append_c(flags_str, ' ');
     g_string_append_c(flags_str, '\\');
-    g_string_append(flags_str, msg_flags[idx]);
+    g_string_append(flags_str, imap_msg_flags[idx]);
   }
   return g_string_free(flags_str, FALSE);
 }
diff --git a/libbalsa/imap/imap-handle.c b/libbalsa/imap/imap-handle.c
index 7f47277..c32c5d5 100644
--- a/libbalsa/imap/imap-handle.c
+++ b/libbalsa/imap/imap-handle.c
@@ -583,6 +583,8 @@ imap_mbox_handle_connect(ImapMboxHandle* ret, const char *host, int over_ssl)
   ImapResult rc;
 
   g_return_val_if_fail(imap_mbox_is_disconnected(ret), IMAP_CONNECT_FAILED);
+
+  HANDLE_LOCK(ret);
 #if !defined(USE_TLS)
   if(over_ssl) {
     imap_mbox_handle_set_msg(ret,"SSL requested but SSL support not compiled");
@@ -599,6 +601,8 @@ imap_mbox_handle_connect(ImapMboxHandle* ret, const char *host, int over_ssl)
 
   rc = imap_authenticate(ret);
 
+  HANDLE_UNLOCK(ret);
+
   return rc;
 }
 
@@ -627,25 +631,33 @@ imap_mbox_handle_reconnect(ImapMboxHandle* h, gboolean *readonly)
 {
   ImapResult rc;
   
+  HANDLE_LOCK(h);
 
-  if( (rc=imap_mbox_connect(h)) != IMAP_SUCCESS)
-    return rc;
-
-  if( (rc = imap_authenticate(h)) != IMAP_SUCCESS)
-    return rc;
-
-  imap_mbox_resize_cache(h, 0); /* invalidate cache */
-  mbox_view_dispose(&h->mbox_view); /* FIXME: recreate it here? */
+  if( (rc=imap_mbox_connect(h)) == IMAP_SUCCESS) {
+    if( (rc = imap_authenticate(h)) == IMAP_SUCCESS) {
+      imap_mbox_resize_cache(h, 0); /* invalidate cache */
+      mbox_view_dispose(&h->mbox_view); /* FIXME: recreate it here? */
 
-  if(h->mbox) {
-    switch(imap_mbox_select(h, h->mbox, readonly)) {
-    case IMR_OK: rc = IMAP_SUCCESS;       break;
-    default:     rc = IMAP_SELECT_FAILED; break;
+      if(h->mbox && 
+         imap_mbox_select_unlocked(h, h->mbox, readonly) != IMR_OK) {
+        rc = IMAP_SELECT_FAILED;
+      }
     }
   }
+  HANDLE_UNLOCK(h);
   return rc;
 }
 
+/** Drops the connection without waiting for response.  This can be
+    called when eg a signal from NetworkManager arrives. */
+void
+imap_handle_force_disconnect(ImapMboxHandle *h)
+{
+  HANDLE_LOCK(h);
+  imap_handle_disconnect(h);
+  HANDLE_UNLOCK(h);
+}
+
 ImapTlsMode
 imap_handle_set_tls_mode(ImapMboxHandle* r, ImapTlsMode state)
 {
@@ -656,7 +668,7 @@ imap_handle_set_tls_mode(ImapMboxHandle* r, ImapTlsMode state)
   return res;
 }
 
-const char* msg_flags[6] = { 
+const char* imap_msg_flags[6] = { 
   "seen", "answered", "flagged", "deleted", "draft", "recent"
 };
 
@@ -745,7 +757,6 @@ imap_mbox_connect(ImapMboxHandle* handle)
   static const int SIO_BUFSZ=8192;
   ImapResponse resp;
   const char *service = "imap";
-  HANDLE_LOCK(handle);
 
   /* reset some handle status */
   handle->op_cancelled = FALSE;
@@ -763,16 +774,13 @@ imap_mbox_connect(ImapMboxHandle* handle)
 #endif
 
   handle->sd = imap_socket_open(handle->host, service);
-  if(handle->sd<0) {
-    HANDLE_UNLOCK(handle);
+  if(handle->sd<0)
     return IMAP_CONNECT_FAILED;
-  }
   
   /* Add buffering to the socket */
   handle->sio = sio_attach(handle->sd, handle->sd, SIO_BUFSZ);
   if (handle->sio == NULL) {
     close(handle->sd);
-    HANDLE_UNLOCK(handle);
     return IMAP_NOMEM;
   }
   if(handle->timeout>0) {
@@ -784,7 +792,6 @@ imap_mbox_connect(ImapMboxHandle* handle)
     SSL *ssl = imap_create_ssl();
     if(!ssl) {
       imap_mbox_handle_set_msg(handle,"SSL context could not be created");
-      HANDLE_UNLOCK(handle);
       return IMAP_UNSECURE;
     }
     if(imap_setup_ssl(handle->sio, handle->host, ssl,
@@ -793,7 +800,6 @@ imap_mbox_connect(ImapMboxHandle* handle)
     else {
       imap_mbox_handle_set_msg(handle,"SSL negotiation failed");
       imap_handle_disconnect(handle);
-      HANDLE_UNLOCK(handle);
       return IMAP_UNSECURE;
     }
   }
@@ -806,7 +812,6 @@ imap_mbox_connect(ImapMboxHandle* handle)
     g_message("imap_mbox_connect:unexpected initial response(%d):\n%s\n",
 	      resp, handle->last_msg);
     imap_handle_disconnect(handle);
-    HANDLE_UNLOCK(handle);
     return IMAP_PROTOCOL_ERROR;
   }
   handle->can_fetch_body = 
@@ -818,7 +823,6 @@ imap_mbox_connect(ImapMboxHandle* handle)
           imap_mbox_handle_can_do(handle, IMCAP_STARTTLS)) {
     if( imap_handle_starttls(handle) != IMR_OK) {
       imap_mbox_handle_set_msg(handle,"TLS negotiation failed");
-      HANDLE_UNLOCK(handle);
       return IMAP_UNSECURE; /* TLS negotiation error */
     }
     resp = IMR_OK; /* secured with TLS */
@@ -829,10 +833,9 @@ imap_mbox_connect(ImapMboxHandle* handle)
 #endif
   if(handle->tls_mode == IMAP_TLS_REQUIRED && resp != IMR_OK) {
     imap_mbox_handle_set_msg(handle,"TLS required but not available");
-    HANDLE_UNLOCK(handle);
     return IMAP_UNSECURE;
   }
-  HANDLE_UNLOCK(handle);
+
   return IMAP_SUCCESS;
 }
 
@@ -2841,8 +2844,8 @@ ir_msg_att_flags(ImapMboxHandle *h, int c, unsigned seqno)
   do {
     char buf[LONG_STRING];
     c = imap_get_flag(h->sio, buf, sizeof(buf));
-    for(i=0; i<ELEMENTS(msg_flags); i++)
-      if(buf[0] == '\\' && g_ascii_strcasecmp(msg_flags[i], buf+1) == 0) {
+    for(i=0; i<ELEMENTS(imap_msg_flags); i++)
+      if(buf[0] == '\\' && g_ascii_strcasecmp(imap_msg_flags[i], buf+1) == 0) {
         msg->flags |= 1<<i;
         break;
       }
diff --git a/libbalsa/imap/imap-handle.h b/libbalsa/imap/imap-handle.h
index 3667597..0e84bb0 100644
--- a/libbalsa/imap/imap-handle.h
+++ b/libbalsa/imap/imap-handle.h
@@ -132,6 +132,8 @@ ImapResult imap_mbox_handle_connect(ImapMboxHandle* r, const char *hst,
                                     int over_ssl);
 ImapResult imap_mbox_handle_reconnect(ImapMboxHandle* r,
                                       gboolean *readonly);
+void imap_handle_force_disconnect(ImapMboxHandle *h);
+
 ImapTlsMode imap_handle_set_tls_mode(ImapMboxHandle *h, ImapTlsMode option);
 
 /* int below is a boolean */
diff --git a/libbalsa/imap/imap_private.h b/libbalsa/imap/imap_private.h
index a0f5771..2e5f66b 100644
--- a/libbalsa/imap/imap_private.h
+++ b/libbalsa/imap/imap_private.h
@@ -166,7 +166,10 @@ struct _ImapMboxHandle {
 
 #define EAT_LINE(h, c) while( (c=sio_getc(h->sio)) != -1 && c != '\n')
 
-extern const char* msg_flags[6];
+extern const char* imap_msg_flags[6];
+
+ImapResponse imap_mbox_select_unlocked(ImapMboxHandle* handle, const char *mbox,
+                                       gboolean *readonly_mbox);
 
 void imap_mbox_resize_cache(ImapMboxHandle *h, unsigned new_size);
 
diff --git a/libbalsa/mailbox.c b/libbalsa/mailbox.c
index e37344a..18588b4 100644
--- a/libbalsa/mailbox.c
+++ b/libbalsa/mailbox.c
@@ -1622,6 +1622,16 @@ libbalsa_mailbox_msgno_filt_check(LibBalsaMailbox * mailbox, guint seqno,
                 libbalsa_mailbox_msgno_has_flags(mailbox, seqno, 0,
                                                  LIBBALSA_MESSAGE_FLAG_SELECTED)
                 : TRUE;
+#if 1
+	    /* a hack. The whole filtering idea is bit silly since we
+	       keep checking flags (or maybe more!) on all messages so
+	       that the time spent on changing the selection grows
+	       linearly with the mailbox size!  */
+	    if (LIBBALSA_IS_MAILBOX_IMAP(mailbox) &&
+		!libbalsa_mailbox_imap_is_connected
+		(LIBBALSA_MAILBOX_IMAP(mailbox)))
+		filt_out = FALSE;
+#endif
             if (filt_out)
                 libbalsa_mailbox_msgno_filt_out(mailbox, seqno);
         }
diff --git a/libbalsa/mailbox_imap.c b/libbalsa/mailbox_imap.c
index 70deeea..8ddc4d6 100644
--- a/libbalsa/mailbox_imap.c
+++ b/libbalsa/mailbox_imap.c
@@ -1653,6 +1653,45 @@ libbalsa_mailbox_imap_noop(LibBalsaMailboxImap* mimap)
 	    ;
 }
 
+void
+libbalsa_mailbox_imap_force_disconnect(LibBalsaMailboxImap* mimap)
+{
+    g_return_if_fail(mimap != NULL);
+
+    if (mimap->handle) {/* we do not attempt to reconnect here */
+        printf("Disconnecting %s (%u)\n", LIBBALSA_MAILBOX(mimap)->name,
+               (unsigned)time(NULL));
+        imap_handle_force_disconnect(mimap->handle);
+        printf("Disconnected %s (%u)\n", LIBBALSA_MAILBOX(mimap)->name,
+               (unsigned)time(NULL));
+    }
+}
+
+void
+libbalsa_mailbox_imap_reconnect(LibBalsaMailboxImap* mimap)
+{
+    g_return_if_fail(mimap != NULL);
+
+    if (mimap->handle &&
+        imap_mbox_is_disconnected (mimap->handle)) {
+        printf("Reconnecting %s (%u)\n",
+               LIBBALSA_MAILBOX_REMOTE_SERVER(mimap)->host,
+               (unsigned)time(NULL));
+        if (imap_mbox_handle_reconnect
+            (mimap->handle, &(LIBBALSA_MAILBOX(mimap)->readonly))
+            == IMAP_SUCCESS)
+            printf("Reconnected %s (%u)\n",
+                   LIBBALSA_MAILBOX_REMOTE_SERVER(mimap)->host,
+                   (unsigned)time(NULL));
+    }
+}
+
+gboolean
+libbalsa_mailbox_imap_is_connected(LibBalsaMailboxImap* mimap)
+{
+    return mimap->handle && !imap_mbox_is_disconnected(mimap->handle);
+}
+
 /* imap_close_all_connections:
    close all connections to leave the place cleanly.
 */
diff --git a/libbalsa/mailbox_imap.h b/libbalsa/mailbox_imap.h
index 046c091..679f5f2 100644
--- a/libbalsa/mailbox_imap.h
+++ b/libbalsa/mailbox_imap.h
@@ -60,6 +60,9 @@ GHashTable * libbalsa_mailbox_imap_get_matchings(LibBalsaMailboxImap* mbox,
 
 void libbalsa_mailbox_imap_noop(LibBalsaMailboxImap* mbox);
 
+void libbalsa_mailbox_imap_force_disconnect(LibBalsaMailboxImap* mimap);
+gboolean libbalsa_mailbox_imap_is_connected(LibBalsaMailboxImap* mimap);
+void libbalsa_mailbox_imap_reconnect(LibBalsaMailboxImap* mimap);
 void libbalsa_imap_close_all_connections(void);
 
 gboolean libbalsa_imap_new_subfolder(const gchar *parent, const gchar *folder,
diff --git a/src/main-window.c b/src/main-window.c
index e093a56..f5095e5 100644
--- a/src/main-window.c
+++ b/src/main-window.c
@@ -35,6 +35,7 @@
 #include <string.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
 
+#include "imap-server.h"
 #include "libbalsa.h"
 #include "misc.h"
 #include "html.h"
@@ -45,6 +46,10 @@
 #  include "macosx-helpers.h"
 #endif
 
+#if defined(HAVE_LIBNM_GLIB)
+#include <libnm_glib.h>
+#endif
+
 #include "ab-window.h"
 #include "balsa-app.h"
 #include "balsa-icons.h"
@@ -115,6 +120,10 @@ static void bw_check_messages_thread(struct check_messages_thread_info
 #endif
 static void bw_display_new_mail_notification(int num_new, int has_new);
 
+#if defined(HAVE_LIBNM_GLIB)
+static void mw_change_connection_status(libnm_glib_ctx *ctx, gpointer data);
+#endif
+
 static void balsa_window_class_init(BalsaWindowClass * klass);
 static void balsa_window_init(BalsaWindow * window);
 static void balsa_window_real_open_mbnode(BalsaWindow *window,
@@ -973,6 +982,19 @@ balsa_window_class_init(BalsaWindowClass * klass)
 static void
 balsa_window_init(BalsaWindow * window)
 {
+#if defined(HAVE_LIBNM_GLIB)
+    libnm_glib_ctx *ctx;
+    guint id;
+
+    ctx = libnm_glib_init ();
+    if (!ctx) {
+        fprintf (stderr, "Could not initialize libnm.\n");
+        return;
+    }
+
+    id = libnm_glib_register_callback(ctx, mw_change_connection_status,
+                                      window, NULL);
+#endif /* LIBNM_GLIB */
 }
 
 static gboolean
@@ -3390,6 +3412,94 @@ bw_display_new_mail_notification(int num_new, int has_new)
     g_free(msg);
 }
 
+#if defined(HAVE_LIBNM_GLIB)
+/*Callback to create or disconnect an IMAP mbox. */
+static gboolean
+mw_mbox_change_connection_status(GtkTreeModel * model, GtkTreePath * path,
+                      GtkTreeIter * iter, gboolean is_connected)
+{
+    BalsaMailboxNode *mbnode;
+    LibBalsaMailbox *mailbox;
+
+    gtk_tree_model_get(model, iter, 0, &mbnode, -1);
+    g_return_val_if_fail(mbnode, FALSE);
+
+    if ((mailbox = mbnode->mailbox)) {	/* mailbox, not a folder */
+	if (LIBBALSA_IS_MAILBOX_IMAP(mailbox)) {
+            if (is_connected) {
+                libbalsa_mailbox_imap_reconnect
+                    (LIBBALSA_MAILBOX_IMAP(mailbox));
+            } else {
+                libbalsa_mailbox_imap_force_disconnect
+                    (LIBBALSA_MAILBOX_IMAP(mailbox));
+            }
+        }
+    }
+    g_object_unref(mbnode);
+
+    return FALSE;
+}
+
+#if BALSA_USE_THREADS
+static void*
+bw_change_connection_status_thread(void *arg)
+{
+    gtk_tree_model_foreach(GTK_TREE_MODEL(balsa_app.mblist_tree_store),
+			   (GtkTreeModelForeachFunc)
+                           mw_mbox_change_connection_status,
+			   arg);
+    return NULL;
+}
+#endif /* BALSA_USE_THREADS */
+
+/** Responds to NetworkManager events and creates, alternatively
+forcefully destroys the IMAP connections. */
+static void
+mw_change_connection_status(libnm_glib_ctx *ctx, gpointer data)
+{
+    gboolean is_connected;
+    libnm_glib_state state = libnm_glib_get_network_state (ctx);
+
+    switch (state) {
+    case LIBNM_NO_DBUS:
+        fprintf(stderr, "Status: No DBUS\n");
+        return;
+    case LIBNM_NO_NETWORKMANAGER:
+        fprintf(stderr, "Status: No NetworkManager\n");
+        return;
+    case LIBNM_NO_NETWORK_CONNECTION:
+        fprintf (stderr, "Status: Inactive Connection\n");
+        is_connected = FALSE;
+        break;
+    case LIBNM_ACTIVE_NETWORK_CONNECTION:
+        fprintf (stderr, "Status: Active Connection\n");
+        is_connected = TRUE;
+        break;
+    case LIBNM_INVALID_CONTEXT:
+        fprintf (stderr, "Status: Error\n");
+        return;
+    default:
+        fprintf (stderr, "Status: unknown\n");
+        return;
+    }
+
+#if BALSA_USE_THREADS
+    {
+        pthread_t thread_id;
+        if (pthread_create(&thread_id,
+                   NULL, (void *) &bw_change_connection_status_thread,
+                           GINT_TO_POINTER(is_connected)) == 0)
+            pthread_detach(thread_id);
+    }
+#else /* BALSA_USE_THREADS */
+    gtk_tree_model_foreach(GTK_TREE_MODEL(balsa_app.mblist_tree_store),
+			   (GtkTreeModelForeachFunc)
+                           mw_mbox_change_connection_status,
+			   GINT_TO_POINTER(is_connected));
+#endif /* BALSA_USE_THREADS */
+}
+#endif /* LIBNM_GLIB */
+
 GtkWidget *
 balsa_window_find_current_index(BalsaWindow * window)
 {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]