2007-10-18 [colin] 3.0.2cvs82
authorColin Leroy <colin@colino.net>
Thu, 18 Oct 2007 07:13:06 +0000 (07:13 +0000)
committerColin Leroy <colin@colino.net>
Thu, 18 Oct 2007 07:13:06 +0000 (07:13 +0000)
* src/common/Makefile.am
* src/common/nntp.c
* src/common/nntp.h
* src/etpan/Makefile.am
* src/etpan/etpan-thread-manager-types.h
* src/etpan/etpan-thread-manager.c
* src/etpan/imap-thread.c
* src/etpan/nntp-thread.c
* src/etpan/nntp-thread.h
* src/news.c
* src/news.h
Rewrite the nntp implementation
to use libetpan. Non-blocking NNTP!
* src/account.c
* src/crash.c
* src/imap.c
* src/inc.c
* src/main.c
* src/mainwindow.c
* src/pop.c
* src/pop.h
* src/prefs_account.c
* src/recv.c
* src/recv.h
* src/send_message.c
* src/send_message.h
* src/ssl_manager.c
* src/ssl_manager.h
* src/wizard.c
* src/common/claws.c
* src/common/session.c
* src/common/session.h
* src/common/smtp.c
* src/common/smtp.h
* src/common/socket.c
* src/common/socket.h
* src/common/ssl.c
* src/common/ssl.h
* src/common/ssl_certificate.c
* src/common/ssl_certificate.h
* src/gtk/about.c
* src/gtk/sslcertwindow.c
* src/gtk/sslcertwindow.h
Implement GnuTLS support. GnuTLS support
will be used if OpenSSL isn't available, or
specified explicitely. (the reason is that
GnuTLS cerficate checking is a bit less
practical than OpenSSL's)

44 files changed:
ChangeLog
PATCHSETS
configure.ac
src/account.c
src/common/Makefile.am
src/common/claws.c
src/common/nntp.c [deleted file]
src/common/nntp.h [deleted file]
src/common/session.c
src/common/session.h
src/common/smtp.c
src/common/smtp.h
src/common/socket.c
src/common/socket.h
src/common/ssl.c
src/common/ssl.h
src/common/ssl_certificate.c
src/common/ssl_certificate.h
src/crash.c
src/etpan/Makefile.am
src/etpan/etpan-thread-manager-types.h
src/etpan/etpan-thread-manager.c
src/etpan/imap-thread.c
src/etpan/nntp-thread.c [new file with mode: 0644]
src/etpan/nntp-thread.h [new file with mode: 0644]
src/gtk/about.c
src/gtk/sslcertwindow.c
src/gtk/sslcertwindow.h
src/imap.c
src/inc.c
src/main.c
src/mainwindow.c
src/news.c
src/news.h
src/pop.c
src/pop.h
src/prefs_account.c
src/recv.c
src/recv.h
src/send_message.c
src/send_message.h
src/ssl_manager.c
src/ssl_manager.h
src/wizard.c

index 87f865e..5c115a5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,54 @@
+2007-10-18 [colin]     3.0.2cvs82
+
+       * src/common/Makefile.am
+       * src/common/nntp.c
+       * src/common/nntp.h
+       * src/etpan/Makefile.am
+       * src/etpan/etpan-thread-manager-types.h
+       * src/etpan/etpan-thread-manager.c
+       * src/etpan/imap-thread.c
+       * src/etpan/nntp-thread.c
+       * src/etpan/nntp-thread.h
+       * src/news.c
+       * src/news.h
+               Rewrite the nntp implementation
+               to use libetpan. Non-blocking NNTP!
+       * src/account.c
+       * src/crash.c
+       * src/imap.c
+       * src/inc.c
+       * src/main.c
+       * src/mainwindow.c
+       * src/pop.c
+       * src/pop.h
+       * src/prefs_account.c
+       * src/recv.c
+       * src/recv.h
+       * src/send_message.c
+       * src/send_message.h
+       * src/ssl_manager.c
+       * src/ssl_manager.h
+       * src/wizard.c
+       * src/common/claws.c
+       * src/common/session.c
+       * src/common/session.h
+       * src/common/smtp.c
+       * src/common/smtp.h
+       * src/common/socket.c
+       * src/common/socket.h
+       * src/common/ssl.c
+       * src/common/ssl.h
+       * src/common/ssl_certificate.c
+       * src/common/ssl_certificate.h
+       * src/gtk/about.c
+       * src/gtk/sslcertwindow.c
+       * src/gtk/sslcertwindow.h
+               Implement GnuTLS support. GnuTLS support
+               will be used if OpenSSL isn't available, or
+               specified explicitely. (the reason is that
+               GnuTLS cerficate checking is a bit less 
+               practical than OpenSSL's)
+
 2007-10-18 [paul]      3.0.2cvs81
 
        * src/gtk/inputdialog.c
index bb4504d..12ad59f 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.382.2.417 -r 1.382.2.418 src/compose.c;  cvs diff -u -r 1.8.2.25 -r 1.8.2.26 src/quote_fmt.c;  cvs diff -u -r 1.5.12.12 -r 1.5.12.13 src/quote_fmt.h;  cvs diff -u -r 1.8.2.15 -r 1.8.2.16 src/quote_fmt_lex.l;  cvs diff -u -r 1.22.2.36 -r 1.22.2.37 src/quote_fmt_parse.y;  ) > 3.0.2cvs79.patchset
 ( cvs diff -u -r 1.1.2.18 -r 1.1.2.19 src/plugins/pgpcore/select-keys.c;  ) > 3.0.2cvs80.patchset
 ( cvs diff -u -r 1.2.2.24 -r 1.2.2.25 src/gtk/inputdialog.c;  cvs diff -u -r 1.1.2.6 -r 1.1.2.7 src/gtk/inputdialog.h;  ) > 3.0.2cvs81.patchset
+( cvs diff -u -r 1.61.2.74 -r 1.61.2.75 src/account.c;  cvs diff -u -r 1.23.2.26 -r 1.23.2.27 src/crash.c;  cvs diff -u -r 1.179.2.194 -r 1.179.2.195 src/imap.c;  cvs diff -u -r 1.149.2.83 -r 1.149.2.84 src/inc.c;  cvs diff -u -r 1.115.2.173 -r 1.115.2.174 src/main.c;  cvs diff -u -r 1.274.2.217 -r 1.274.2.218 src/mainwindow.c;  cvs diff -u -r 1.101.2.41 -r 1.101.2.42 src/news.c;  cvs diff -u -r 1.21.2.7 -r 1.21.2.8 src/news.h;  cvs diff -u -r 1.56.2.59 -r 1.56.2.60 src/pop.c;  cvs diff -u -r 1.17.2.20 -r 1.17.2.21 src/pop.h;  cvs diff -u -r 1.105.2.112 -r 1.105.2.113 src/prefs_account.c;  cvs diff -u -r 1.17.2.13 -r 1.17.2.14 src/recv.c;  cvs diff -u -r 1.6.12.7 -r 1.6.12.8 src/recv.h;  cvs diff -u -r 1.17.2.44 -r 1.17.2.45 src/send_message.c;  cvs diff -u -r 1.1.4.7 -r 1.1.4.8 src/send_message.h;  cvs diff -u -r 1.3.2.29 -r 1.3.2.30 src/ssl_manager.c;  cvs diff -u -r 1.2.2.7 -r 1.2.2.8 src/ssl_manager.h;  cvs diff -u -r 1.1.2.62 -r 1.1.2.63 src/wizard.c;  cvs diff -u -r 1.24.2.15 -r 1.24.2.16 src/common/Makefile.am;  cvs diff -u -r 1.1.2.2 -r 1.1.2.3 src/common/claws.c;  cvs diff -u -r -1.6.2.15 -r -1.6.2.16 src/common/nntp.c;  cvs diff -u -r -1.4.2.6 -r -1.4.2.7 src/common/nntp.h;  cvs diff -u -r 1.23.2.15 -r 1.23.2.16 src/common/session.c;  cvs diff -u -r 1.8.2.10 -r 1.8.2.11 src/common/session.h;  cvs diff -u -r 1.11.2.22 -r 1.11.2.23 src/common/smtp.c;  cvs diff -u -r 1.6.2.12 -r 1.6.2.13 src/common/smtp.h;  cvs diff -u -r 1.13.2.36 -r 1.13.2.37 src/common/socket.c;  cvs diff -u -r 1.13.2.16 -r 1.13.2.17 src/common/socket.h;  cvs diff -u -r 1.9.2.21 -r 1.9.2.22 src/common/ssl.c;  cvs diff -u -r 1.2.2.6 -r 1.2.2.7 src/common/ssl.h;  cvs diff -u -r 1.4.2.20 -r 1.4.2.21 src/common/ssl_certificate.c;  cvs diff -u -r 1.1.4.9 -r 1.1.4.10 src/common/ssl_certificate.h;  cvs diff -u -r 1.1.4.7 -r 1.1.4.8 src/etpan/Makefile.am;  cvs diff -u -r 1.1.4.6 -r 1.1.4.7 src/etpan/etpan-thread-manager-types.h;  cvs diff -u -r 1.1.4.8 -r 1.1.4.9 src/etpan/etpan-thread-manager.c;  cvs diff -u -r 1.1.4.87 -r 1.1.4.88 src/etpan/imap-thread.c;  diff -u /dev/null src/etpan/nntp-thread.c;  diff -u /dev/null src/etpan/nntp-thread.h;  cvs diff -u -r 1.4.2.53 -r 1.4.2.54 src/gtk/about.c;  cvs diff -u -r 1.9.2.18 -r 1.9.2.19 src/gtk/sslcertwindow.c;  cvs diff -u -r 1.6.2.8 -r 1.6.2.9 src/gtk/sslcertwindow.h;  ) > 3.0.2cvs82.patchset
index 280b99c..b04ba3e 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=0
 MICRO_VERSION=2
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=81
+EXTRA_VERSION=82
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
@@ -363,7 +363,7 @@ fi
 
 dnl Check for OpenSSL
 AC_ARG_ENABLE(openssl,
-       [  --disable-openssl    disable SSL (OpenSSL) support.],
+       [  --disable-openssl    disable OpenSSL support.],
        [ac_cv_enable_openssl=$enableval], [ac_cv_enable_openssl=yes])
 AC_MSG_CHECKING([whether to use OpenSSL])
 if test x"$ac_cv_enable_openssl" = xyes; then
@@ -371,6 +371,7 @@ if test x"$ac_cv_enable_openssl" = xyes; then
        PKG_CHECK_MODULES(OPENSSL, openssl >= 0.9.7, :, ac_cv_enable_openssl=no)
        if test x$ac_cv_enable_openssl = xyes; then
                AC_DEFINE(USE_OPENSSL, 1, Define if you want OpenSSL support)
+               disable_gnutls="yes"
        else
                AC_MSG_RESULT(not found)
                AC_MSG_WARN([*** OpenSSL will not be supported ***])
@@ -381,6 +382,37 @@ fi
 AC_SUBST(OPENSSL_CFLAGS)
 AC_SUBST(OPENSSL_LIBS)
 
+dnl GNUTLS
+AC_ARG_ENABLE(gnutls,    [ --disable-gnutls      disable GnuTLS support],
+            [ac_cv_enable_gnutls=$enableval], [ac_cv_enable_gnutls=yes])
+if test "x$disable_gnutls" != "xyes"; then
+       AC_MSG_CHECKING([whether to use GnuTLS])
+       if test "x$ac_cv_enable_gnutls" != "xno"; then
+         OCPPFLAGS="$CPPFLAGS"
+         OLDFLAGS="$LDFLAGS"
+         GNUTLS_LIBS=""
+         AC_CHECK_HEADER(gnutls/gnutls.h, [
+               AC_CHECK_LIB(gnutls, gnutls_global_deinit, 
+                       [AC_DEFINE(USE_GNUTLS, 1, Define to use GnuTLS.)],
+                       [ac_cv_enable_gnutls=no])
+         ],[ac_cv_enable_gnutls=no])
+         if test "x$ac_cv_enable_gnutls" != "xyes"; then
+          CPPFLAGS="$OCPPFLAGS"
+          LDFLAGS="$OLDFLAGS"
+         fi
+       fi
+       if test "x$ac_cv_enable_gnutls" = "xyes"; then
+         AC_DEFINE([USE_GNUTLS],1, [Define to use GnuTLS])
+         GNUTLS_LIBS="-lgnutls"
+         disable_openssl="yes"
+       else
+         GNUTLS_LIBS=""
+       fi
+else
+       ac_cv_enable_gnutls="no"
+fi
+AC_SUBST(GNUTLS_LIBS)
+
 dnl password encryption
 OLDLIBS=$LIBS
 LIBS=
@@ -954,6 +986,7 @@ echo ""
 echo "JPilot        : $ac_cv_enable_jpilot"
 echo "LDAP          : $ac_cv_enable_ldap"
 echo "OpenSSL       : $ac_cv_enable_openssl"
+echo "gnuTLS        : $ac_cv_enable_gnutls"
 echo "iconv         : $am_cv_func_iconv"
 echo "compface      : $ac_cv_enable_compface"
 echo "IPv6          : $ac_cv_enable_ipv6"
index 6ec5a36..fc1e889 100644 (file)
@@ -1238,7 +1238,7 @@ static void account_list_view_add(PrefsAccount *ac_prefs)
        gboolean getall;
 
        name = ac_prefs->account_name;
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        protocol = ac_prefs->protocol == A_POP3 ?
                  (ac_prefs->ssl_pop == SSL_TUNNEL ?
                   "POP3 (SSL)" :
index edd5b1b..508ba9d 100644 (file)
@@ -18,7 +18,6 @@ libclawscommon_la_SOURCES = $(arch_sources) \
        log.c \
        md5.c \
        mgutils.c \
-       nntp.c \
        passcrypt.c \
        plugin.c \
        prefs.c \
@@ -47,7 +46,6 @@ clawscommoninclude_HEADERS = $(arch_headers) \
        log.h \
        md5.h \
        mgutils.h \
-       nntp.h \
        passcrypt.h \
        plugin.h \
        prefs.h \
index 44d6dd0..38fd532 100644 (file)
@@ -115,7 +115,7 @@ gboolean claws_init(int *argc, char ***argv)
 
        srand((gint) time(NULL));
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        ssl_init();
 #endif
 
@@ -127,7 +127,7 @@ gboolean claws_init(int *argc, char ***argv)
 void claws_done(void)
 {
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        ssl_done();
 #endif
 }
diff --git a/src/common/nntp.c b/src/common/nntp.c
deleted file mode 100644 (file)
index 1733efd..0000000
+++ /dev/null
@@ -1,402 +0,0 @@
-/*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * 
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-#include <glib.h>
-#ifdef ENABLE_NLS
-#include <glib/gi18n.h>
-#else
-#define _(a) (a)
-#define N_(a) (a)
-#endif
-#include <stdio.h>
-#include <string.h>
-
-#include "nntp.h"
-#include "socket.h"
-#include "utils.h"
-#include "log.h"
-#if USE_OPENSSL
-#  include "ssl.h"
-#endif
-
-static gint verbose = 1;
-
-static void nntp_session_destroy(Session       *session);
-
-static gint nntp_ok            (SockInfo       *sock,
-                                gchar          *argbuf);
-
-static gint nntp_gen_send      (SockInfo       *sock,
-                                const gchar    *format,
-                                ...);
-static gint nntp_gen_recv      (SockInfo       *sock,
-                                gchar          *buf,
-                                gint            size);
-static gint nntp_gen_command   (NNTPSession    *session,
-                                gchar          *argbuf,
-                                const gchar    *format,
-                                ...);
-
-#if USE_OPENSSL
-Session *nntp_session_new(const gchar *server, gushort port, gchar *buf,
-                         const gchar *userid, const gchar *passwd,
-                         SSLType ssl_type)
-#else
-Session *nntp_session_new(const gchar *server, gushort port, gchar *buf,
-                         const gchar *userid, const gchar *passwd)
-#endif
-{
-       NNTPSession *session;
-       SockInfo *sock;
-
-       if ((sock = sock_connect(server, port)) == NULL) {
-               log_warning(LOG_PROTOCOL, _("Can't connect to NNTP server: %s:%d\n"),
-                           server, port);
-               return NULL;
-       }
-
-#if USE_OPENSSL
-       if (ssl_type == SSL_TUNNEL && !ssl_init_socket(sock)) {
-               log_error(LOG_PROTOCOL, _("SSL handshake failed\n"));
-               sock_close(sock);
-               return NULL;
-       }
-#endif
-
-       if (nntp_ok(sock, buf) != NN_SUCCESS) {
-               sock_close(sock);
-               return NULL;
-       }
-
-       session = g_new0(NNTPSession, 1);
-
-       session_init(SESSION(session));
-
-       SESSION(session)->type                  = SESSION_NEWS;
-       SESSION(session)->server                = g_strdup(server);
-       SESSION(session)->sock                  = sock;
-       SESSION(session)->last_access_time      = time(NULL);
-       SESSION(session)->data                  = NULL;
-
-       SESSION(session)->destroy               = nntp_session_destroy;
-
-       session->group = NULL;
-       
-       nntp_mode(session, FALSE);
-       
-       if (userid && passwd) {
-               gint ok;
-
-               session->userid = g_strdup(userid);
-               session->passwd = g_strdup(passwd);
-
-               ok = nntp_gen_send(sock, "AUTHINFO USER %s", session->userid);
-               if (ok != NN_SUCCESS) {
-                       session_destroy(SESSION(session));
-                       return NULL;
-               }
-               ok = nntp_ok(sock, NULL);
-               if (ok == NN_AUTHCONT) {
-                       ok = nntp_gen_send(sock, "AUTHINFO PASS %s",
-                                          session->passwd);
-                       if (ok != NN_SUCCESS) {
-                               session_destroy(SESSION(session));
-                               return NULL;
-                       }
-                       ok = nntp_ok(sock, NULL);
-                       if (ok != NN_SUCCESS)
-                               session->auth_failed = TRUE;
-               }
-               if (ok == NN_SOCKET) {
-                       session_destroy(SESSION(session));
-                       return NULL;
-               }
-       }
-
-       session_set_access_time(SESSION(session));
-       
-       return SESSION(session);
-}
-
-void nntp_forceauth(NNTPSession *session, gchar *buf, const gchar *userid, const gchar *passwd)
-
-{
-       if (!session) return;
-               
-       nntp_gen_command(session, buf , "AUTHINFO USER %s", userid);
-
-
-}
-
-static void nntp_session_destroy(Session *session)
-{
-       NNTPSession *nntp_session = NNTP_SESSION(session);
-
-       g_return_if_fail(session != NULL);
-
-       g_free(nntp_session->group);
-       g_free(nntp_session->userid);
-       g_free(nntp_session->passwd);
-}
-
-gint nntp_group(NNTPSession *session, const gchar *group,
-               gint *num, gint *first, gint *last)
-{
-       gint ok;
-       gint resp;
-       gchar buf[NNTPBUFSIZE];
-
-       ok = nntp_gen_command(session, buf, "GROUP %s", group);
-
-       if (ok != NN_SUCCESS && ok != NN_SOCKET && ok != NN_AUTHREQ) {
-               ok = nntp_mode(session, FALSE);
-               if (ok == NN_SUCCESS)
-                       ok = nntp_gen_command(session, buf, "GROUP %s", group);
-       }
-
-       if (ok != NN_SUCCESS)
-               return ok;
-
-       if (sscanf(buf, "%d %d %d %d", &resp, num, first, last)
-           != 4) {
-               log_warning(LOG_PROTOCOL, _("protocol error: %s\n"), buf);
-               return NN_PROTOCOL;
-       }
-
-       return NN_SUCCESS;
-}
-
-gint nntp_get_article(NNTPSession *session, const gchar *cmd, gint num,
-                     gchar **msgid)
-{
-       gint ok;
-       gchar buf[NNTPBUFSIZE];
-
-       if (num > 0)
-               ok = nntp_gen_command(session, buf, "%s %d", cmd, num);
-       else
-               ok = nntp_gen_command(session, buf, cmd);
-
-       if (ok != NN_SUCCESS)
-               return ok;
-
-       extract_parenthesis(buf, '<', '>');
-       if (buf[0] == '\0') {
-               log_warning(LOG_PROTOCOL, _("protocol error\n"));
-               *msgid = g_strdup("0");
-       } else
-               *msgid = g_strdup(buf);
-
-       return NN_SUCCESS;
-}
-
-gint nntp_xover(NNTPSession *session, gint first, gint last)
-{
-       gint ok;
-       gchar buf[NNTPBUFSIZE];
-
-       ok = nntp_gen_command(session, buf, "XOVER %d-%d", first, last);
-       if (ok != NN_SUCCESS)
-               return ok;
-
-       return NN_SUCCESS;
-}
-
-gint nntp_xhdr(NNTPSession *session, const gchar *header, gint first, gint last)
-{
-       gint ok;
-       gchar buf[NNTPBUFSIZE];
-
-       ok = nntp_gen_command(session, buf, "XHDR %s %d-%d",
-                             header, first, last);
-       if (ok != NN_SUCCESS)
-               return ok;
-
-       return NN_SUCCESS;
-}
-
-gint nntp_list(NNTPSession *session)
-{
-       return nntp_gen_command(session, NULL, "LIST");
-}
-
-gint nntp_post(NNTPSession *session, FILE *fp)
-{
-       gint ok;
-       gchar buf[NNTPBUFSIZE];
-       gchar *msg;
-
-       ok = nntp_gen_command(session, buf, "POST");
-       if (ok != NN_SUCCESS)
-               return ok;
-
-       msg = get_outgoing_rfc2822_str(fp);
-       if (sock_write_all(SESSION(session)->sock, msg, strlen(msg)) < 0) {
-               log_warning(LOG_PROTOCOL, _("Error occurred while posting\n"));
-               g_free(msg);
-               return NN_SOCKET;
-       }
-       g_free(msg);
-
-       sock_write_all(SESSION(session)->sock, ".\r\n", 3);
-       if ((ok = nntp_ok(SESSION(session)->sock, buf)) != NN_SUCCESS)
-               return ok;
-
-       session_set_access_time(SESSION(session));
-
-       return NN_SUCCESS;
-}
-
-gint nntp_mode(NNTPSession *session, gboolean stream)
-{
-       gint ok;
-
-       ok = nntp_gen_command(session, NULL, "MODE %s",
-                             stream ? "STREAM" : "READER");
-
-       return ok;
-}
-
-static gint nntp_ok(SockInfo *sock, gchar *argbuf)
-{
-       gint ok;
-       gchar buf[NNTPBUFSIZE];
-
-       if ((ok = nntp_gen_recv(sock, buf, sizeof(buf))) == NN_SUCCESS) {
-               if (strlen(buf) < 3)
-                       return NN_ERROR;
-
-               if ((buf[0] == '1' || buf[0] == '2' || buf[0] == '3') &&
-                   (buf[3] == ' ' || buf[3] == '\0')) {
-                       if (argbuf)
-                               strcpy(argbuf, buf);
-
-                       if (!strncmp(buf, "381", 3))
-                               return NN_AUTHCONT;
-
-                       return NN_SUCCESS;
-               } else if (!strncmp(buf, "480", 3))
-                       return NN_AUTHREQ;
-               else
-                       return NN_ERROR;
-       }
-
-       return ok;
-}
-
-static gint nntp_gen_send(SockInfo *sock, const gchar *format, ...)
-{
-       gchar buf[NNTPBUFSIZE];
-       va_list args;
-
-       va_start(args, format);
-       g_vsnprintf(buf, sizeof(buf), format, args);
-       va_end(args);
-
-       if (verbose) {
-               if (!g_ascii_strncasecmp(buf, "AUTHINFO PASS", 13))
-                       log_print(LOG_PROTOCOL, "NNTP> AUTHINFO PASS ********\n");
-               else
-                       log_print(LOG_PROTOCOL, "NNTP> %s\n", buf);
-       }
-
-       strcat(buf, "\r\n");
-       if (sock_write_all(sock, buf, strlen(buf)) < 0) {
-               log_warning(LOG_PROTOCOL, _("Error occurred while sending command\n"));
-               return NN_SOCKET;
-       }
-
-       return NN_SUCCESS;
-}
-
-static gint nntp_gen_recv(SockInfo *sock, gchar *buf, gint size)
-{
-       if (sock_gets(sock, buf, size) == -1)
-               return NN_SOCKET;
-
-       strretchomp(buf);
-
-       if (verbose)
-               log_print(LOG_PROTOCOL, "NNTP< %s\n", buf);
-
-       return NN_SUCCESS;
-}
-
-static gint nntp_gen_command(NNTPSession *session, gchar *argbuf,
-                            const gchar *format, ...)
-{
-       gchar buf[NNTPBUFSIZE];
-       va_list args;
-       gint ok;
-       SockInfo *sock;
-
-       va_start(args, format);
-       g_vsnprintf(buf, sizeof(buf), format, args);
-       va_end(args);
-
-       sock = SESSION(session)->sock;
-       ok = nntp_gen_send(sock, "%s", buf);
-       if (ok != NN_SUCCESS)
-               return ok;
-       ok = nntp_ok(sock, argbuf);
-       if (ok == NN_AUTHREQ) {
-               if (!session->userid || !session->passwd) {
-                       session->auth_failed = TRUE;
-                       return ok;
-               }
-
-               ok = nntp_gen_send(sock, "AUTHINFO USER %s", session->userid);
-               if (ok != NN_SUCCESS)
-                       return ok;
-               ok = nntp_ok(sock, NULL);
-               if (ok == NN_AUTHCONT) {
-                       ok = nntp_gen_send(sock, "AUTHINFO PASS %s",
-                                          session->passwd);
-                       if (ok != NN_SUCCESS)
-                               return ok;
-                       ok = nntp_ok(sock, NULL);
-               }
-               if (ok != NN_SUCCESS) {
-                       session->auth_failed = TRUE;
-                       return ok;
-               }
-
-               ok = nntp_gen_send(sock, "%s", buf);
-               if (ok != NN_SUCCESS)
-                       return ok;
-               ok = nntp_ok(sock, argbuf);
-
-       } else if (ok == NN_AUTHCONT) {
-                ok = nntp_gen_send(sock, "AUTHINFO PASS %s",
-                                  session->passwd);
-               if (ok != NN_SUCCESS)  {
-                       session->auth_failed = TRUE;
-                       return ok;
-               }
-                ok = nntp_ok(sock, NULL);
-       }
-       
-       session_set_access_time(SESSION(session));
-       
-       return ok;
-}
diff --git a/src/common/nntp.h b/src/common/nntp.h
deleted file mode 100644 (file)
index fde9e23..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * 
- */
-
-#ifndef __NNTP_H__
-#define __NNTP_H__
-
-#include "session.h"
-#if USE_OPENSSL
-#  include "ssl.h"
-#endif
-
-typedef struct _NNTPSession    NNTPSession;
-
-#define NNTP_SESSION(obj)       ((NNTPSession *)obj)
-
-struct _NNTPSession
-{
-       Session session;
-
-       gchar *group;
-       gfloat fetch_base_percentage;
-       gfloat fetch_total_percentage;
-
-       gchar *userid;
-       gchar *passwd;
-       gboolean auth_failed;
-};
-
-#define NN_SUCCESS     0
-#define NN_SOCKET      2
-#define NN_AUTHFAIL    3
-#define NN_PROTOCOL    4
-#define NN_SYNTAX      5
-#define NN_IOERR       6
-#define NN_ERROR       7
-#define NN_AUTHREQ     8
-#define NN_AUTHCONT    9
-
-#define NNTPBUFSIZE    8192
-
-#if USE_OPENSSL
-Session *nntp_session_new      (const gchar    *server,
-                                gushort         port,
-                                gchar          *buf,
-                                const gchar    *userid,
-                                const gchar    *passwd,
-                                SSLType         ssl_type);
-#else
-Session *nntp_session_new      (const gchar    *server,
-                                gushort         port,
-                                gchar          *buf,
-                                const gchar    *userid,
-                                const gchar    *passwd);
-#endif
-
-void nntp_forceauth            (NNTPSession    *session,
-                                gchar          *buf, 
-                                const gchar    *userid, 
-                                const gchar    *passwd);
-
-gint nntp_group                        (NNTPSession    *session,
-                                const gchar    *group,
-                                gint           *num,
-                                gint           *first,
-                                gint           *last);
-gint nntp_get_article          (NNTPSession    *session,
-                                const gchar    *cmd,
-                                gint            num,
-                                gchar         **msgid);
-gint nntp_xover                        (NNTPSession    *session,
-                                gint            first,
-                                gint            last);
-gint nntp_xhdr                 (NNTPSession    *session,
-                                const gchar    *header,
-                                gint            first,
-                                gint            last);
-gint nntp_list                 (NNTPSession    *session);
-gint nntp_post                 (NNTPSession    *session,
-                                FILE           *fp);
-gint nntp_mode                 (NNTPSession    *sessio,
-                                gboolean        stream);
-
-#endif /* __NNTP_H__ */
index 997372e..5bc0098 100644 (file)
@@ -66,7 +66,7 @@ void session_init(Session *session)
        session->sock = NULL;
        session->server = NULL;
        session->port = 0;
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        session->ssl_type = SSL_NONE;
 #endif
        session->nonblocking = TRUE;
@@ -158,7 +158,7 @@ static gint session_connect_cb(SockInfo *sock, gpointer data)
 
        session->sock = sock;
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        if (session->ssl_type == SSL_TUNNEL) {
                sock_set_nonblocking_mode(sock, FALSE);
                if (!ssl_init_socket(sock)) {
@@ -335,7 +335,7 @@ static gint session_close(Session *session)
        return 0;
 }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 gint session_start_tls(Session *session)
 {
        gboolean nb_mode;
index c94d45e..f192721 100644 (file)
@@ -92,7 +92,7 @@ struct _Session
        gchar *server;
        gushort port;
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        SSLType ssl_type;
 #endif
 
@@ -187,7 +187,7 @@ void session_set_send_data_notify   (Session        *session,
                                         SendDataNotify  notify_func,
                                         gpointer        data);
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 gint session_start_tls (Session        *session);
 #endif
 
index 80b5797..f7e5c39 100644 (file)
@@ -40,7 +40,7 @@
 static void smtp_session_destroy(Session *session);
 
 static gint smtp_auth(SMTPSession *session);
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static gint smtp_starttls(SMTPSession *session);
 #endif
 static gint smtp_auth_cram_md5(SMTPSession *session);
@@ -80,7 +80,7 @@ Session *smtp_session_new(void)
 
        session->state                     = SMTP_READY;
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        session->tls_init_done             = FALSE;
 #endif
 
@@ -330,7 +330,7 @@ static gint smtp_ehlo_recv(SMTPSession *session, const gchar *msg)
        return SM_ERROR;
 }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static gint smtp_starttls(SMTPSession *session)
 {
        session->state = SMTP_STARTTLS;
@@ -580,7 +580,7 @@ static gint smtp_session_recv_msg(Session *session, const gchar *msg)
                if (strstr(msg, "ESMTP"))
                        smtp_session->is_esmtp = TRUE;
        case SMTP_CONNECTED:
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                if (smtp_session->user || session->ssl_type != SSL_NONE ||
                    smtp_session->is_esmtp)
 #else
@@ -608,7 +608,7 @@ static gint smtp_session_recv_msg(Session *session, const gchar *msg)
                        smtp_session->error_val = SM_ERROR;
                        return -1;
                }
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                if (session->ssl_type == SSL_STARTTLS &&
                    smtp_session->tls_init_done == FALSE) {
                        ret = smtp_starttls(smtp_session);
@@ -617,7 +617,7 @@ static gint smtp_session_recv_msg(Session *session, const gchar *msg)
 #endif
                if (smtp_session->user) {
                        if (smtp_auth(smtp_session) != SM_OK) {
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                                if (session->ssl_type == SSL_NONE
                                &&  smtp_session->tls_init_done == FALSE
                                &&  (smtp_session->avail_auth_type & SMTPAUTH_TLS_AVAILABLE))
@@ -630,7 +630,7 @@ static gint smtp_session_recv_msg(Session *session, const gchar *msg)
                        ret = smtp_from(smtp_session);
                break;
        case SMTP_STARTTLS:
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                if (session_start_tls(session) < 0) {
                        log_warning(LOG_PROTOCOL, _("couldn't start TLS session\n"));
                        smtp_session->state = SMTP_ERROR;
index def5f23..216fb61 100644 (file)
@@ -90,7 +90,7 @@ struct _SMTPSession
 
        SMTPState state;
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        gboolean tls_init_done;
 #endif
 
index 83529d5..adefb2f 100644 (file)
@@ -62,7 +62,7 @@
 #include "socket.h"
 #include "utils.h"
 #include "log.h"
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #  include "ssl.h"
 #endif
 
@@ -409,6 +409,8 @@ static gboolean sock_check(GSource *source)
                                condition |= G_IO_IN;
                }
        }
+#elif USE_GNUTLS
+/* ?? */
 #endif
 
        FD_ZERO(&fds);
@@ -454,7 +456,7 @@ guint sock_add_watch(SockInfo *sock, GIOCondition condition, SockFunc func,
        sock->condition = condition;
        sock->data = data;
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        if (sock->ssl)
        {
                GSource *source = g_source_new(&sock_watch_funcs,
@@ -1284,6 +1286,37 @@ static gint ssl_read(SSL *ssl, gchar *buf, gint len)
                return -1;
        }
 }
+#elif USE_GNUTLS
+static gint ssl_read(gnutls_session ssl, gchar *buf, gint len)
+{
+       gint r;
+
+       if (gnutls_record_check_pending(ssl) == 0) {
+               if (fd_check_io(GPOINTER_TO_INT(gnutls_transport_get_ptr(ssl)), G_IO_IN) < 0)
+                       return -1;
+       }
+
+       while (1) {
+               r = gnutls_record_recv(ssl, buf, len);
+               if (r > 0)
+                       return r;
+
+               switch (r) {
+               case 0: /* closed connection */
+                       return -1;
+
+               case GNUTLS_E_AGAIN:
+               case GNUTLS_E_INTERRUPTED:
+                       errno = EAGAIN;
+                       return -1;
+               break;
+
+               default:
+                       return -1;
+               }
+       }
+
+}
 #endif
 
 gint sock_read(SockInfo *sock, gchar *buf, gint len)
@@ -1292,7 +1325,7 @@ gint sock_read(SockInfo *sock, gchar *buf, gint len)
 
        g_return_val_if_fail(sock != NULL, -1);
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        if (sock->ssl)
                ret = ssl_read(sock->ssl, buf, len);
        else
@@ -1332,6 +1365,28 @@ static gint ssl_write(SSL *ssl, const gchar *buf, gint len)
                return -1;
        }
 }
+#elif USE_GNUTLS
+static gint ssl_write(gnutls_session ssl, const gchar *buf, gint len)
+{
+       gint ret;
+
+       if (fd_check_io(GPOINTER_TO_INT(gnutls_transport_get_ptr(ssl)), G_IO_OUT) < 0)
+               return -1;
+
+       ret = gnutls_record_send(ssl, buf, len);
+
+       switch (ret) {
+       case 0:
+               return -1;
+       case GNUTLS_E_AGAIN:
+       case GNUTLS_E_INTERRUPTED:
+               return 0;
+
+       default:
+               return ret;
+       }
+}
+
 #endif
 
 gint sock_write(SockInfo *sock, const gchar *buf, gint len)
@@ -1340,7 +1395,7 @@ gint sock_write(SockInfo *sock, const gchar *buf, gint len)
 
        g_return_val_if_fail(sock != NULL, -1);
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        if (sock->ssl)
                ret = ssl_write(sock->ssl, buf, len);
        else
@@ -1379,8 +1434,12 @@ gint fd_write_all(gint fd, const gchar *buf, gint len)
        return wrlen;
 }
 
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #if USE_OPENSSL
 static gint ssl_write_all(SSL *ssl, const gchar *buf, gint len)
+#else
+static gint ssl_write_all(gnutls_session ssl, const gchar *buf, gint len)
+#endif
 {
        gint n, wrlen = 0;
 
@@ -1403,7 +1462,7 @@ gint sock_write_all(SockInfo *sock, const gchar *buf, gint len)
 
        g_return_val_if_fail(sock != NULL, -1);
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        if (sock->ssl)
                ret = ssl_write_all(sock->ssl, buf, len);
        else
@@ -1470,84 +1529,6 @@ Single-byte send() and recv().
        return bp - buf;
 }
 
-#if USE_OPENSSL
-static gint ssl_peek           (SSL *ssl, gchar *buf, gint len);
-
-static gint ssl_gets(SSL *ssl, gchar *buf, gint len)
-{
-       gchar *newline, *bp = buf;
-       gint n;
-
-       if (--len < 1)
-               return -1;
-       do {
-               if ((n = ssl_peek(ssl, bp, len)) <= 0)
-                       return -1;
-               if ((newline = memchr(bp, '\n', n)) != NULL)
-                       n = newline - bp + 1;
-               if ((n = ssl_read(ssl, bp, n)) < 0)
-                       return -1;
-               bp += n;
-               len -= n;
-       } while (!newline && len);
-
-       *bp = '\0';
-       return bp - buf;
-}
-#endif
-
-gint sock_gets(SockInfo *sock, gchar *buf, gint len)
-{
-       gint ret;
-
-       g_return_val_if_fail(sock != NULL, -1);
-
-#if USE_OPENSSL
-       if (sock->ssl)
-               return ssl_gets(sock->ssl, buf, len);
-       else
-#endif
-               return fd_gets(sock->sock, buf, len);
-
-       if (ret < 0)
-               sock->state = CONN_DISCONNECTED;
-       return ret;
-}
-
-/* peek at the socket data without actually reading it */
-#if USE_OPENSSL
-static gint ssl_peek(SSL *ssl, gchar *buf, gint len)
-{
-       gint err, ret;
-
-       if (SSL_pending(ssl) == 0) {
-               if (fd_check_io(SSL_get_rfd(ssl), G_IO_IN) < 0)
-                       return -1;
-       }
-
-       ret = SSL_peek(ssl, buf, len);
-
-       switch ((err = SSL_get_error(ssl, ret))) {
-       case SSL_ERROR_NONE:
-               return ret;
-       case SSL_ERROR_WANT_READ:
-       case SSL_ERROR_WANT_WRITE:
-               errno = EAGAIN;
-               return -1;
-       case SSL_ERROR_ZERO_RETURN:
-               return 0;
-       case SSL_ERROR_SYSCALL:
-               g_warning("SSL_peek() returned syscall error. errno=%d\n", errno);
-               return -1;
-       default:
-               g_warning("SSL_peek() returned error %d, ret = %d\n", err, ret);
-               if (ret == 0)
-                       return 0;
-               return -1;
-       }
-}
-#endif
-
 gint sock_close(SockInfo *sock)
 {
        gint ret;
@@ -1558,7 +1539,7 @@ gint sock_close(SockInfo *sock)
        if (sock->sock_ch)
                g_io_channel_unref(sock->sock_ch);
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        if (sock->ssl)
                ssl_done_socket(sock);
        if (sock->g_source != 0)
index 916ba39..d017ee9 100644 (file)
@@ -35,7 +35,7 @@
 
 typedef struct _SockInfo       SockInfo;
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #  include "ssl.h"
 #endif
 
@@ -61,6 +61,9 @@ struct _SockInfo
 #if USE_OPENSSL
        SSL *ssl;
        guint g_source;
+#elif USE_GNUTLS
+       gnutls_session ssl;
+       guint g_source;
 #endif
        GIOChannel *sock_ch;
 
@@ -97,7 +100,6 @@ gint sock_connect_async_cancel               (gint id);
 gint sock_read         (SockInfo *sock, gchar *buf, gint len);
 gint sock_write                (SockInfo *sock, const gchar *buf, gint len);
 gint sock_write_all    (SockInfo *sock, const gchar *buf, gint len);
-gint sock_gets         (SockInfo *sock, gchar *buf, gint len);
 gint sock_close                (SockInfo *sock);
 
 /* Functions to directly work on FD.  They are needed for pipes */
index 0055117..8228543 100644 (file)
@@ -21,8 +21,7 @@
 #  include "config.h"
 #endif
 
-#if USE_OPENSSL
-
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #include "defs.h"
 
 #include <glib.h>
 
 #ifdef USE_PTHREAD
 typedef struct _thread_data {
+#ifdef USE_OPENSSL
        SSL *ssl;
+#else
+       gnutls_session ssl;
+#endif
        gboolean done;
 } thread_data;
 #endif
 
 
+#ifdef USE_OPENSSL
 static SSL_CTX *ssl_ctx;
+#endif
 
 void ssl_init(void)
 {
+#ifdef USE_OPENSSL
        SSL_METHOD *meth;
 
        /* Global system initialization*/
@@ -73,14 +79,21 @@ void ssl_init(void)
 #if (OPENSSL_VERSION_NUMBER < 0x0090600fL)
        SSL_CTX_set_verify_depth(ssl_ctx,1);
 #endif
+#else
+       gnutls_global_init();
+#endif
 }
 
 void ssl_done(void)
 {
+#if USE_OPENSSL
        if (!ssl_ctx)
                return;
        
        SSL_CTX_free(ssl_ctx);
+#else
+       gnutls_global_deinit();
+#endif
 }
 
 #ifdef USE_PTHREAD
@@ -92,18 +105,31 @@ static void *SSL_connect_thread(void *data)
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
 
+#ifdef USE_OPENSSL
        result = SSL_connect(td->ssl);
+#else
+       do {
+               result = gnutls_handshake(td->ssl);
+       } while (result == GNUTLS_E_AGAIN || result == GNUTLS_E_INTERRUPTED);
+#endif
        td->done = TRUE; /* let the caller thread join() */
        return GINT_TO_POINTER(result);
 }
 #endif
 
+#ifdef USE_OPENSSL
 static gint SSL_connect_nb(SSL *ssl)
+#else
+static gint SSL_connect_nb(gnutls_session ssl)
+#endif
 {
 #if (defined USE_PTHREAD && ((defined __GLIBC__ && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3))) || !defined __GLIBC__))
        thread_data *td = g_new0(thread_data, 1);
        pthread_t pt;
        void *res = NULL;
+#ifdef USE_GNUTLS
+       int result;
+#endif
        time_t start_time = time(NULL);
        gboolean killed = FALSE;
        
@@ -114,9 +140,15 @@ static gint SSL_connect_nb(SSL *ssl)
         * fallback to blocking method in case of problem 
         */
        if (pthread_create(&pt, PTHREAD_CREATE_JOINABLE, 
-                       SSL_connect_thread, td) != 0)
+                       SSL_connect_thread, td) != 0) {
+#ifdef USE_OPENSSL
                return SSL_connect(ssl);
-       
+#else
+               do {
+                       result = gnutls_handshake(td->ssl);
+               } while (result == GNUTLS_E_AGAIN || result == GNUTLS_E_INTERRUPTED);
+#endif
+       }
        debug_print("waiting for SSL_connect thread...\n");
        while(!td->done) {
                /* don't let the interface freeze while waiting */
@@ -140,7 +172,13 @@ static gint SSL_connect_nb(SSL *ssl)
        
        return GPOINTER_TO_INT(res);
 #else
+#ifdef USE_OPENSSL
        return SSL_connect(ssl);
+#else
+       do {
+               result = gnutls_handshake(td->ssl);
+       } while (result == GNUTLS_E_AGAIN || result == GNUTLS_E_INTERRUPTED);
+#endif
 #endif
 }
 
@@ -149,8 +187,20 @@ gboolean ssl_init_socket(SockInfo *sockinfo)
        return ssl_init_socket_with_method(sockinfo, SSL_METHOD_SSLv23);
 }
 
+static const gchar *ssl_get_cert_file(void)
+{
+       if (g_getenv("SSL_CERT_FILE"))
+               return g_getenv("SSL_CERT_FILE");
+#ifndef G_OS_WIN32
+       return "/etc/ssl/certs/ca-certificates.crt";
+#else
+       return "put_what_s_needed_here";
+#endif
+}
+
 gboolean ssl_init_socket_with_method(SockInfo *sockinfo, SSLMethod method)
 {
+#ifdef USE_OPENSSL
        X509 *server_cert;
        SSL *ssl;
 
@@ -202,14 +252,93 @@ gboolean ssl_init_socket_with_method(SockInfo *sockinfo, SSLMethod method)
 
        X509_free(server_cert);
        sockinfo->ssl = ssl;
+#else
+       gnutls_session session;
+       int r;
+       const int cipher_prio[] = { GNUTLS_CIPHER_AES_128_CBC,
+                               GNUTLS_CIPHER_3DES_CBC,
+                               GNUTLS_CIPHER_AES_256_CBC,
+                               GNUTLS_CIPHER_ARCFOUR_128, 0 };
+       const int kx_prio[] = { GNUTLS_KX_DHE_RSA,
+                          GNUTLS_KX_RSA, 
+                          GNUTLS_KX_DHE_DSS, 0 };
+       const int mac_prio[] = { GNUTLS_MAC_SHA1,
+                               GNUTLS_MAC_MD5, 0 };
+       const int proto_prio[] = { GNUTLS_TLS1,
+                                 GNUTLS_SSL3, 0 };
+       const gnutls_datum *raw_cert_list;
+       unsigned int raw_cert_list_length;
+       gnutls_x509_crt cert = NULL;
+       guint status;
+       gnutls_certificate_credentials_t xcred;
+
+       if (gnutls_certificate_allocate_credentials (&xcred) != 0)
+               return FALSE;
+
+       r = gnutls_init(&session, GNUTLS_CLIENT);
+       if (session == NULL || r != 0)
+               return FALSE;
+  
+       gnutls_set_default_priority(session);
+       gnutls_protocol_set_priority (session, proto_prio);
+       gnutls_cipher_set_priority (session, cipher_prio);
+       gnutls_kx_set_priority (session, kx_prio);
+       gnutls_mac_set_priority (session, mac_prio);
+
+       gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, xcred);
+
+       r = gnutls_certificate_set_x509_trust_file(xcred, ssl_get_cert_file(),  GNUTLS_X509_FMT_PEM);
+       if (r < 0)
+               g_warning("Can't read SSL_CERT_FILE %s: %s\n",
+                       ssl_get_cert_file(), 
+                       gnutls_strerror(r));
+
+       gnutls_certificate_set_verify_flags (xcred, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
+
+       gnutls_transport_set_ptr(session, (gnutls_transport_ptr) 
+               sockinfo->sock);
+
+       if (SSL_connect_nb(session) == -1) {
+               g_warning("SSL connection failed");
+               gnutls_deinit(session);
+               return FALSE;
+       }
 
+       /* Get server's certificate (note: beware of dynamic allocation) */
+       raw_cert_list = gnutls_certificate_get_peers(session, &raw_cert_list_length);
+
+       if (!raw_cert_list 
+       ||  gnutls_certificate_type_get(session) != GNUTLS_CRT_X509
+       ||  (r = gnutls_x509_crt_init(&cert)) < 0
+       ||  (r = gnutls_x509_crt_import(cert, &raw_cert_list[0], GNUTLS_X509_FMT_DER)) < 0) {
+               g_warning("cert get failure: %d %s\n", r, gnutls_strerror(r));
+               gnutls_deinit(session);
+               return FALSE;
+       }
+
+       r = gnutls_certificate_verify_peers2(session, &status);
+
+       if (!ssl_certificate_check(cert, status, sockinfo->canonical_name, sockinfo->hostname, sockinfo->port)) {
+               gnutls_x509_crt_deinit(cert);
+               gnutls_deinit(session);
+               return FALSE;
+       }
+
+       gnutls_x509_crt_deinit(cert);
+
+       sockinfo->ssl = session;
+#endif
        return TRUE;
 }
 
 void ssl_done_socket(SockInfo *sockinfo)
 {
        if (sockinfo && sockinfo->ssl) {
+#ifdef USE_OPENSSL
                SSL_free(sockinfo->ssl);
+#else
+               gnutls_deinit(sockinfo->ssl);
+#endif
                sockinfo->ssl = NULL;
        }
 }
index 3e576ec..e016b6d 100644 (file)
@@ -30,16 +30,20 @@ typedef enum {
        SSL_STARTTLS
 } SSLType;
 
-#if USE_OPENSSL
-
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #include <glib.h>
+
+#if USE_OPENSSL
 #include <openssl/crypto.h>
 #include <openssl/x509.h>
 #include <openssl/pem.h>
 #include <openssl/ssl.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
-
+#else
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#endif
 #include "socket.h"
 
 typedef enum {
index 73e1638..7bdfc5f 100644 (file)
 #  include "config.h"
 #endif
 
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #if USE_OPENSSL
-
 #include <openssl/ssl.h>
+#else
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#endif
 #include <glib.h>
 #include <glib/gi18n.h>
 
@@ -33,6 +42,7 @@
 #include "log.h"
 #include "socket.h"
 #include "hooks.h"
+#include "defs.h"
 
 static GHashTable *warned_expired = NULL;
 
@@ -50,8 +60,12 @@ static gchar *get_certificate_path(const gchar *host, const gchar *port, const g
                          host, ".", port, ".cert", NULL);
 }
 
+#if USE_OPENSSL
 static SSLCertificate *ssl_certificate_new_lookup(X509 *x509_cert, gchar *host, gushort port, gboolean lookup);
-
+#else
+static SSLCertificate *ssl_certificate_new_lookup(gnutls_x509_crt x509_cert, gchar *host, gushort port, gboolean lookup);
+#endif
+#if USE_OPENSSL
 /* from Courier */
 time_t asn1toTime(ASN1_TIME *asn1Time)
 {
@@ -97,6 +111,7 @@ time_t asn1toTime(ASN1_TIME *asn1Time)
 
        return mktime(&tm)-offset;
 }
+#endif
 
 static char * get_fqdn(char *host)
 {
@@ -134,17 +149,68 @@ char * readable_fingerprint(unsigned char *src, int len)
        return ret;
 }
 
+#if USE_GNUTLS
+static gnutls_x509_crt x509_crt_copy(gnutls_x509_crt src)
+{
+    int ret;
+    size_t size;
+    gnutls_datum tmp;
+    gnutls_x509_crt dest;
+    
+    if (gnutls_x509_crt_init(&dest) != 0) {
+       g_warning("couldn't gnutls_x509_crt_init\n");
+        return NULL;
+    }
+
+    if (gnutls_x509_crt_export(src, GNUTLS_X509_FMT_DER, NULL, &size) 
+        != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+       g_warning("couldn't gnutls_x509_crt_export to get size\n");
+        gnutls_x509_crt_deinit(dest);
+        return NULL;
+    }
+
+    tmp.data = malloc(size);
+    memset(tmp.data, 0, size);
+    ret = gnutls_x509_crt_export(src, GNUTLS_X509_FMT_DER, tmp.data, &size);
+    if (ret == 0) {
+        tmp.size = size;
+        ret = gnutls_x509_crt_import(dest, &tmp, GNUTLS_X509_FMT_DER);
+       if (ret) {
+               g_warning("couldn't gnutls_x509_crt_import for real (%d %s)\n", ret, gnutls_strerror(ret));
+               gnutls_x509_crt_deinit(dest);
+               dest = NULL;
+       }
+    } else {
+       g_warning("couldn't gnutls_x509_crt_export for real (%d %s)\n", ret, gnutls_strerror(ret));
+        gnutls_x509_crt_deinit(dest);
+        dest = NULL;
+    }
+
+    free(tmp.data);
+    return dest;
+}
+#endif
+
+#if USE_OPENSSL
 static SSLCertificate *ssl_certificate_new_lookup(X509 *x509_cert, gchar *host, gushort port, gboolean lookup)
+#else
+static SSLCertificate *ssl_certificate_new_lookup(gnutls_x509_crt x509_cert, gchar *host, gushort port, gboolean lookup)
+#endif
 {
        SSLCertificate *cert = g_new0(SSLCertificate, 1);
        unsigned int n;
-       unsigned char md[EVP_MAX_MD_SIZE];      
-       
+       unsigned char md[128];  
+
        if (host == NULL || x509_cert == NULL) {
                ssl_certificate_destroy(cert);
                return NULL;
        }
+#if USE_OPENSSL
        cert->x509_cert = X509_dup(x509_cert);
+#else
+       cert->x509_cert = x509_crt_copy(x509_cert);
+       cert->status = (guint)-1;
+#endif
        if (lookup)
                cert->host = get_fqdn(host);
        else
@@ -152,11 +218,60 @@ static SSLCertificate *ssl_certificate_new_lookup(X509 *x509_cert, gchar *host,
        cert->port = port;
        
        /* fingerprint */
+#if USE_OPENSSL
        X509_digest(cert->x509_cert, EVP_md5(), md, &n);
        cert->fingerprint = readable_fingerprint(md, (int)n);
+#else
+       gnutls_x509_crt_get_fingerprint(cert->x509_cert, GNUTLS_DIG_MD5, md, &n);
+       cert->fingerprint = readable_fingerprint(md, (int)n);
+#endif
+       return cert;
+}
+
+#ifdef USE_GNUTLS
+static void i2d_X509_fp(FILE *fp, gnutls_x509_crt x509_cert)
+{
+       char output[10*1024];
+       size_t cert_size;
+       int r;
+       
+       if ((r = gnutls_x509_crt_export(x509_cert, GNUTLS_X509_FMT_DER, output, &cert_size)) < 0) {
+               g_warning("couldn't export cert %s\n", gnutls_strerror(r));
+               return;
+       }
+       debug_print("writing %zd bytes\n",cert_size);
+       if (fwrite(&output, 1, cert_size, fp) < cert_size) {
+               g_warning("failed to write cert\n");
+       }
+}
+static gnutls_x509_crt d2i_X509_fp(FILE *fp, int unused)
+{
+       gnutls_x509_crt cert = NULL;
+       gnutls_datum tmp;
+       struct stat s;
+       int r;
+       if (fstat(fileno(fp), &s) < 0) {
+               perror("fstat");
+               return NULL;
+       }
+       tmp.data = malloc(s.st_size);
+       memset(tmp.data, 0, s.st_size);
+       tmp.size = s.st_size;
+       if (fread (tmp.data, 1, s.st_size, fp) < s.st_size) {
+               perror("fread");
+               return NULL;
+       }
 
+       gnutls_x509_crt_init(&cert);
+       if ((r = gnutls_x509_crt_import(cert, &tmp, GNUTLS_X509_FMT_DER)) < 0) {
+               g_warning("import failed: %s\n", gnutls_strerror(r));
+               gnutls_x509_crt_deinit(cert);
+               cert = NULL;
+       }
+       debug_print("got cert! %p\n", cert);
        return cert;
 }
+#endif
 
 static void ssl_certificate_save (SSLCertificate *cert)
 {
@@ -186,94 +301,17 @@ static void ssl_certificate_save (SSLCertificate *cert)
 
 }
 
-char* ssl_certificate_to_string(SSLCertificate *cert)
-{
-       char *ret, buf[100];
-       char *issuer_commonname, *issuer_location, *issuer_organization;
-       char *subject_commonname, *subject_location, *subject_organization;
-       char *fingerprint, *sig_status;
-       unsigned int n;
-       unsigned char md[EVP_MAX_MD_SIZE];      
-       
-       /* issuer */    
-       if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), 
-                                      NID_commonName, buf, 100) >= 0)
-               issuer_commonname = g_strdup(buf);
-       else
-               issuer_commonname = g_strdup(_("<not in certificate>"));
-       if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), 
-                                      NID_localityName, buf, 100) >= 0) {
-               issuer_location = g_strdup(buf);
-               if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), 
-                                      NID_countryName, buf, 100) >= 0)
-                       issuer_location = g_strconcat(issuer_location,", ",buf, NULL);
-       } else if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), 
-                                      NID_countryName, buf, 100) >= 0)
-               issuer_location = g_strdup(buf);
-       else
-               issuer_location = g_strdup(_("<not in certificate>"));
-
-       if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), 
-                                      NID_organizationName, buf, 100) >= 0)
-               issuer_organization = g_strdup(buf);
-       else 
-               issuer_organization = g_strdup(_("<not in certificate>"));
-        
-       /* subject */   
-       if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert->x509_cert), 
-                                      NID_commonName, buf, 100) >= 0)
-               subject_commonname = g_strdup(buf);
-       else
-               subject_commonname = g_strdup(_("<not in certificate>"));
-       if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert->x509_cert), 
-                                      NID_localityName, buf, 100) >= 0) {
-               subject_location = g_strdup(buf);
-               if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert->x509_cert), 
-                                      NID_countryName, buf, 100) >= 0)
-                       subject_location = g_strconcat(subject_location,", ",buf, NULL);
-       } else if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert->x509_cert), 
-                                      NID_countryName, buf, 100) >= 0)
-               subject_location = g_strdup(buf);
-       else
-               subject_location = g_strdup(_("<not in certificate>"));
-
-       if (X509_NAME_get_text_by_NID(X509_get_subject_name(cert->x509_cert), 
-                                      NID_organizationName, buf, 100) >= 0)
-               subject_organization = g_strdup(buf);
-       else 
-               subject_organization = g_strdup(_("<not in certificate>"));
-        
-       /* fingerprint */
-       X509_digest(cert->x509_cert, EVP_md5(), md, &n);
-       fingerprint = readable_fingerprint(md, (int)n);
-
-       /* signature */
-       sig_status = ssl_certificate_check_signer(cert->x509_cert);
-
-       ret = g_strdup_printf(_("  Owner: %s (%s) in %s\n  Signed by: %s (%s) in %s\n  Fingerprint: %s\n  Signature status: %s"),
-                               subject_commonname, subject_organization, subject_location, 
-                               issuer_commonname, issuer_organization, issuer_location, 
-                               fingerprint,
-                               (sig_status==NULL ? "correct":sig_status));
-
-       g_free(issuer_commonname);
-       g_free(issuer_location);
-       g_free(issuer_organization);
-       g_free(subject_commonname);
-       g_free(subject_location);
-       g_free(subject_organization);
-       g_free(fingerprint);
-       g_free(sig_status);
-       return ret;
-}
-       
 void ssl_certificate_destroy(SSLCertificate *cert) 
 {
        if (cert == NULL)
                return;
 
        if (cert->x509_cert)
+#if USE_OPENSSL
                X509_free(cert->x509_cert);
+#else
+               gnutls_x509_crt_deinit(cert->x509_cert);
+#endif
        g_free(cert->host);
        g_free(cert->fingerprint);
        g_free(cert);
@@ -302,7 +340,11 @@ SSLCertificate *ssl_certificate_find_lookup (gchar *host, gushort port, const gc
        gchar *buf;
        gchar *fqdn_host;
        SSLCertificate *cert = NULL;
+#if USE_OPENSSL
        X509 *tmp_x509;
+#else
+       gnutls_x509_crt tmp_x509;
+#endif
        FILE *fp = NULL;
        gboolean must_rename = FALSE;
 
@@ -319,12 +361,17 @@ SSLCertificate *ssl_certificate_find_lookup (gchar *host, gushort port, const gc
        }
        if (fp == NULL) {
                /* see if we have the old one */
+               debug_print("didn't get %s\n", file);
                g_free(file);
                file = get_certificate_path(fqdn_host, buf, NULL);
                fp = g_fopen(file, "rb");
 
-               if (fp)
+               if (fp) {
+                       debug_print("got %s\n", file);
                        must_rename = (fingerprint != NULL);
+               }
+       } else {
+               debug_print("got %s first try\n", file);
        }
        if (fp == NULL) {
                g_free(file);
@@ -335,7 +382,12 @@ SSLCertificate *ssl_certificate_find_lookup (gchar *host, gushort port, const gc
        
        if ((tmp_x509 = d2i_X509_fp(fp, 0)) != NULL) {
                cert = ssl_certificate_new_lookup(tmp_x509, fqdn_host, port, lookup);
+               debug_print("got cert %p\n", cert);
+#if USE_OPENSSL
                X509_free(tmp_x509);
+#else
+               gnutls_x509_crt_deinit(tmp_x509);
+#endif
        }
        fclose(fp);
        g_free(file);
@@ -356,14 +408,58 @@ SSLCertificate *ssl_certificate_find_lookup (gchar *host, gushort port, const gc
 
 static gboolean ssl_certificate_compare (SSLCertificate *cert_a, SSLCertificate *cert_b)
 {
-       if (cert_a == NULL || cert_b == NULL)
-               return FALSE;
+#ifdef USE_OPENSSL
+       if (cert_a == NULL || cert_b == NULL)
+               return FALSE;
        else if (!X509_cmp(cert_a->x509_cert, cert_b->x509_cert))
                return TRUE;
        else
                return FALSE;
+#else
+       char *output_a;
+       char *output_b;
+       size_t cert_size_a, cert_size_b;
+       int r;
+
+       if (cert_a == NULL || cert_b == NULL)
+               return FALSE;
+
+       if ((r = gnutls_x509_crt_export(cert_a->x509_cert, GNUTLS_X509_FMT_DER, NULL, &cert_size_a)) 
+           != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+               g_warning("couldn't gnutls_x509_crt_export to get size a %s\n", gnutls_strerror(r));
+               return FALSE;
+       }
+
+       if ((r = gnutls_x509_crt_export(cert_b->x509_cert, GNUTLS_X509_FMT_DER, NULL, &cert_size_b))
+           != GNUTLS_E_SHORT_MEMORY_BUFFER) {
+               g_warning("couldn't gnutls_x509_crt_export to get size b %s\n", gnutls_strerror(r));
+               return FALSE;
+       }
+
+       output_a = malloc(cert_size_a);
+       output_b = malloc(cert_size_b);
+       if ((r = gnutls_x509_crt_export(cert_a->x509_cert, GNUTLS_X509_FMT_DER, output_a, &cert_size_a)) < 0) {
+               g_warning("couldn't gnutls_x509_crt_export a %s\n", gnutls_strerror(r));
+               return FALSE;
+       }
+       if ((r = gnutls_x509_crt_export(cert_b->x509_cert, GNUTLS_X509_FMT_DER, output_b, &cert_size_b)) < 0) {
+               g_warning("couldn't gnutls_x509_crt_export b %s\n", gnutls_strerror(r));
+               return FALSE;
+       }
+       if (cert_size_a != cert_size_b) {
+               g_warning("size differ %d %d\n", cert_size_a, cert_size_b);
+               return FALSE;
+       }
+       if (memcmp(output_a, output_b, cert_size_a)) {
+               g_warning("contents differ\n");
+               return FALSE;
+       }
+       
+       return TRUE;
+#endif
 }
 
+#if USE_OPENSSL
 char *ssl_certificate_check_signer (X509 *cert) 
 {
        X509_STORE_CTX store_ctx;
@@ -395,8 +491,33 @@ char *ssl_certificate_check_signer (X509 *cert)
        X509_STORE_free (store);
        return NULL;
 }
+#else
+char *ssl_certificate_check_signer (gnutls_x509_crt cert, guint status) 
+{
+       if (status == (guint)-1)
+               return g_strdup(_("Uncheckable"));
+
+       if (status & GNUTLS_CERT_INVALID) {
+               if (gnutls_x509_crt_check_issuer(cert, cert))
+                       return g_strdup(_("Self-signed certificate"));
+       }
+       if (status & GNUTLS_CERT_REVOKED)
+               return g_strdup(_("Revoked certificate"));
+       if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
+               return g_strdup(_("No certificate issuer found"));
+       if (status & GNUTLS_CERT_SIGNER_NOT_CA)
+               return g_strdup(_("Certificate issuer is not a CA"));
+
 
+       return NULL;
+}
+#endif
+
+#if USE_OPENSSL
 gboolean ssl_certificate_check (X509 *x509_cert, gchar *fqdn, gchar *host, gushort port)
+#else
+gboolean ssl_certificate_check (gnutls_x509_crt x509_cert, guint status, gchar *fqdn, gchar *host, gushort port)
+#endif
 {
        SSLCertificate *current_cert = NULL;
        SSLCertificate *known_cert;
@@ -404,7 +525,7 @@ gboolean ssl_certificate_check (X509 *x509_cert, gchar *fqdn, gchar *host, gusho
        gchar *fqdn_host = NULL;        
        gchar *fingerprint;
        unsigned int n;
-       unsigned char md[EVP_MAX_MD_SIZE];      
+       unsigned char md[128];  
 
        if (fqdn)
                fqdn_host = g_strdup(fqdn);
@@ -423,9 +544,18 @@ gboolean ssl_certificate_check (X509 *x509_cert, gchar *fqdn, gchar *host, gusho
                return FALSE;
        }
 
+#if USE_GNUTLS
+       current_cert->status = status;
+#endif
        /* fingerprint */
+#if USE_OPENSSL
        X509_digest(x509_cert, EVP_md5(), md, &n);
        fingerprint = readable_fingerprint(md, (int)n);
+#else
+       n = 128;
+       gnutls_x509_crt_get_fingerprint(x509_cert, GNUTLS_DIG_MD5, md, &n);
+       fingerprint = readable_fingerprint(md, (int)n);
+#endif
 
        known_cert = ssl_certificate_find_lookup (fqdn_host, port, fingerprint, FALSE);
 
@@ -466,7 +596,11 @@ gboolean ssl_certificate_check (X509 *x509_cert, gchar *fqdn, gchar *host, gusho
                        ssl_certificate_destroy(known_cert);
                        return TRUE;
                }
+#if USE_OPENSSL
        } else if (asn1toTime(X509_get_notAfter(current_cert->x509_cert)) < time(NULL)) {
+#else
+       } else if (gnutls_x509_crt_get_expiration_time(current_cert->x509_cert) < time(NULL)) {
+#endif
                gchar *tmp = g_strdup_printf("%s:%d", current_cert->host, current_cert->port);
                
                if (warned_expired == NULL)
index da8039e..932affe 100644 (file)
 #  include "config.h"
 #endif
 
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #if USE_OPENSSL
-
 #include <openssl/ssl.h>
 #include <openssl/objects.h>
+#else
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#endif
+
 #include <glib.h>
 
 #define SSLCERT_ASK_HOOKLIST "sslcert_ask"
@@ -37,10 +42,17 @@ typedef struct _SSLCertificate SSLCertificate;
 
 struct _SSLCertificate
 {
+#if USE_OPENSSL
        X509 *x509_cert;
+#else
+       gnutls_x509_crt x509_cert;
+#endif
        gchar *host;
        gushort port;
        gchar *fingerprint;
+#if USE_GNUTLS
+       guint status;
+#endif
 };
 
 typedef struct _SSLCertHookData SSLCertHookData;
@@ -55,13 +67,20 @@ struct _SSLCertHookData
 
 SSLCertificate *ssl_certificate_find (gchar *host, gushort port, const gchar *fingerprint);
 SSLCertificate *ssl_certificate_find_lookup (gchar *host, gushort port, const gchar *fingerprint, gboolean lookup);
+#if USE_OPENSSL
 gboolean ssl_certificate_check (X509 *x509_cert, gchar *fqdn, gchar *host, gushort port);
-char* ssl_certificate_to_string(SSLCertificate *cert);
+#else
+gboolean ssl_certificate_check (gnutls_x509_crt x509_cert, guint status, gchar *fqdn, gchar *host, gushort port);
+#endif
 void ssl_certificate_destroy(SSLCertificate *cert);
 void ssl_certificate_delete_from_disk(SSLCertificate *cert);
 char * readable_fingerprint(unsigned char *src, int len);
+#if USE_OPENSSL
 char *ssl_certificate_check_signer (X509 *cert);
 time_t asn1toTime(ASN1_TIME *asn1Time);
+#else
+char *ssl_certificate_check_signer (gnutls_x509_crt cert, guint status);
+#endif
 
 #endif /* USE_OPENSSL */
 #endif /* SSL_CERTIFICATE_H */
index b2b6c08..46e0ab6 100644 (file)
@@ -418,6 +418,9 @@ static const gchar *get_compiled_in_features(void)
 #if USE_OPENSSL
                   " OpenSSL"
 #endif
+#if USE_GNUTLS
+                  " GnuTLS"
+#endif
 #if USE_LDAP
                   " LDAP"
 #endif
index 8e7df70..c587cfb 100644 (file)
@@ -4,14 +4,16 @@ noinst_LTLIBRARIES = libclawsetpan.la
 
 libclawsetpan_la_SOURCES = \
        etpan-thread-manager.c \
-       imap-thread.c
+       imap-thread.c \
+       nntp-thread.c
 
 clawsetpanincludedir = $(pkgincludedir)/etpan
 clawsetpaninclude_HEADERS = \
        etpan-thread-manager-types.h \
        etpan-thread-manager.h \
        etpan-errors.h \
-       imap-thread.h
+       imap-thread.h \
+       nntp-thread.h
 
 INCLUDES = \
        -I$(top_srcdir)/src \
index 11dbb6e..8047b1f 100644 (file)
@@ -70,6 +70,7 @@ struct etpan_thread_op {
   void * result;
   int finished;
   mailimap *imap;
+  newsnntp *nntp;
 };
 
 #endif
index 212a19f..7b8dce7 100644 (file)
@@ -196,6 +196,7 @@ struct etpan_thread_op * etpan_thread_op_new(void)
   op->result = NULL;
   op->finished = 0;
   op->imap = NULL;
+  op->nntp = NULL;
 
   r = pthread_mutex_init(&op->lock, NULL);
   if (r != 0)
index dd95a57..14355a8 100644 (file)
@@ -247,7 +247,7 @@ static void imap_logger_append(int direction, const char * str, size_t size)
 }
 
 #define ETPAN_DEFAULT_NETWORK_TIMEOUT 60
-static gboolean etpan_skip_ssl_cert_check = FALSE;
+gboolean etpan_skip_ssl_cert_check = FALSE;
 extern void mailsasl_ref(void);
 
 void imap_main_init(gboolean skip_ssl_cert_check)
@@ -508,7 +508,7 @@ static int etpan_certificate_check(const unsigned char *certificate, int len, vo
        }
        cert = d2i_X509(NULL, (const unsigned char **)&certificate, len);
        if (cert == NULL) {
-               g_warning("can't get cert\n");
+               g_warning("IMAP: can't get cert\n");
                return 0;
        } else if (ssl_certificate_check(cert, NULL,
                (gchar *)param->server, (gushort)param->port) == TRUE) {
@@ -518,9 +518,33 @@ static int etpan_certificate_check(const unsigned char *certificate, int len, vo
                X509_free(cert);
                return -1;
        }
-#else
-       return 0;
+#elif USE_GNUTLS
+       struct connect_param *param = (struct connect_param *)data;
+       gnutls_x509_crt cert = NULL;
+       gnutls_datum tmp;
+       
+       if (certificate == NULL || len < 0) {
+               g_warning("no cert presented.\n");
+               return 0;
+       }
+       
+       tmp.data = malloc(len);
+       memcpy(tmp.data, certificate, len);
+       tmp.size = len;
+       gnutls_x509_crt_init(&cert);
+       if (gnutls_x509_crt_import(cert, &tmp, GNUTLS_X509_FMT_DER) < 0) {
+               g_warning("IMAP: can't get cert\n");
+               return 0;
+       } else if (ssl_certificate_check(cert, (guint)-1, NULL,
+               (gchar *)param->server, (gushort)param->port) == TRUE) {
+               gnutls_x509_crt_deinit(cert);
+               return 0;
+       } else {
+               gnutls_x509_crt_deinit(cert);
+               return -1;
+       }
 #endif
+       return 0;
 }
 
 static void connect_ssl_run(struct etpan_thread_op * op)
diff --git a/src/etpan/nntp-thread.c b/src/etpan/nntp-thread.c
new file mode 100644 (file)
index 0000000..463e615
--- /dev/null
@@ -0,0 +1,946 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2005-2007 DINH Viet Hoa and the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#ifdef HAVE_LIBETPAN
+
+#include "nntp-thread.h"
+#include "news.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#if (defined(__DragonFly__) || defined (__NetBSD__) || defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__CYGWIN__))
+#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"
+#include "mainwindow.h"
+#include "ssl_certificate.h"
+#include "socket.h"
+#include "remotefolder.h"
+
+#define DISABLE_LOG_DURING_LOGIN
+
+static struct etpan_thread_manager * thread_manager = NULL;
+static chash * courier_workaround_hash = NULL;
+static chash * nntp_hash = NULL;
+static chash * session_hash = NULL;
+static guint thread_manager_signal = 0;
+static GIOChannel * io_channel = NULL;
+
+static void (*previous_stream_logger)(int direction,
+    const char * str, size_t size);
+
+static void nntp_logger(int direction, const char * str, size_t size) 
+{
+       gchar *buf;
+       gchar **lines;
+       int i = 0;
+
+       if (size > 256) {
+               log_print(LOG_PROTOCOL, "NNTP%c [data - %zd bytes]\n", direction?'>':'<', size);
+               return;
+       }
+       buf = malloc(size+1);
+       memset(buf, 0, size+1);
+       strncpy(buf, str, size);
+       buf[size] = '\0';
+
+       if (!strncmp(buf, "<<<<<<<", 7) 
+       ||  !strncmp(buf, ">>>>>>>", 7)) {
+               free(buf);
+               return;
+       }
+       while (strstr(buf, "\r"))
+               *strstr(buf, "\r") = ' ';
+       while (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
+               buf[strlen(buf)-1] = '\0';
+
+       lines = g_strsplit(buf, "\n", -1);
+
+       while (lines[i] && *lines[i]) {
+               log_print(LOG_PROTOCOL, "NNTP%c %s\n", direction?'>':'<', lines[i]);
+               i++;
+       }
+       g_strfreev(lines);
+       free(buf);
+}
+
+static void delete_nntp(Folder *folder, newsnntp *nntp)
+{
+       chashdatum key;
+       chashdatum value;
+
+       key.data = &folder;
+       key.len = sizeof(folder);
+       value.data = nntp;
+       value.len = 0;
+       chash_delete(session_hash, &key, NULL);
+       
+       key.data = &nntp;
+       key.len = sizeof(nntp);
+       if (nntp && nntp->nntp_stream) {
+               /* we don't want libetpan to logout */
+               mailstream_close(nntp->nntp_stream);
+               nntp->nntp_stream = NULL;
+       }
+       debug_print("removing newsnntp %p\n", nntp);
+       newsnntp_free(nntp);    
+}
+
+static gboolean thread_manager_event(GIOChannel * source,
+    GIOCondition condition,
+    gpointer data)
+{
+       etpan_thread_manager_loop(thread_manager);
+       
+       return TRUE;
+}
+
+#define ETPAN_DEFAULT_NETWORK_TIMEOUT 60
+extern gboolean etpan_skip_ssl_cert_check;
+
+void nntp_main_init(gboolean skip_ssl_cert_check)
+{
+       int fd_thread_manager;
+       
+       etpan_skip_ssl_cert_check = skip_ssl_cert_check;
+       
+       nntp_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();
+       
+       fd_thread_manager = etpan_thread_manager_get_fd(thread_manager);
+       
+       io_channel = g_io_channel_unix_new(fd_thread_manager);
+       
+       thread_manager_signal = g_io_add_watch_full(io_channel, 0, G_IO_IN,
+                                                   thread_manager_event,
+                                                   (gpointer) NULL,
+                                                   NULL);
+}
+
+void nntp_main_done(void)
+{
+       etpan_thread_manager_stop(thread_manager);
+       etpan_thread_manager_join(thread_manager);
+       
+       g_source_remove(thread_manager_signal);
+       g_io_channel_unref(io_channel);
+       
+       etpan_thread_manager_free(thread_manager);
+       
+       chash_free(session_hash);
+       chash_free(nntp_hash);
+}
+
+void nntp_init(Folder * folder)
+{
+       struct etpan_thread * thread;
+       chashdatum key;
+       chashdatum value;
+       
+       thread = etpan_thread_manager_get_thread(thread_manager);
+       
+       key.data = &folder;
+       key.len = sizeof(folder);
+       value.data = thread;
+       value.len = 0;
+       
+       chash_set(nntp_hash, &key, &value, NULL);
+}
+
+void nntp_done(Folder * folder)
+{
+       struct etpan_thread * thread;
+       chashdatum key;
+       chashdatum value;
+       int r;
+       
+       key.data = &folder;
+       key.len = sizeof(folder);
+       
+       r = chash_get(nntp_hash, &key, &value);
+       if (r < 0)
+               return;
+       
+       thread = value.data;
+       
+       etpan_thread_unbind(thread);
+       
+       chash_delete(nntp_hash, &key, NULL);
+       
+       debug_print("remove thread");
+}
+
+static struct etpan_thread * get_thread(Folder * folder)
+{
+       struct etpan_thread * thread;
+       chashdatum key;
+       chashdatum value;
+       
+       key.data = &folder;
+       key.len = sizeof(folder);
+       
+       chash_get(nntp_hash, &key, &value);
+       thread = value.data;
+       
+       return thread;
+}
+
+static newsnntp * get_nntp(Folder * folder)
+{
+       newsnntp * nntp;
+       chashdatum key;
+       chashdatum value;
+       int r;
+       
+       key.data = &folder;
+       key.len = sizeof(folder);
+       
+       r = chash_get(session_hash, &key, &value);
+       if (r < 0)
+               return NULL;
+       
+       nntp = value.data;
+       debug_print("found nntp %p\n", nntp);
+       return nntp;
+}
+
+
+static void generic_cb(int cancelled, void * result, void * callback_data)
+{
+       struct etpan_thread_op * op;
+       
+       op = (struct etpan_thread_op *) callback_data;
+
+       debug_print("generic_cb\n");
+       op->finished = 1;
+}
+
+static void threaded_run(Folder * folder, void * param, void * result,
+                        void (* func)(struct etpan_thread_op * ))
+{
+       struct etpan_thread_op * op;
+       struct etpan_thread * thread;
+       
+       nntp_folder_ref(folder);
+
+       op = etpan_thread_op_new();
+       
+       op->nntp = get_nntp(folder);
+       op->param = param;
+       op->result = result;
+       
+       op->cancellable = 0;
+       op->run = func;
+       op->callback = generic_cb;
+       op->callback_data = op;
+       op->cleanup = NULL;
+       
+       op->finished = 0;
+       
+       previous_stream_logger = mailstream_logger;
+       mailstream_logger = nntp_logger;
+
+       thread = get_thread(folder);
+       etpan_thread_op_schedule(thread, op);
+       
+       while (!op->finished) {
+               gtk_main_iteration();
+       }
+       
+       mailstream_logger = previous_stream_logger;
+
+       etpan_thread_op_free(op);
+
+       nntp_folder_unref(folder);
+}
+
+
+/* connect */
+
+struct connect_param {
+       newsnntp * nntp;
+       const char * server;
+       int port;
+};
+
+struct connect_result {
+       int error;
+};
+
+#define CHECK_NNTP() {                                         \
+       if (!param->nntp) {                                     \
+               result->error = NEWSNNTP_ERROR_BAD_STATE;       \
+               return;                                         \
+       }                                                       \
+}
+
+static void connect_run(struct etpan_thread_op * op)
+{
+       int r;
+       struct connect_param * param;
+       struct connect_result * result;
+       
+       param = op->param;
+       result = op->result;
+       
+       CHECK_NNTP();
+
+       r = newsnntp_socket_connect(param->nntp,
+                                   param->server, param->port);
+       
+       result->error = r;
+}
+
+
+int nntp_threaded_connect(Folder * folder, const char * server, int port)
+{
+       struct connect_param param;
+       struct connect_result result;
+       chashdatum key;
+       chashdatum value;
+       newsnntp * nntp, * oldnntp;
+       
+       oldnntp = get_nntp(folder);
+
+       nntp = newsnntp_new(0, NULL);
+       
+       if (oldnntp) {
+               debug_print("deleting old nntp %p\n", oldnntp);
+               delete_nntp(folder, oldnntp);
+       }
+       
+       key.data = &folder;
+       key.len = sizeof(folder);
+       value.data = nntp;
+       value.len = 0;
+       chash_set(session_hash, &key, &value, NULL);
+       
+       param.nntp = nntp;
+       param.server = server;
+       param.port = port;
+       
+       refresh_resolvers();
+       threaded_run(folder, &param, &result, connect_run);
+       
+       debug_print("connect ok %i with nntp %p\n", result.error, nntp);
+       
+       return result.error;
+}
+
+static int etpan_certificate_check(const unsigned char *certificate, int len, void *data)
+{
+#ifdef USE_OPENSSL
+       struct connect_param *param = (struct connect_param *)data;
+       X509 *cert = NULL;
+       
+       if (certificate == NULL || len < 0) {
+               g_warning("no cert presented.\n");
+               return 0;
+       }
+       cert = d2i_X509(NULL, (const unsigned char **)&certificate, len);
+       if (cert == NULL) {
+               g_warning("nntp: can't get cert\n");
+               return 0;
+       } else if (ssl_certificate_check(cert, NULL,
+               (gchar *)param->server, (gushort)param->port) == TRUE) {
+               X509_free(cert);
+               return 0;
+       } else {
+               X509_free(cert);
+               return -1;
+       }
+#elif USE_GNUTLS
+       struct connect_param *param = (struct connect_param *)data;
+       gnutls_x509_crt cert = NULL;
+       gnutls_datum tmp;
+       
+       if (certificate == NULL || len < 0) {
+               g_warning("no cert presented.\n");
+               return 0;
+       }
+       
+       tmp.data = malloc(len);
+       memcpy(tmp.data, certificate, len);
+       tmp.size = len;
+       gnutls_x509_crt_init(&cert);
+       if (gnutls_x509_crt_import(cert, &tmp, GNUTLS_X509_FMT_DER) < 0) {
+               g_warning("nntp: can't get cert\n");
+               return 0;
+       } else if (ssl_certificate_check(cert, (guint)-1, NULL,
+               (gchar *)param->server, (gushort)param->port) == TRUE) {
+               gnutls_x509_crt_deinit(cert);
+               return 0;
+       } else {
+               gnutls_x509_crt_deinit(cert);
+               return -1;
+       }
+#endif
+       return 0;
+}
+
+static void connect_ssl_run(struct etpan_thread_op * op)
+{
+       int r;
+       struct connect_param * param;
+       struct connect_result * result;
+       
+       param = op->param;
+       result = op->result;
+       
+       CHECK_NNTP();
+
+       r = newsnntp_ssl_connect(param->nntp,
+                                param->server, param->port);
+       result->error = r;
+}
+
+int nntp_threaded_connect_ssl(Folder * folder, const char * server, int port)
+{
+       struct connect_param param;
+       struct connect_result result;
+       chashdatum key;
+       chashdatum value;
+       newsnntp * nntp, * oldnntp;
+       unsigned char *certificate = NULL;
+       int cert_len;
+       
+       oldnntp = get_nntp(folder);
+
+       nntp = newsnntp_new(0, NULL);
+       
+       if (oldnntp) {
+               debug_print("deleting old nntp %p\n", oldnntp);
+               delete_nntp(folder, oldnntp);
+       }
+
+       key.data = &folder;
+       key.len = sizeof(folder);
+       value.data = nntp;
+       value.len = 0;
+       chash_set(session_hash, &key, &value, NULL);
+       
+       param.nntp = nntp;
+       param.server = server;
+       param.port = port;
+       
+       refresh_resolvers();
+       threaded_run(folder, &param, &result, connect_ssl_run);
+
+       if (result.error == NEWSNNTP_NO_ERROR && !etpan_skip_ssl_cert_check) {
+               cert_len = (int)mailstream_ssl_get_certificate(nntp->nntp_stream, &certificate);
+               if (etpan_certificate_check(certificate, cert_len, &param) < 0)
+                       return -1;
+               if (certificate) 
+                       free(certificate); 
+       }
+       debug_print("connect %d with nntp %p\n", result.error, nntp);
+       
+       return result.error;
+}
+
+void nntp_threaded_disconnect(Folder * folder)
+{
+       newsnntp * nntp;
+       
+       nntp = get_nntp(folder);
+       if (nntp == NULL) {
+               debug_print("was disconnected\n");
+               return;
+       }
+       
+       debug_print("deleting old nntp %p\n", nntp);
+       delete_nntp(folder, nntp);
+       
+       debug_print("disconnect ok\n");
+}
+
+void nntp_threaded_cancel(Folder * folder)
+{
+       newsnntp * nntp;
+       
+       nntp = get_nntp(folder);
+       if (nntp->nntp_stream != NULL)
+               mailstream_cancel(nntp->nntp_stream);
+}
+
+
+struct login_param {
+       newsnntp * nntp;
+       const char * login;
+       const char * password;
+};
+
+struct login_result {
+       int error;
+};
+
+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;
+       result = op->result;
+
+       CHECK_NNTP();
+
+#ifdef DISABLE_LOG_DURING_LOGIN
+       old_debug = mailstream_debug;
+       mailstream_debug = 0;
+#endif
+
+       r = newsnntp_authinfo_username(param->nntp, param->login);
+       if (r == NEWSNNTP_NO_ERROR) {
+               r = newsnntp_authinfo_password(param->nntp, param->password);
+       }
+       
+
+
+#ifdef DISABLE_LOG_DURING_LOGIN
+       mailstream_debug = old_debug;
+#endif
+       
+       result->error = r;
+       debug_print("nntp login run - end %i\n", r);
+}
+
+int nntp_threaded_login(Folder * folder, const char * login, const char * password)
+{
+       struct login_param param;
+       struct login_result result;
+       
+       debug_print("nntp login - begin\n");
+       
+       param.nntp = get_nntp(folder);
+       param.login = login;
+       param.password = password;
+
+       threaded_run(folder, &param, &result, login_run);
+       
+       debug_print("nntp login - end\n");
+       
+       return result.error;
+}
+
+struct date_param {
+       newsnntp * nntp;
+       struct tm * lt;
+};
+
+struct date_result {
+       int error;
+};
+
+static void date_run(struct etpan_thread_op * op)
+{
+       struct date_param * param;
+       struct date_result * result;
+       int r;
+       
+       param = op->param;
+       result = op->result;
+
+       CHECK_NNTP();
+
+       r = newsnntp_date(param->nntp, param->lt);
+       
+       result->error = r;
+       debug_print("nntp date run - end %i\n", r);
+}
+
+int nntp_threaded_date(Folder * folder, struct tm *lt)
+{
+       struct date_param param;
+       struct date_result result;
+       
+       debug_print("nntp date - begin\n");
+       
+       param.nntp = get_nntp(folder);
+       param.lt = lt;
+
+       threaded_run(folder, &param, &result, date_run);
+       
+       debug_print("nntp date - end\n");
+       
+       return result.error;
+}
+
+struct list_param {
+       newsnntp * nntp;
+       clist **grouplist;
+};
+
+struct list_result {
+       int error;
+};
+
+static void list_run(struct etpan_thread_op * op)
+{
+       struct list_param * param;
+       struct list_result * result;
+       int r;
+       
+       param = op->param;
+       result = op->result;
+
+       CHECK_NNTP();
+
+       r = newsnntp_list(param->nntp, param->grouplist);
+       
+       result->error = r;
+       debug_print("nntp list run - end %i\n", r);
+}
+
+int nntp_threaded_list(Folder * folder, clist **grouplist)
+{
+       struct list_param param;
+       struct list_result result;
+       
+       debug_print("nntp list - begin\n");
+       
+       param.nntp = get_nntp(folder);
+       param.grouplist = grouplist;
+
+       threaded_run(folder, &param, &result, list_run);
+       
+       debug_print("nntp list - end\n");
+       
+       return result.error;
+}
+
+struct post_param {
+       newsnntp * nntp;
+       char *contents;
+       size_t len;
+};
+
+struct post_result {
+       int error;
+};
+
+static void post_run(struct etpan_thread_op * op)
+{
+       struct post_param * param;
+       struct post_result * result;
+       int r;
+       
+       param = op->param;
+       result = op->result;
+
+       CHECK_NNTP();
+
+       r = newsnntp_post(param->nntp, param->contents, param->len);
+       
+       result->error = r;
+       debug_print("nntp post run - end %i\n", r);
+}
+
+int nntp_threaded_post(Folder * folder, char *contents, size_t len)
+{
+       struct post_param param;
+       struct post_result result;
+       
+       debug_print("nntp post - begin\n");
+       
+       param.nntp = get_nntp(folder);
+       param.contents = contents;
+       param.len = len;
+
+       threaded_run(folder, &param, &result, post_run);
+       
+       debug_print("nntp post - end\n");
+       
+       return result.error;
+}
+
+struct article_param {
+       newsnntp * nntp;
+       guint32 num;
+       char **contents;
+       size_t *len;
+};
+
+struct article_result {
+       int error;
+};
+
+static void article_run(struct etpan_thread_op * op)
+{
+       struct article_param * param;
+       struct article_result * result;
+       int r;
+       
+       param = op->param;
+       result = op->result;
+
+       CHECK_NNTP();
+
+       r = newsnntp_article(param->nntp, param->num, param->contents, param->len);
+       
+       result->error = r;
+       debug_print("nntp article run - end %i\n", r);
+}
+
+int nntp_threaded_article(Folder * folder, guint32 num, char **contents, size_t *len)
+{
+       struct article_param param;
+       struct article_result result;
+       
+       debug_print("nntp article - begin\n");
+       
+       param.nntp = get_nntp(folder);
+       param.num = num;
+       param.contents = contents;
+       param.len = len;
+
+       threaded_run(folder, &param, &result, article_run);
+       
+       debug_print("nntp post - end\n");
+       
+       return result.error;
+}
+
+struct group_param {
+       newsnntp * nntp;
+       const char *group;
+       struct newsnntp_group_info **info;
+};
+
+struct group_result {
+       int error;
+};
+
+static void group_run(struct etpan_thread_op * op)
+{
+       struct group_param * param;
+       struct group_result * result;
+       int r;
+       
+       param = op->param;
+       result = op->result;
+
+       CHECK_NNTP();
+
+       r = newsnntp_group(param->nntp, param->group, param->info);
+       
+       result->error = r;
+       debug_print("nntp group run - end %i\n", r);
+}
+
+int nntp_threaded_group(Folder * folder, const char *group, struct newsnntp_group_info **info)
+{
+       struct group_param param;
+       struct group_result result;
+       
+       debug_print("nntp group - begin\n");
+       
+       param.nntp = get_nntp(folder);
+       param.group = group;
+       param.info = info;
+
+       threaded_run(folder, &param, &result, group_run);
+       
+       debug_print("nntp group - end\n");
+       
+       return result.error;
+}
+
+struct mode_reader_param {
+       newsnntp * nntp;
+};
+
+struct mode_reader_result {
+       int error;
+};
+
+static void mode_reader_run(struct etpan_thread_op * op)
+{
+       struct mode_reader_param * param;
+       struct mode_reader_result * result;
+       int r;
+       
+       param = op->param;
+       result = op->result;
+
+       CHECK_NNTP();
+
+       r = newsnntp_mode_reader(param->nntp);
+       
+       result->error = r;
+       debug_print("nntp mode_reader run - end %i\n", r);
+}
+
+int nntp_threaded_mode_reader(Folder * folder)
+{
+       struct mode_reader_param param;
+       struct mode_reader_result result;
+       
+       debug_print("nntp mode_reader - begin\n");
+       
+       param.nntp = get_nntp(folder);
+
+       threaded_run(folder, &param, &result, mode_reader_run);
+       
+       debug_print("nntp mode_reader - end\n");
+       
+       return result.error;
+}
+
+struct xover_param {
+       newsnntp * nntp;
+       guint32 beg;
+       guint32 end;
+       struct newsnntp_xover_resp_item **result;
+       clist **msglist;
+};
+
+struct xover_result {
+       int error;
+};
+
+static void xover_run(struct etpan_thread_op * op)
+{
+       struct xover_param * param;
+       struct xover_result * result;
+       int r;
+       
+       param = op->param;
+       result = op->result;
+
+       CHECK_NNTP();
+       
+       if (param->result) {
+               r = newsnntp_xover_single(param->nntp, param->beg, param->result);
+       } else {
+               r = newsnntp_xover_range(param->nntp, param->beg, param->end, param->msglist);
+       }
+       
+       result->error = r;
+       debug_print("nntp xover run - end %i\n", r);
+}
+
+int nntp_threaded_xover(Folder * folder, guint32 beg, guint32 end, struct newsnntp_xover_resp_item **single_result, clist **multiple_result)
+{
+       struct xover_param param;
+       struct xover_result result;
+       
+       debug_print("nntp xover - begin\n");
+       
+       param.nntp = get_nntp(folder);
+       param.beg = beg;
+       param.end = end;
+       param.result = single_result;
+       param.msglist = multiple_result;
+
+       threaded_run(folder, &param, &result, xover_run);
+       
+       debug_print("nntp xover - end\n");
+       
+       return result.error;
+}
+
+struct xhdr_param {
+       newsnntp * nntp;
+       const char *header;
+       guint32 beg;
+       guint32 end;
+       clist **hdrlist;
+};
+
+struct xhdr_result {
+       int error;
+};
+
+static void xhdr_run(struct etpan_thread_op * op)
+{
+       struct xhdr_param * param;
+       struct xhdr_result * result;
+       int r;
+       
+       param = op->param;
+       result = op->result;
+
+       CHECK_NNTP();
+       
+       if (param->beg == param->end) {
+               r = newsnntp_xhdr_single(param->nntp, param->header, param->beg, param->hdrlist);
+       } else {
+               r = -1;
+               g_warning("XHDR range not implemented\n");
+       }
+       
+       result->error = r;
+       debug_print("nntp xhdr run - end %i\n", r);
+}
+
+int nntp_threaded_xhdr(Folder * folder, const char *header, guint32 beg, guint32 end, clist **hdrlist)
+{
+       struct xhdr_param param;
+       struct xhdr_result result;
+       
+       debug_print("nntp xhdr - begin\n");
+       
+       param.nntp = get_nntp(folder);
+       param.header = header;
+       param.beg = beg;
+       param.end = end;
+       param.hdrlist = hdrlist;
+
+       threaded_run(folder, &param, &result, xhdr_run);
+       
+       debug_print("nntp xhdr - end\n");
+       
+       return result.error;
+}
+
+
+#else
+
+void nntp_main_init(void)
+{
+}
+void nntp_main_done(void)
+{
+}
+void nntp_main_set_timeout(int sec)
+{
+}
+
+void nntp_threaded_cancel(Folder * folder);
+{
+}
+
+#endif
diff --git a/src/etpan/nntp-thread.h b/src/etpan/nntp-thread.h
new file mode 100644 (file)
index 0000000..be0066e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2005-2007 DINH Viet Hoa and the Claws Mail team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
+ */
+
+#ifndef NNTP_THREAD_H
+
+#define NNTP_THREAD_H
+
+#include <libetpan/libetpan.h>
+#include "folder.h"
+
+void nntp_main_set_timeout(int sec);
+void nntp_main_init(gboolean skip_ssl_cert_check);
+void nntp_main_done(void);
+
+void nntp_init(Folder * folder);
+void nntp_done(Folder * folder);
+
+int nntp_threaded_connect(Folder * folder, const char * server, int port);
+int nntp_threaded_connect_ssl(Folder * folder, const char * server, int port);
+
+void nntp_threaded_disconnect(Folder * folder);
+
+void nntp_threaded_cancel(Folder * folder);
+
+int nntp_threaded_login(Folder * folder, const char * login, const char * password);
+int nntp_threaded_date(Folder * folder, struct tm *lt);
+int nntp_threaded_list(Folder * folder, clist **grouplist);
+int nntp_threaded_post(Folder * folder, char *contents, size_t len);
+int nntp_threaded_article(Folder * folder, guint32 num, char **contents, size_t *len);
+int nntp_threaded_group(Folder * folder, const char *group, struct newsnntp_group_info **info);
+int nntp_threaded_mode_reader(Folder * folder);
+int nntp_threaded_xover(Folder * folder, guint32 beg, guint32 end, struct newsnntp_xover_resp_item **single_result, clist **multiple_result);
+int nntp_threaded_xhdr(Folder * folder, const char *header, guint32 beg, guint32 end, clist **hdrlist);
+
+#endif
index 907a3b6..5f2597f 100644 (file)
@@ -453,6 +453,16 @@ static GtkWidget *about_create_child_page_features(void)
        gtk_text_buffer_insert(buffer, &iter, 
                (gchar *)Q_("OpenSSL|adds support for encrypted connections to servers\n"), -1);
 
+#if USE_GNUTLS
+       gtk_text_buffer_insert_pixbuf(buffer, &iter, active_pixbuf);
+#else
+       gtk_text_buffer_insert_pixbuf(buffer, &iter, inactive_pixbuf);
+#endif
+       gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, (" GnuTLS "), -1,
+                                                "bold", NULL);
+       gtk_text_buffer_insert(buffer, &iter, 
+               (gchar *)Q_("GnuTLS|is another mean of adding support for encrypted connections to servers\n"), -1);
+
 #if USE_LDAP
        gtk_text_buffer_insert_pixbuf(buffer, &iter, active_pixbuf);
 #else
index c4c060c..83b0ba3 100644 (file)
 #  include "config.h"
 #endif
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 
+#if USE_OPENSSL
 #include <openssl/ssl.h>
+#else
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#endif
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
 #include "prefs_common.h"
+#include "defs.h"
 #include "ssl_certificate.h"
 #include "utils.h"
 #include "alertpanel.h"
@@ -51,17 +62,22 @@ static GtkWidget *cert_presenter(SSLCertificate *cert)
        GtkTable *status_table = NULL;
        GtkWidget *label = NULL;
        
-       char buf[100];
        char *issuer_commonname, *issuer_location, *issuer_organization;
        char *subject_commonname, *subject_location, *subject_organization;
        char *fingerprint, *sig_status, *exp_date;
        unsigned int n;
-       unsigned char md[EVP_MAX_MD_SIZE];      
+       char buf[100];
+       unsigned char md[128];  
+#if USE_OPENSSL
        ASN1_TIME *validity;
+#else
+       char *tmp;
+#endif
        time_t exp_time_t;
        struct tm lt;
 
        /* issuer */    
+#if USE_OPENSSL
        if (X509_NAME_get_text_by_NID(X509_get_issuer_name(cert->x509_cert), 
                                       NID_commonName, buf, 100) >= 0)
                issuer_commonname = g_strdup(buf);
@@ -114,17 +130,90 @@ static GtkWidget *cert_presenter(SSLCertificate *cert)
        } else {
                exp_time_t = (time_t)0;
        }
-       
+#else
+       issuer_commonname = g_malloc(BUFFSIZE);
+       issuer_location = g_malloc(BUFFSIZE);
+       issuer_organization = g_malloc(BUFFSIZE);
+       subject_commonname = g_malloc(BUFFSIZE);
+       subject_location = g_malloc(BUFFSIZE);
+       subject_organization = g_malloc(BUFFSIZE);
+
+       n = BUFFSIZE;
+       if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, 
+               GNUTLS_OID_X520_COMMON_NAME, 0, 0, issuer_commonname, &n))
+               strncpy(issuer_commonname, _("<not in certificate>"), BUFFSIZE);
+       n = BUFFSIZE;
+
+       if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, 
+               GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, issuer_location, &n)) {
+               if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, 
+                       GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, issuer_location, &n)) {
+                       strncpy(issuer_location, _("<not in certificate>"), BUFFSIZE);
+               }
+       } else {
+               tmp = g_malloc(BUFFSIZE);
+               if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, 
+                       GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, tmp, &n) == 0) {
+                       strncat(issuer_location, ", ", BUFFSIZE-strlen(issuer_location));
+                       strncat(issuer_location, tmp, BUFFSIZE-strlen(issuer_location));
+               }
+               g_free(tmp);
+       }
+
+       n = BUFFSIZE;
+       if (gnutls_x509_crt_get_issuer_dn_by_oid(cert->x509_cert, 
+               GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, issuer_organization, &n))
+               strncpy(issuer_organization, _("<not in certificate>"), BUFFSIZE);
+
+       n = BUFFSIZE;
+       if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, 
+               GNUTLS_OID_X520_COMMON_NAME, 0, 0, subject_commonname, &n))
+               strncpy(subject_commonname, _("<not in certificate>"), BUFFSIZE);
+       n = BUFFSIZE;
+
+       if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, 
+               GNUTLS_OID_X520_LOCALITY_NAME, 0, 0, subject_location, &n)) {
+               if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, 
+                       GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, subject_location, &n)) {
+                       strncpy(subject_location, _("<not in certificate>"), BUFFSIZE);
+               }
+       } else {
+               tmp = g_malloc(BUFFSIZE);
+               if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, 
+                       GNUTLS_OID_X520_COUNTRY_NAME, 0, 0, tmp, &n) == 0) {
+                       strncat(subject_location, ", ", BUFFSIZE-strlen(subject_location));
+                       strncat(subject_location, tmp, BUFFSIZE-strlen(subject_location));
+               }
+               g_free(tmp);
+       }
+
+       n = BUFFSIZE;
+       if (gnutls_x509_crt_get_dn_by_oid(cert->x509_cert, 
+               GNUTLS_OID_X520_ORGANIZATION_NAME, 0, 0, subject_organization, &n))
+               strncpy(subject_organization, _("<not in certificate>"), BUFFSIZE);
+               
+       exp_time_t = gnutls_x509_crt_get_expiration_time(cert->x509_cert);
+#endif 
+
        memset(buf, 0, sizeof(buf));
        strftime(buf, sizeof(buf)-1, prefs_common.date_format, localtime_r(&exp_time_t, &lt));
        exp_date = buf? g_strdup(buf):g_strdup("?");
 
        /* fingerprint */
+#if USE_OPENSSL
        X509_digest(cert->x509_cert, EVP_md5(), md, &n);
        fingerprint = readable_fingerprint(md, (int)n);
 
        /* signature */
        sig_status = ssl_certificate_check_signer(cert->x509_cert);
+#else
+       n = 128;
+       gnutls_x509_crt_get_fingerprint(cert->x509_cert, GNUTLS_DIG_MD5, md, &n);
+       fingerprint = readable_fingerprint(md, (int)n);
+
+       /* signature */
+       sig_status = ssl_certificate_check_signer(cert->x509_cert, cert->status);
+#endif
 
        if (sig_status==NULL)
                sig_status = g_strdup(_("correct"));
@@ -277,8 +366,11 @@ static gboolean sslcertwindow_ask_new_cert(SSLCertificate *cert)
        gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
        g_free(buf);
        
+#if USE_OPENSSL
        sig_status = ssl_certificate_check_signer(cert->x509_cert);
-
+#else
+       sig_status = ssl_certificate_check_signer(cert->x509_cert, cert->status);
+#endif
        if (sig_status==NULL)
                sig_status = g_strdup(_("correct"));
 
@@ -317,7 +409,11 @@ static gboolean sslcertwindow_ask_expired_cert(SSLCertificate *cert)
        gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);
        g_free(buf);
        
+#if USE_OPENSSL
        sig_status = ssl_certificate_check_signer(cert->x509_cert);
+#else
+       sig_status = ssl_certificate_check_signer(cert->x509_cert, cert->status);
+#endif
 
        if (sig_status==NULL)
                sig_status = g_strdup(_("correct"));
@@ -371,7 +467,11 @@ static gboolean sslcertwindow_ask_changed_cert(SSLCertificate *old_cert, SSLCert
        gtk_box_pack_start(GTK_BOX(vbox2), label, TRUE, TRUE, 0);
        g_free(buf);
        
+#if USE_OPENSSL
        sig_status = ssl_certificate_check_signer(new_cert->x509_cert);
+#else
+       sig_status = ssl_certificate_check_signer(new_cert->x509_cert, new_cert->status);
+#endif
 
        if (sig_status==NULL)
                sig_status = g_strdup(_("correct"));
index 3f2d33d..9d4818d 100644 (file)
 #  include "config.h"
 #endif
 
-#if USE_OPENSSL
-
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
+#ifdef USE_OPENSSL
 #include <openssl/ssl.h>
 #include <openssl/objects.h>
+#else
+/* GNUTLS */
+#endif
 #include <glib.h>
 #include <gtk/gtk.h>
 #include "ssl_certificate.h"
index cd4fbb4..dbb4f47 100644 (file)
@@ -45,7 +45,7 @@
 #  include <iconv.h>
 #endif
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #  include "ssl.h"
 #endif
 
@@ -153,7 +153,7 @@ typedef enum
 
 
 #define IMAP4_PORT     143
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #define IMAPS_PORT     993
 #endif
 
@@ -322,7 +322,7 @@ static gint imap_cmd_login  (IMAPSession    *session,
                                 const gchar    *pass,
                                 const gchar    *type);
 static gint imap_cmd_noop      (IMAPSession    *session);
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static gint imap_cmd_starttls  (IMAPSession    *session);
 #endif
 static gint imap_cmd_select    (IMAPSession    *session,
@@ -430,7 +430,7 @@ typedef struct _thread_data {
        gushort port;
        gboolean done;
        SockInfo *sock;
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        SSLType ssl_type;
 #endif
 } thread_data;
@@ -836,7 +836,7 @@ static IMAPSession *imap_session_new(Folder * folder,
        int r;
        int authenticated = FALSE;
        
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        /* FIXME: IMAP over SSL only... */ 
        SSLType ssl_type;
 
@@ -870,7 +870,7 @@ static IMAPSession *imap_session_new(Folder * folder,
                                              port);
        }
        else {
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                if (ssl_type == SSL_TUNNEL) {
                        r = imap_threaded_connect_ssl(folder,
                                                      account->recv_server,
@@ -894,7 +894,7 @@ static IMAPSession *imap_session_new(Folder * folder,
        }
        else {
 #if (LIBETPAN_VERSION_MAJOR > 0 || LIBETPAN_VERSION_MINOR > 48)
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                if (r == MAILIMAP_ERROR_SSL)
                        log_error(LOG_PROTOCOL, _("SSL handshake failed\n"));
 #endif
@@ -929,7 +929,7 @@ static IMAPSession *imap_session_new(Folder * folder,
        session->folder = folder;
        IMAP_FOLDER(session->folder)->last_seen_separator = 0;
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        if (account->ssl_imap == SSL_STARTTLS) {
                gint ok;
 
@@ -3017,7 +3017,7 @@ static gint imap_cmd_login(IMAPSession *session,
        if (!strcmp(type, "LOGIN") && imap_has_capability(session, "LOGINDISABLED")) {
                gint ok = IMAP_ERROR;
                if (imap_has_capability(session, "STARTTLS")) {
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                        log_warning(LOG_PROTOCOL, _("Server requires TLS to log in.\n"));
                        ok = imap_cmd_starttls(session);
                        if (ok != IMAP_SUCCESS) {
@@ -3100,7 +3100,7 @@ static gint imap_cmd_noop(IMAPSession *session)
        return IMAP_SUCCESS;
 }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static gint imap_cmd_starttls(IMAPSession *session)
 {
        int r;
index b40f18f..869afd9 100644 (file)
--- a/src/inc.c
+++ b/src/inc.c
@@ -785,7 +785,7 @@ static IncState inc_pop3_session_do(IncSession *session)
        g_free(buf);
 
        server = pop3_session->ac_prefs->recv_server;
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        port = pop3_session->ac_prefs->set_popport ?
                pop3_session->ac_prefs->popport :
                pop3_session->ac_prefs->ssl_pop == SSL_TUNNEL ? 995 : 110;
index 59c5d0e..b926360 100644 (file)
 #include "tags.h"
 #ifdef HAVE_LIBETPAN
 #include "imap-thread.h"
+#include "nntp-thread.h"
 #endif
 #include "stock_pixmap.h"
 #ifdef HAVE_VALGRIND
 #include "valgrind.h"
 #endif
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #  include "ssl.h"
 #endif
 
@@ -1144,6 +1145,7 @@ int main(int argc, char *argv[])
 #ifdef HAVE_LIBETPAN
        imap_main_init(prefs_common.skip_ssl_cert_check);
        imap_main_set_timeout(prefs_common.io_timeout_secs);
+       nntp_main_init(prefs_common.skip_ssl_cert_check);
 #endif 
        account_set_missing_folder();
        folder_set_missing_folders();
@@ -1407,6 +1409,7 @@ static void exit_claws(MainWindow *mainwin)
 
 #ifdef HAVE_LIBETPAN
        imap_main_done();
+       nntp_main_done();
 #endif
        /* delete crashfile */
        if (!cmd.crash)
index 3bc0368..66d1af0 100644 (file)
@@ -448,7 +448,7 @@ static void prefs_post_processing_open_cb (MainWindow       *mainwin,
 static void prefs_filtering_open_cb    (MainWindow     *mainwin,
                                         guint           action,
                                         GtkWidget      *widget);
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static void ssl_manager_open_cb        (MainWindow     *mainwin,
                                         guint           action,
                                         GtkWidget      *widget);
@@ -899,7 +899,7 @@ static GtkItemFactoryEntry mainwin_entries[] =
                                                NULL, delete_duplicated_all_cb,   0, NULL},
        {N_("/_Tools/---"),                     NULL, NULL, 0, "<Separator>"},
        {N_("/_Tools/E_xecute"),                "X", execute_summary_cb, 0, NULL},
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        {N_("/_Tools/---"),                     NULL, NULL, 0, "<Separator>"},
        {N_("/_Tools/SSL cer_tificates..."),    
                                                NULL, ssl_manager_open_cb, 0, NULL},
@@ -1810,7 +1810,7 @@ MainWindow *main_window_create()
        folderview_init(folderview);
        summary_init(summaryview);
        messageview_init(messageview);
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        sslcertwindow_register_hook();
 #endif
        mainwin->lock_count = 0;
@@ -4219,7 +4219,7 @@ static void prefs_tags_open_cb(MainWindow *mainwin, guint action,
 {
        prefs_tags_open(mainwin);
 }
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static void ssl_manager_open_cb(MainWindow *mainwin, guint action,
                                  GtkWidget *widget)
 {
index df66d4c..b6dcf08 100644 (file)
@@ -21,6 +21,8 @@
 #  include "config.h"
 #endif
 
+#ifdef HAVE_LIBETPAN
+
 #include "defs.h"
 
 #include <glib.h>
 #include <dirent.h>
 #include <unistd.h>
 #include <time.h>
+#include <libetpan/libetpan.h>
 
+#include "nntp-thread.h"
+#include "news.h"
 #include "news.h"
 #include "news_gtk.h"
-#include "nntp.h"
 #include "socket.h"
 #include "recv.h"
 #include "procmsg.h"
 #include "remotefolder.h"
 #include "alertpanel.h"
 #include "inc.h"
-
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #  include "ssl.h"
 #endif
 
 #define NNTP_PORT      119
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #define NNTPS_PORT     563
 #endif
 
 typedef struct _NewsFolder     NewsFolder;
+typedef struct _NewsSession    NewsSession;
 
 #define NEWS_FOLDER(obj)       ((NewsFolder *)obj)
+#define NEWS_SESSION(obj)       ((NewsSession *)obj)
 
 struct _NewsFolder
 {
@@ -72,11 +77,18 @@ struct _NewsFolder
 
        gboolean use_auth;
        gboolean lock_count;
+       guint refcnt;
+};
+
+struct _NewsSession
+{
+       Session session;
+
+       gchar *group;
 };
 
-static void news_folder_init            (Folder        *folder,
-                                         const gchar   *name,
-                                         const gchar   *path);
+static void news_folder_init(Folder *folder, const gchar *name,
+                            const gchar *path);
 
 static Folder  *news_folder_new        (const gchar    *name,
                                         const gchar    *folder);
@@ -88,34 +100,32 @@ static gchar *news_fetch_msg               (Folder         *folder,
 static void news_remove_cached_msg     (Folder         *folder, 
                                         FolderItem     *item, 
                                         MsgInfo        *msginfo);
-#if USE_OPENSSL
-static Session *news_session_new        (const gchar   *server,
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
+static Session *news_session_new        (Folder        *folder,
+                                         const gchar   *server,
                                          gushort        port,
                                          const gchar   *userid,
                                          const gchar   *passwd,
                                          SSLType        ssl_type);
 #else
-static Session *news_session_new        (const gchar   *server,
+static Session *news_session_new        (Folder        *folder,
+                                         const gchar   *server,
                                          gushort        port,
                                          const gchar   *userid,
                                          const gchar   *passwd);
 #endif
 
-static gint news_get_article_cmd        (NNTPSession   *session,
-                                         const gchar   *cmd,
-                                         gint           num,
-                                         gchar         *filename);
-static gint news_get_article            (NNTPSession   *session,
+static gint news_get_article            (Folder        *folder,
                                          gint           num,
                                          gchar         *filename);
 
-static gint news_select_group           (NNTPSession   *session,
+static gint news_select_group           (Folder        *folder,
                                          const gchar   *group,
                                          gint          *num,
                                          gint          *first,
                                          gint          *last);
-static MsgInfo *news_parse_xover        (const gchar   *xover_str);
-static gchar *news_parse_xhdr           (const gchar   *xhdr_str,
+static MsgInfo *news_parse_xover        (struct newsnntp_xover_resp_item *item);
+static gchar *news_parse_xhdr           (clist         *list,
                                          MsgInfo       *msginfo);
 static gint news_get_num_list                   (Folder        *folder, 
                                          FolderItem    *item,
@@ -130,8 +140,6 @@ static GSList *news_get_msginfos             (Folder        *folder,
 static gboolean news_scan_required              (Folder        *folder,
                                          FolderItem    *item);
 
-static gint news_post_stream                    (Folder        *folder, 
-                                         FILE          *fp);
 static gchar *news_folder_get_path      (Folder        *folder);
 static gchar *news_item_get_path                (Folder        *folder,
                                          FolderItem    *item);
@@ -172,6 +180,22 @@ FolderClass *news_get_class(void)
        return &news_class;
 }
 
+guint nntp_folder_get_refcnt(Folder *folder)
+{
+       return ((NewsFolder *)folder)->refcnt;
+}
+
+void nntp_folder_ref(Folder *folder)
+{
+       ((NewsFolder *)folder)->refcnt++;
+}
+
+void nntp_folder_unref(Folder *folder)
+{
+       if (((NewsFolder *)folder)->refcnt > 0)
+               ((NewsFolder *)folder)->refcnt--;
+}
+
 static int news_remove_msg              (Folder        *folder, 
                                          FolderItem    *item, 
                                          gint           msgnum)
@@ -226,11 +250,15 @@ static void news_folder_destroy(Folder *folder)
 {
        gchar *dir;
 
+       while (nntp_folder_get_refcnt(folder) > 0)
+               gtk_main_iteration();
+
        dir = news_folder_get_path(folder);
        if (is_dir_exist(dir))
                remove_dir_recursive(dir);
        g_free(dir);
 
+       nntp_done(folder);
        folder_remote_folder_destroy(REMOTE_FOLDER(folder));
 }
 
@@ -240,29 +268,54 @@ static void news_folder_init(Folder *folder, const gchar *name,
        folder_remote_folder_init(folder, name, path);
 }
 
-#if USE_OPENSSL
-static Session *news_session_new(const gchar *server, gushort port,
+static void news_session_destroy(Session *session)
+{
+       NewsSession *news_session = NEWS_SESSION(session);
+
+       g_return_if_fail(session != NULL);
+
+       if (news_session->group)
+               g_free(news_session->group);
+}
+
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
+static Session *news_session_new(Folder *folder, const gchar *server, gushort port,
                                 const gchar *userid, const gchar *passwd,
                                 SSLType ssl_type)
 #else
-static Session *news_session_new(const gchar *server, gushort port,
+static Session *news_session_new(Folder *folder, const gchar *server, gushort port,
                                 const gchar *userid, const gchar *passwd)
 #endif
 {
-       gchar buf[NNTPBUFSIZE];
-       Session *session;
-
+       NewsSession *session;
+       int r = 0;
        g_return_val_if_fail(server != NULL, NULL);
 
        log_message(LOG_PROTOCOL, _("creating NNTP connection to %s:%d ...\n"), server, port);
 
-#if USE_OPENSSL
-       session = nntp_session_new(server, port, buf, userid, passwd, ssl_type);
-#else
-       session = nntp_session_new(server, port, buf, userid, passwd);
-#endif
+       session = g_new0(NewsSession, 1);
+       session_init(SESSION(session));
+       SESSION(session)->type             = SESSION_NEWS;
+       SESSION(session)->server           = g_strdup(server);
+       SESSION(session)->sock             = NULL;
+       SESSION(session)->destroy          = news_session_destroy;
+       
+       nntp_init(folder);
 
-       return session;
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
+       if (ssl_type != SSL_NONE)
+               r = nntp_threaded_connect_ssl(folder, server, port);
+       else
+#endif
+               r = nntp_threaded_connect(folder, server, port);
+       
+       if (r != NEWSNNTP_NO_ERROR) {
+               log_error(LOG_PROTOCOL, _("Error logging in to %s:%d ...\n"), server, port);
+               session_destroy(SESSION(session));
+               return NULL;
+       }
+       
+       return SESSION(session);
 }
 
 static Session *news_session_new_for_folder(Folder *folder)
@@ -272,7 +325,6 @@ static Session *news_session_new_for_folder(Folder *folder)
        const gchar *userid = NULL;
        gchar *passwd = NULL;
        gushort port;
-       gchar buf[NNTPBUFSIZE];
 
        g_return_val_if_fail(folder != NULL, NULL);
        g_return_val_if_fail(folder->account != NULL, NULL);
@@ -287,10 +339,10 @@ static Session *news_session_new_for_folder(Folder *folder)
                                                             userid);
        }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        port = ac->set_nntpport ? ac->nntpport
                : ac->ssl_nntp ? NNTPS_PORT : NNTP_PORT;
-       session = news_session_new(ac->nntp_server, port, userid, passwd,
+       session = news_session_new(folder, ac->nntp_server, port, userid, passwd,
                                   ac->ssl_nntp);
 #else
        if (ac->ssl_nntp != SSL_NONE) {
@@ -307,20 +359,27 @@ static Session *news_session_new_for_folder(Folder *folder)
                        return NULL;
        }
        port = ac->set_nntpport ? ac->nntpport : NNTP_PORT;
-       session = news_session_new(ac->nntp_server, port, userid, passwd);
+       session = news_session_new(folder, ac->nntp_server, port, userid, passwd);
 #endif
-       if ((session != NULL) && ac->use_nntp_auth && ac->use_nntp_auth_onconnect)
-               nntp_forceauth(NNTP_SESSION(session), buf, userid, passwd);
 
+       if ((session != NULL) && ac->use_nntp_auth && ac->use_nntp_auth_onconnect) {
+               if (nntp_threaded_login(folder, userid, passwd) !=
+                       NEWSNNTP_NO_ERROR) {
+                       log_error(LOG_PROTOCOL, _("Error authenticating to %s:%d ...\n"), ac->nntp_server, port);
+                       session_destroy(SESSION(session));
+                       g_free(passwd);
+                       return NULL;
+               }
+       }
        g_free(passwd);
 
        return session;
 }
 
-static NNTPSession *news_session_get(Folder *folder)
+static NewsSession *news_session_get(Folder *folder)
 {
        RemoteFolder *rfolder = REMOTE_FOLDER(folder);
-
+       struct tm lt;
        g_return_val_if_fail(folder != NULL, NULL);
        g_return_val_if_fail(FOLDER_CLASS(folder) == &news_class, NULL);
        g_return_val_if_fail(folder->account != NULL, NULL);
@@ -334,16 +393,16 @@ static NNTPSession *news_session_get(Folder *folder)
 
        if (!rfolder->session) {
                rfolder->session = news_session_new_for_folder(folder);
-               return NNTP_SESSION(rfolder->session);
+               return NEWS_SESSION(rfolder->session);
        }
 
        if (time(NULL) - rfolder->session->last_access_time <
                SESSION_TIMEOUT_INTERVAL) {
-               return NNTP_SESSION(rfolder->session);
+               return NEWS_SESSION(rfolder->session);
        }
 
-       if (nntp_mode(NNTP_SESSION(rfolder->session), FALSE)
-           != NN_SUCCESS) {
+       if (nntp_threaded_date(folder, &lt)
+           == NEWSNNTP_ERROR_STREAM) {
                log_warning(LOG_PROTOCOL, _("NNTP connection to %s:%d has been"
                              " disconnected. Reconnecting...\n"),
                            folder->account->nntp_server,
@@ -352,11 +411,11 @@ static NNTPSession *news_session_get(Folder *folder)
                session_destroy(rfolder->session);
                rfolder->session = news_session_new_for_folder(folder);
        }
-
+       
        if (rfolder->session)
                session_set_access_time(rfolder->session);
 
-       return NNTP_SESSION(rfolder->session);
+       return NEWS_SESSION(rfolder->session);
 }
 
 static void news_remove_cached_msg(Folder *folder, FolderItem *item, MsgInfo *msginfo)
@@ -382,7 +441,7 @@ static void news_remove_cached_msg(Folder *folder, FolderItem *item, MsgInfo *ms
 static gchar *news_fetch_msg(Folder *folder, FolderItem *item, gint num)
 {
        gchar *path, *filename;
-       NNTPSession *session;
+       NewsSession *session;
        gint ok;
 
        g_return_val_if_fail(folder != NULL, NULL);
@@ -405,9 +464,9 @@ static gchar *news_fetch_msg(Folder *folder, FolderItem *item, gint num)
                return NULL;
        }
 
-       ok = news_select_group(session, item->path, NULL, NULL, NULL);
-       if (ok != NN_SUCCESS) {
-               if (ok == NN_SOCKET) {
+       ok = news_select_group(folder, item->path, NULL, NULL, NULL);
+       if (ok != NEWSNNTP_NO_ERROR) {
+               if (ok == NEWSNNTP_ERROR_STREAM) {
                        session_destroy(SESSION(session));
                        REMOTE_FOLDER(folder)->session = NULL;
                }
@@ -416,11 +475,11 @@ static gchar *news_fetch_msg(Folder *folder, FolderItem *item, gint num)
        }
 
        debug_print("getting article %d...\n", num);
-       ok = news_get_article(NNTP_SESSION(REMOTE_FOLDER(folder)->session),
+       ok = news_get_article(folder,
                              num, filename);
-       if (ok != NN_SUCCESS) {
+       if (ok != NEWSNNTP_NO_ERROR) {
                g_warning("can't read article %d\n", num);
-               if (ok == NN_SOCKET) {
+               if (ok == NEWSNNTP_ERROR_STREAM) {
                        session_destroy(SESSION(session));
                        REMOTE_FOLDER(folder)->session = NULL;
                }
@@ -463,7 +522,7 @@ GSList *news_get_group_list(Folder *folder)
        FILE *fp;
        GSList *list = NULL;
        GSList *last = NULL;
-       gchar buf[NNTPBUFSIZE];
+       gchar buf[BUFFSIZE];
 
        g_return_val_if_fail(folder != NULL, NULL);
        g_return_val_if_fail(FOLDER_CLASS(folder) == &news_class, NULL);
@@ -475,26 +534,56 @@ GSList *news_get_group_list(Folder *folder)
        g_free(path);
 
        if ((fp = g_fopen(filename, "rb")) == NULL) {
-               NNTPSession *session;
+               NewsSession *session;
                gint ok;
-
+               clist *grouplist = NULL;
+               clistiter *cur;
+               fp = fopen(filename, "wb");
+               
+               if (!fp) {
+                       g_free(filename);
+                       return NULL;
+               }
                session = news_session_get(folder);
                if (!session) {
+                       fclose(fp);
                        g_free(filename);
                        return NULL;
                }
 
-               ok = nntp_list(session);
-               if (ok != NN_SUCCESS) {
-                       if (ok == NN_SOCKET) {
+               ok = nntp_threaded_list(folder, &grouplist);
+               
+               if (ok != NEWSNNTP_NO_ERROR) {
+                       if (ok == NEWSNNTP_ERROR_STREAM) {
                                session_destroy(SESSION(session));
                                REMOTE_FOLDER(folder)->session = NULL;
                        }
+                       fclose(fp);
                        g_free(filename);
                        return NULL;
                }
-               if (recv_write_to_file(SESSION(session)->sock, filename) < 0) {
-                       log_warning(LOG_PROTOCOL, _("can't retrieve newsgroup list\n"));
+               
+               for (cur = clist_begin(grouplist); cur; cur = clist_next(cur)) {
+                       struct newsnntp_group_info *info = (struct newsnntp_group_info *)
+                                                               clist_content(cur);
+                       if (fprintf(fp, "%s %d %d %c\n",
+                               info->grp_name,
+                               info->grp_last,
+                               info->grp_first,
+                               info->grp_type) < 0) {
+                               log_error(LOG_PROTOCOL, ("Can't write newsgroup list\n"));
+                               session_destroy(SESSION(session));
+                               REMOTE_FOLDER(folder)->session = NULL;
+                               fclose(fp);
+                               g_free(filename);
+                               newsnntp_list_free(grouplist);
+                               return NULL;
+                       }
+               }
+               newsnntp_list_free(grouplist);
+
+               if (fclose(fp) == EOF) {
+                       log_error(LOG_PROTOCOL, ("Can't write newsgroup list\n"));
                        session_destroy(SESSION(session));
                        REMOTE_FOLDER(folder)->session = NULL;
                        g_free(filename);
@@ -574,78 +663,46 @@ void news_remove_group_list_cache(Folder *folder)
 
 gint news_post(Folder *folder, const gchar *file)
 {
-       FILE *fp;
-       gint ok;
-
-       g_return_val_if_fail(folder != NULL, -1);
-       g_return_val_if_fail(FOLDER_CLASS(folder) == &news_class, -1);
-       g_return_val_if_fail(file != NULL, -1);
-
-       if ((fp = g_fopen(file, "rb")) == NULL) {
-               FILE_OP_ERROR(file, "fopen");
-               return -1;
-       }
-
-       ok = news_post_stream(folder, fp);
-
-       fclose(fp);
-
-       return ok;
-}
-
-static gint news_post_stream(Folder *folder, FILE *fp)
-{
-       NNTPSession *session;
        gint ok;
+       char *contents = file_read_to_str(file);
+       NewsSession *session;
 
        g_return_val_if_fail(folder != NULL, -1);
        g_return_val_if_fail(FOLDER_CLASS(folder) == &news_class, -1);
-       g_return_val_if_fail(fp != NULL, -1);
-
+       g_return_val_if_fail(contents != NULL, -1);
+       
        session = news_session_get(folder);
-       if (!session) return -1;
-
-       ok = nntp_post(session, fp);
-       if (ok != NN_SUCCESS) {
-               log_warning(LOG_PROTOCOL, _("couldn't post article.\n"));
-               if (ok == NN_SOCKET) {
-                       session_destroy(SESSION(session));
-                       REMOTE_FOLDER(folder)->session = NULL;
-               }
+       if (!session)  {
+               g_free(contents);
                return -1;
        }
-
-       return 0;
-}
-
-static gint news_get_article_cmd(NNTPSession *session, const gchar *cmd,
-                                gint num, gchar *filename)
-{
-       gchar *msgid;
-       gint ok;
-
-       ok = nntp_get_article(session, cmd, num, &msgid);
-       if (ok != NN_SUCCESS)
-               return ok;
-
-       debug_print("Message-ID = %s, num = %d\n", msgid, num);
-       g_free(msgid);
-
-       ok = recv_write_to_file(SESSION(session)->sock, filename);
-       if (ok < 0) {
-               log_warning(LOG_PROTOCOL, _("couldn't retrieve article %d\n"), num);
-               if (ok == -2)
-                       return NN_SOCKET;
-               else
-                       return NN_IOERR;
+       
+       ok = nntp_threaded_post(folder, contents, strlen(contents));
+       
+       g_free(contents);
+       if (ok == NEWSNNTP_ERROR_STREAM) {
+               session_destroy(SESSION(session));
+               REMOTE_FOLDER(folder)->session = NULL;
        }
 
-       return NN_SUCCESS;
+       return ok;
 }
 
-static gint news_get_article(NNTPSession *session, gint num, gchar *filename)
+static gint news_get_article(Folder *folder, gint num, gchar *filename)
 {
-       return news_get_article_cmd(session, "ARTICLE", num, filename);
+       size_t len;
+       char *result = NULL;
+       int r;
+       
+       r = nntp_threaded_article(folder, num, &result, &len);
+       
+       if (r == NEWSNNTP_NO_ERROR) {
+               if (str_write_to_file(result, filename) < 0)
+                       return -1;
+       }
+       
+       g_free(result);
+       return r;
 }
 
 /**
@@ -661,15 +718,19 @@ static gint news_get_article(NNTPSession *session, gint num, gchar *filename)
  *
  * Return value: NNTP result code.
  **/
-static gint news_select_group(NNTPSession *session, const gchar *group,
+static gint news_select_group(Folder *folder, const gchar *group,
                              gint *num, gint *first, gint *last)
 {
        gint ok;
        gint num_, first_, last_;
+       struct newsnntp_group_info *info = NULL;
+       NewsSession *session = NEWS_SESSION(news_session_get(folder));
 
+       g_return_val_if_fail(session != NULL, -1);
+       
        if (!num || !first || !last) {
                if (session->group && g_ascii_strcasecmp(session->group, group) == 0)
-                       return NN_SUCCESS;
+                       return NEWSNNTP_NO_ERROR;
                num = &num_;
                first = &first_;
                last = &last_;
@@ -678,8 +739,25 @@ static gint news_select_group(NNTPSession *session, const gchar *group,
        g_free(session->group);
        session->group = NULL;
 
-       ok = nntp_group(session, group, num, first, last);
-       if (ok == NN_SUCCESS)
+       ok = nntp_threaded_group(folder, group, &info);
+       
+       if (ok != NEWSNNTP_NO_ERROR && 
+           ok != NEWSNNTP_ERROR_STREAM && 
+           ok != NEWSNNTP_WARNING_REQUEST_AUTHORIZATION_USERNAME) {
+               ok = nntp_threaded_mode_reader(folder);
+               if (ok == NEWSNNTP_NO_ERROR)
+                       ok = nntp_threaded_group(folder, group, &info);
+       }
+
+       if (ok == NEWSNNTP_NO_ERROR) {
+               *num = info->grp_first;
+               *first = info->grp_first;
+               *last = info->grp_last;
+       }
+
+       newsnntp_group_free(info);
+       
+       if (ok == NEWSNNTP_NO_ERROR)
                session->group = g_strdup(group);
        else
                log_warning(LOG_PROTOCOL, _("couldn't select group: %s\n"), group);
@@ -687,80 +765,45 @@ static gint news_select_group(NNTPSession *session, const gchar *group,
        return ok;
 }
 
-#define PARSE_ONE_PARAM(p, srcp) \
-{ \
-       p = strchr(srcp, '\t'); \
-       if (!p) return NULL; \
-       else \
-               *p++ = '\0'; \
-}
-
-static MsgInfo *news_parse_xover(const gchar *xover_str)
+static MsgInfo *news_parse_xover(struct newsnntp_xover_resp_item *item)
 {
        MsgInfo *msginfo;
-       gchar *subject, *sender, *size, *line, *date, *msgid, *ref, *tmp;
-       gchar *p;
-       gint num, size_int, line_int;
-       gchar *xover_buf;
-
-       Xstrdup_a(xover_buf, xover_str, return NULL);
-
-       PARSE_ONE_PARAM(subject, xover_buf);
-       PARSE_ONE_PARAM(sender, subject);
-       PARSE_ONE_PARAM(date, sender);
-       PARSE_ONE_PARAM(msgid, date);
-       PARSE_ONE_PARAM(ref, msgid);
-       PARSE_ONE_PARAM(size, ref);
-       PARSE_ONE_PARAM(line, size);
-       /*
-        * PARSE_ONE_PARAM(xref, line);
-        *
-         * if we parse extra headers we should first examine the
-        * LIST OVERVIEW.FMT response from the server. See
-        * RFC2980 for details
-        */
-
-       tmp = strchr(line, '\t');
-       if (!tmp) tmp = strchr(line, '\r');
-       if (!tmp) tmp = strchr(line, '\n');
-       if (tmp) *tmp = '\0';
-
-       num = atoi(xover_str);
-       size_int = atoi(size);
-       line_int = atoi(line);
 
        /* set MsgInfo */
        msginfo = procmsg_msginfo_new();
-       msginfo->msgnum = num;
-       msginfo->size = size_int;
+       msginfo->msgnum = item->ovr_article;
+       msginfo->size = item->ovr_size;
 
-       msginfo->date = g_strdup(date);
-       msginfo->date_t = procheader_date_parse(NULL, date, 0);
+       msginfo->date = g_strdup(item->ovr_date);
+       msginfo->date_t = procheader_date_parse(NULL, item->ovr_date, 0);
 
-        msginfo->from = conv_unmime_header(sender, NULL);
+        msginfo->from = conv_unmime_header(item->ovr_author, NULL);
        msginfo->fromname = procheader_get_fromname(msginfo->from);
 
-        msginfo->subject = conv_unmime_header(subject, NULL);
+        msginfo->subject = conv_unmime_header(item->ovr_subject, NULL);
 
        remove_return(msginfo->from);
        remove_return(msginfo->fromname);
        remove_return(msginfo->subject);
 
-        if (msgid) {
-                extract_parenthesis(msgid, '<', '>');
-                remove_space(msgid);
-                if (*msgid != '\0')
-                        msginfo->msgid = g_strdup(msgid);
+        if (item->ovr_message_id) {
+               gchar *tmp = g_strdup(item->ovr_message_id);
+                extract_parenthesis(tmp, '<', '>');
+                remove_space(tmp);
+                if (*tmp != '\0')
+                        msginfo->msgid = g_strdup(tmp);
+               g_free(tmp);
         }                        
 
         /* FIXME: this is a quick fix; references' meaning was changed
          * into having the actual list of references in the References: header.
          * We need a GSList here, so msginfo_free() and msginfo_copy() can do 
          * their things properly. */ 
-        if (ref && strlen(ref)) {       
-               gchar **ref_tokens = g_strsplit(ref, " ", -1);
+        if (item->ovr_references && *(item->ovr_references)) {  
+               gchar **ref_tokens = g_strsplit(item->ovr_references, " ", -1);
                guint i = 0;
-               
+               char *tmp;
+               char *p;
                while (ref_tokens[i]) {
                        gchar *cur_ref = ref_tokens[i];
                        msginfo->references = references_list_append(msginfo->references, 
@@ -769,40 +812,28 @@ static MsgInfo *news_parse_xover(const gchar *xover_str)
                }
                g_strfreev(ref_tokens);
                
-                eliminate_parenthesis(ref, '(', ')');
-                if ((p = strrchr(ref, '<')) != NULL) {
+               tmp = g_strdup(item->ovr_references);
+                eliminate_parenthesis(tmp, '(', ')');
+                if ((p = strrchr(tmp, '<')) != NULL) {
                         extract_parenthesis(p, '<', '>');
                         remove_space(p);
                         if (*p != '\0')
                                 msginfo->inreplyto = g_strdup(p);
                 }
+               g_free(tmp);
         } 
 
        return msginfo;
 }
 
-static gchar *news_parse_xhdr(const gchar *xhdr_str, MsgInfo *msginfo)
+static gchar *news_parse_xhdr(clist *hdrlist, MsgInfo *msginfo)
 {
-       gchar *p;
-       gchar *tmp;
-       gint num;
-
-       p = strchr(xhdr_str, ' ');
-       if (!p)
+       struct newsnntp_xhdr_resp_item *hdr;
+       
+       hdr = clist_content(clist_begin(hdrlist));
+       if (hdr->hdr_article != msginfo->msgnum)
                return NULL;
-       else
-               p++;
-
-       num = atoi(xhdr_str);
-       if (msginfo->msgnum != num) return NULL;
-
-       tmp = strchr(p, '\r');
-       if (!tmp) tmp = strchr(p, '\n');
-
-       if (tmp)
-               return g_strndup(p, tmp - p);
-       else
-               return g_strdup(p);
+       return g_strdup(hdr->hdr_value);
 }
 
 gint news_cancel_article(Folder * folder, MsgInfo * msginfo)
@@ -908,7 +939,7 @@ static gchar *news_item_get_path(Folder *folder, FolderItem *item)
 
 static gint news_get_num_list(Folder *folder, FolderItem *item, GSList **msgnum_list, gboolean *old_uids_valid)
 {
-       NNTPSession *session;
+       NewsSession *session;
        gint i, ok, num, first, last, nummsgs = 0;
        gchar *dir;
 
@@ -923,8 +954,8 @@ static gint news_get_num_list(Folder *folder, FolderItem *item, GSList **msgnum_
        
        news_folder_lock(NEWS_FOLDER(item->folder));
 
-       ok = news_select_group(session, item->path, &num, &first, &last);
-       if (ok != NN_SUCCESS) {
+       ok = news_select_group(folder, item->path, &num, &first, &last);
+       if (ok != NEWSNNTP_NO_ERROR) {
                log_warning(LOG_PROTOCOL, _("couldn't set group: %s\n"), item->path);
                news_folder_unlock(NEWS_FOLDER(item->folder));
                return -1;
@@ -951,14 +982,6 @@ static gint news_get_num_list(Folder *folder, FolderItem *item, GSList **msgnum_
        return nummsgs;
 }
 
-#define READ_TO_LISTEND(hdr) \
-       while (!(buf[0] == '.' && buf[1] == '\r')) { \
-               if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) { \
-                       log_warning(LOG_PROTOCOL, _("error occurred while getting %s.\n"), hdr); \
-                       return msginfo; \
-               } \
-       }
-
 static void news_set_msg_flags(FolderItem *item, MsgInfo *msginfo)
 {
        msginfo->flags.tmp_flags = 0;
@@ -981,10 +1004,11 @@ static void news_set_msg_flags(FolderItem *item, MsgInfo *msginfo)
 
 static MsgInfo *news_get_msginfo(Folder *folder, FolderItem *item, gint num)
 {
-       NNTPSession *session;
+       NewsSession *session;
        MsgInfo *msginfo = NULL;
-       gchar buf[NNTPBUFSIZE];
        gint ok;
+       struct newsnntp_xover_resp_item *result = NULL;
+       clist *hdrlist = NULL;
 
        session = news_session_get(folder);
        g_return_val_if_fail(session != NULL, NULL);
@@ -994,13 +1018,12 @@ static MsgInfo *news_get_msginfo(Folder *folder, FolderItem *item, gint num)
 
        log_message(LOG_PROTOCOL, _("getting xover %d in %s...\n"),
                    num, item->path);
-       ok = nntp_xover(session, num, num);
-       
        news_folder_lock(NEWS_FOLDER(item->folder));
-       
-       if (ok != NN_SUCCESS) {
+
+       ok = nntp_threaded_xover(folder, num, num, &result, NULL);
+       if (ok != NEWSNNTP_NO_ERROR) {
                log_warning(LOG_PROTOCOL, _("couldn't get xover\n"));
-               if (ok == NN_SOCKET) {
+               if (ok == NEWSNNTP_ERROR_STREAM) {
                        session_destroy(SESSION(session));
                        REMOTE_FOLDER(item->folder)->session = NULL;
                }
@@ -1008,19 +1031,12 @@ static MsgInfo *news_get_msginfo(Folder *folder, FolderItem *item, gint num)
                return NULL;
        }
        
-       if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
-               log_warning(LOG_PROTOCOL, _("error occurred while getting xover.\n"));
-               news_folder_unlock(NEWS_FOLDER(item->folder));
-               return NULL;
-       }
-       
-       msginfo = news_parse_xover(buf);
+       msginfo = news_parse_xover(result);
+       xover_resp_item_free(result);
        if (!msginfo) {
-               log_warning(LOG_PROTOCOL, _("invalid xover line: %s\n"), buf);
+               log_warning(LOG_PROTOCOL, _("invalid xover line\n"));
        }
 
-       READ_TO_LISTEND("xover");
-
        if(!msginfo) {
                news_folder_unlock(NEWS_FOLDER(item->folder));
                return NULL;
@@ -1032,10 +1048,11 @@ static MsgInfo *news_get_msginfo(Folder *folder, FolderItem *item, gint num)
        msginfo->flags.tmp_flags |= MSG_NEWS;
        msginfo->newsgroups = g_strdup(item->path);
 
-       ok = nntp_xhdr(session, "to", num, num);
-       if (ok != NN_SUCCESS) {
+       ok = nntp_threaded_xhdr(folder, "to", num, num, &hdrlist);
+       
+       if (ok != NEWSNNTP_NO_ERROR) {
                log_warning(LOG_PROTOCOL, _("couldn't get xhdr\n"));
-               if (ok == NN_SOCKET) {
+               if (ok == NEWSNNTP_ERROR_STREAM) {
                        session_destroy(SESSION(session));
                        REMOTE_FOLDER(item->folder)->session = NULL;
                }
@@ -1043,20 +1060,14 @@ static MsgInfo *news_get_msginfo(Folder *folder, FolderItem *item, gint num)
                return msginfo;
        }
 
-       if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
-               log_warning(LOG_PROTOCOL, _("error occurred while getting xhdr.\n"));
-               news_folder_unlock(NEWS_FOLDER(item->folder));
-               return msginfo;
-       }
-
-       msginfo->to = news_parse_xhdr(buf, msginfo);
-
-       READ_TO_LISTEND("xhdr (to)");
+       msginfo->to = news_parse_xhdr(hdrlist, msginfo);
+       newsnntp_xhdr_free(hdrlist);
 
-       ok = nntp_xhdr(session, "cc", num, num);
-       if (ok != NN_SUCCESS) {
+       ok = nntp_threaded_xhdr(folder, "cc", num, num, &hdrlist);
+       
+       if (ok != NEWSNNTP_NO_ERROR) {
                log_warning(LOG_PROTOCOL, _("couldn't get xhdr\n"));
-               if (ok == NN_SOCKET) {
+               if (ok == NEWSNNTP_ERROR_STREAM) {
                        session_destroy(SESSION(session));
                        REMOTE_FOLDER(item->folder)->session = NULL;
                }
@@ -1064,62 +1075,47 @@ static MsgInfo *news_get_msginfo(Folder *folder, FolderItem *item, gint num)
                return msginfo;
        }
 
-       if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
-               log_warning(LOG_PROTOCOL, _("error occurred while getting xhdr.\n"));
-               news_folder_unlock(NEWS_FOLDER(item->folder));
-               return msginfo;
-       }
-
-       msginfo->cc = news_parse_xhdr(buf, msginfo);
+       msginfo->cc = news_parse_xhdr(hdrlist, msginfo);
+       newsnntp_xhdr_free(hdrlist);
 
-       READ_TO_LISTEND("xhdr (cc)");
        news_folder_unlock(NEWS_FOLDER(item->folder));
        return msginfo;
 }
 
-static GSList *news_get_msginfos_for_range(NNTPSession *session, FolderItem *item, guint begin, guint end)
+static GSList *news_get_msginfos_for_range(NewsSession *session, FolderItem *item, guint begin, guint end)
 {
-       gchar buf[NNTPBUFSIZE];
        GSList *newlist = NULL;
        GSList *llast = NULL;
        MsgInfo *msginfo;
-       guint count = 0, lines = (end - begin) + 2;
        gint ok;
-
+       clist *msglist = NULL;
+       clistiter *cur;
        g_return_val_if_fail(session != NULL, NULL);
        g_return_val_if_fail(item != NULL, NULL);
 
        log_message(LOG_PROTOCOL, _("getting xover %d - %d in %s...\n"),
                    begin, end, item->path);
-       ok = nntp_xover(session, begin, end);
-       if (ok != NN_SUCCESS) {
+
+       news_folder_lock(NEWS_FOLDER(item->folder));
+       
+       ok = nntp_threaded_xover(item->folder, begin, end, NULL, &msglist);
+       
+       if (ok != NEWSNNTP_NO_ERROR) {
                log_warning(LOG_PROTOCOL, _("couldn't get xover\n"));
-               if (ok == NN_SOCKET) {
+               if (ok == NEWSNNTP_ERROR_STREAM) {
                        session_destroy(SESSION(session));
                        REMOTE_FOLDER(item->folder)->session = NULL;
                }
+               news_folder_unlock(NEWS_FOLDER(item->folder));
                return NULL;
        }
 
-       news_folder_lock(NEWS_FOLDER(item->folder));
-       
-       for (;;) {
-               if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
-                       log_warning(LOG_PROTOCOL, _("error occurred while getting xover.\n"));
-                       news_folder_unlock(NEWS_FOLDER(item->folder));
-                       return newlist;
-               }
-               count++;
-               progressindicator_set_percentage
-                       (PROGRESS_TYPE_NETWORK,
-                        session->fetch_base_percentage +
-                        (((gfloat) count) / ((gfloat) lines)) * session->fetch_total_percentage);
-
-               if (buf[0] == '.' && buf[1] == '\r') break;
-
-               msginfo = news_parse_xover(buf);
+       for (cur = clist_begin(msglist); cur; cur = clist_next(cur)) {
+               struct newsnntp_xover_resp_item *ritem = (struct newsnntp_xover_resp_item *)clist_content(cur);
+               msginfo = news_parse_xover(ritem);
+               
                if (!msginfo) {
-                       log_warning(LOG_PROTOCOL, _("invalid xover line: %s\n"), buf);
+                       log_warning(LOG_PROTOCOL, _("invalid xover line\n"));
                        continue;
                }
 
@@ -1135,70 +1131,8 @@ static GSList *news_get_msginfos_for_range(NNTPSession *session, FolderItem *ite
                        llast = llast->next;
                }
        }
+       newsnntp_xover_resp_list_free(msglist);
 
-       ok = nntp_xhdr(session, "to", begin, end);
-       if (ok != NN_SUCCESS) {
-               log_warning(LOG_PROTOCOL, _("couldn't get xhdr\n"));
-               if (ok == NN_SOCKET) {
-                       session_destroy(SESSION(session));
-                       REMOTE_FOLDER(item->folder)->session = NULL;
-               }
-               news_folder_unlock(NEWS_FOLDER(item->folder));
-               return newlist;
-       }
-
-       llast = newlist;
-
-       for (;;) {
-               if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
-                       log_warning(LOG_PROTOCOL, _("error occurred while getting xhdr.\n"));
-                       news_folder_unlock(NEWS_FOLDER(item->folder));
-                       return newlist;
-               }
-
-               if (buf[0] == '.' && buf[1] == '\r') break;
-               if (!llast) {
-                       g_warning("llast == NULL\n");
-                       continue;
-               }
-
-               msginfo = (MsgInfo *)llast->data;
-               msginfo->to = news_parse_xhdr(buf, msginfo);
-
-               llast = llast->next;
-       }
-
-       ok = nntp_xhdr(session, "cc", begin, end);
-       if (ok != NN_SUCCESS) {
-               log_warning(LOG_PROTOCOL, _("couldn't get xhdr\n"));
-               if (ok == NN_SOCKET) {
-                       session_destroy(SESSION(session));
-                       REMOTE_FOLDER(item->folder)->session = NULL;
-               }
-               news_folder_unlock(NEWS_FOLDER(item->folder));
-               return newlist;
-       }
-
-       llast = newlist;
-
-       for (;;) {
-               if (sock_gets(SESSION(session)->sock, buf, sizeof(buf)) < 0) {
-                       log_warning(LOG_PROTOCOL, _("error occurred while getting xhdr.\n"));
-                       news_folder_unlock(NEWS_FOLDER(item->folder));
-                       return newlist;
-               }
-
-               if (buf[0] == '.' && buf[1] == '\r') break;
-               if (!llast) {
-                       g_warning("llast == NULL\n");
-                       continue;
-               }
-
-               msginfo = (MsgInfo *)llast->data;
-               msginfo->cc = news_parse_xhdr(buf, msginfo);
-
-               llast = llast->next;
-       }
        news_folder_unlock(NEWS_FOLDER(item->folder));
 
        session_set_access_time(SESSION(session));
@@ -1208,7 +1142,7 @@ static GSList *news_get_msginfos_for_range(NNTPSession *session, FolderItem *ite
 
 static GSList *news_get_msginfos(Folder *folder, FolderItem *item, GSList *msgnum_list)
 {
-       NNTPSession *session;
+       NewsSession *session;
        GSList *elem, *msginfo_list = NULL, *tmp_msgnum_list, *tmp_msginfo_list;
        guint first, last, next;
        guint tofetch, fetched;
@@ -1236,8 +1170,9 @@ static GSList *news_get_msginfos(Folder *folder, FolderItem *item, GSList *msgnu
        for(elem = g_slist_next(tmp_msgnum_list); elem != NULL; elem = g_slist_next(elem)) {
                next = GPOINTER_TO_INT(elem->data);
                if(next != (last + 1)) {
-                       session->fetch_base_percentage = ((gfloat) fetched) / ((gfloat) tofetch);
+/*                     session->fetch_base_percentage = ((gfloat) fetched) / ((gfloat) tofetch);
                        session->fetch_total_percentage = ((gfloat) (last - first + 1)) / ((gfloat) tofetch);
+*/
                        tmp_msginfo_list = news_get_msginfos_for_range(session, item, first, last);
                        msginfo_list = g_slist_concat(msginfo_list, tmp_msginfo_list);
                        fetched = last - first + 1;
@@ -1248,8 +1183,9 @@ static GSList *news_get_msginfos(Folder *folder, FolderItem *item, GSList *msgnu
        
        news_folder_unlock(NEWS_FOLDER(item->folder));
        
-       session->fetch_base_percentage = ((gfloat) fetched) / ((gfloat) tofetch);
+/*     session->fetch_base_percentage = ((gfloat) fetched) / ((gfloat) tofetch);
        session->fetch_total_percentage = ((gfloat) (last - first + 1)) / ((gfloat) tofetch);
+*/
        tmp_msginfo_list = news_get_msginfos_for_range(session, item, first, last);
        msginfo_list = g_slist_concat(msginfo_list, tmp_msginfo_list);
 
@@ -1289,3 +1225,82 @@ static gint news_remove_folder(Folder *folder, FolderItem *item)
        folder_item_remove(item);
        return 0;
 }
+
+#else
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include "folder.h"
+#include "alertpanel.h"
+
+static FolderClass news_class;
+
+static void warn_etpan(void)
+{
+       static gboolean missing_news_warning = TRUE;
+       if (missing_news_warning) {
+               missing_news_warning = FALSE;
+               alertpanel_error(
+                       _("You have one or more News accounts "
+                         "defined. However this version of "
+                         "Claws Mail has been built without "
+                         "News support; your News account(s) are "
+                         "disabled.\n\n"
+                         "You probably need to "
+                         "install libetpan and recompile "
+                         "Claws Mail."));
+       }
+}
+static Folder *news_folder_new(const gchar *name, const gchar *path)
+{
+       warn_etpan();
+       return NULL;
+}
+void news_group_list_free(GSList *group_list)
+{
+       warn_etpan();
+}
+void news_remove_group_list_cache(Folder *folder)
+{
+       warn_etpan();
+}
+int news_folder_locked(Folder *folder)
+{
+       warn_etpan();
+       return 0;
+}
+gint news_post(Folder *folder, const gchar *file)
+{
+       warn_etpan();
+       return -1;
+}
+
+gint news_cancel_article(Folder * folder, MsgInfo * msginfo)
+{
+       warn_etpan();
+       return -1;
+}
+
+GSList *news_get_group_list(Folder *folder)
+{
+       warn_etpan();
+       return NULL;
+}
+
+
+FolderClass *news_get_class(void)
+{
+       if (news_class.idstr == NULL) {
+               news_class.type = F_NEWS;
+               news_class.idstr = "news";
+               news_class.uistr = "News";
+
+               /* Folder functions */
+               news_class.new_folder = news_folder_new;
+       };
+
+       return &news_class;
+}
+
+
+#endif
index dcb5353..6d9c9bb 100644 (file)
@@ -47,4 +47,8 @@ gint news_cancel_article              (Folder         *folder,
                                         MsgInfo        *msginfo);
 int news_folder_locked                 (Folder         *folder);
 
+guint nntp_folder_get_refcnt(Folder *folder);
+void nntp_folder_ref(Folder *folder);
+void nntp_folder_unref(Folder *folder);
+
 #endif /* __NEWS_H__ */
index 3631908..3ce3eb7 100644 (file)
--- a/src/pop.c
+++ b/src/pop.c
@@ -45,7 +45,7 @@ static gint pop3_greeting_recv                (Pop3Session *session,
 static gint pop3_getauth_user_send     (Pop3Session *session);
 static gint pop3_getauth_pass_send     (Pop3Session *session);
 static gint pop3_getauth_apop_send     (Pop3Session *session);
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static gint pop3_stls_send             (Pop3Session *session);
 static gint pop3_stls_recv             (Pop3Session *session);
 #endif
@@ -100,7 +100,7 @@ static gint pop3_greeting_recv(Pop3Session *session, const gchar *msg)
        return PS_SUCCESS;
 }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static gint pop3_stls_send(Pop3Session *session)
 {
        session->state = POP3_STLS;
@@ -879,7 +879,7 @@ static Pop3ErrorValue pop3_ok(Pop3Session *session, const gchar *msg)
                        ok = PS_ERROR;
                } else {
                        switch (session->state) {
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                        case POP3_STLS:
                                log_error(LOG_PROTOCOL, _("couldn't start TLS session\n"));
                                ok = PS_ERROR;
@@ -943,7 +943,7 @@ static gint pop3_session_recv_msg(Session *session, const gchar *msg)
        case POP3_READY:
        case POP3_GREETING:
                pop3_greeting_recv(pop3_session, body);
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                if (pop3_session->ac_prefs->ssl_pop == SSL_STARTTLS)
                        val = pop3_stls_send(pop3_session);
                else
@@ -953,7 +953,7 @@ static gint pop3_session_recv_msg(Session *session, const gchar *msg)
                else
                        val = pop3_getauth_user_send(pop3_session);
                break;
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        case POP3_STLS:
                if (pop3_stls_recv(pop3_session) != PS_SUCCESS)
                        return -1;
index 7d9ba2d..cd95c1f 100644 (file)
--- a/src/pop.h
+++ b/src/pop.h
@@ -47,7 +47,7 @@ typedef struct _MailReceiveData       MailReceiveData;
 typedef enum {
        POP3_READY,
        POP3_GREETING,
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        POP3_STLS,
 #endif
        POP3_GETAUTH_USER,
index 52db93e..e37e43a 100644 (file)
@@ -286,7 +286,7 @@ static SendPage send_page;
 static ComposePage compose_page;
 static TemplatesPage templates_page;
 static PrivacyPage privacy_page;
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static SSLPage ssl_page;
 #endif
 static AdvancedPage advanced_page;
@@ -650,7 +650,7 @@ static PrefParam privacy_param[] = {
 };
 
 static PrefParam ssl_param[] = {
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        {"ssl_pop", "0", &tmp_ac_prefs.ssl_pop, P_ENUM,
         &ssl_page.pop_nossl_radiobtn,
         prefs_account_enum_set_data_from_radiobtn,
@@ -1037,7 +1037,7 @@ static void basic_create_widget_func(PrefsPage * _page,
        no_imap_warn_icon = gtk_image_new_from_stock
                         (GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_SMALL_TOOLBAR);
        no_imap_warn_label = gtk_label_new(_("<span weight=\"bold\">Warning: this version of Claws Mail\n"
-                         "has been built without IMAP support.</span>"));
+                         "has been built without IMAP and News support.</span>"));
        gtk_label_set_use_markup(GTK_LABEL(no_imap_warn_label), TRUE);
 
        gtk_box_pack_start(GTK_BOX (optmenubox), no_imap_warn_icon, FALSE, FALSE, 0);
@@ -2186,7 +2186,7 @@ static void privacy_create_widget_func(PrefsPage * _page,
        page->page.widget = vbox1;
 }
        
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 
 #define CREATE_RADIO_BUTTON(box, btn, btn_p, label, data)              \
 {                                                                      \
@@ -2709,7 +2709,7 @@ static gint prefs_privacy_apply(void)
        return 0;
 }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static gint prefs_ssl_apply(void)
 {
        prefs_set_data_from_dialog(ssl_param);
@@ -2753,7 +2753,7 @@ static void privacy_destroy_widget_func(PrefsPage *_page)
        /* PrivacyPage *page = (PrivacyPage *) _page; */
 }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static void ssl_destroy_widget_func(PrefsPage *_page)
 {
        /* SSLPage *page = (SSLPage *) _page; */
@@ -2825,7 +2825,7 @@ static gboolean privacy_can_close_func(PrefsPage *_page)
        return prefs_privacy_apply() >= 0;
 }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static gboolean ssl_can_close_func(PrefsPage *_page)
 {
        SSLPage *page = (SSLPage *) _page;
@@ -2922,7 +2922,7 @@ static void privacy_save_func(PrefsPage *_page)
                cancelled = FALSE;
 }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static void ssl_save_func(PrefsPage *_page)
 {
        SSLPage *page = (SSLPage *) _page;
@@ -3054,7 +3054,7 @@ static void register_privacy_page(void)
        prefs_account_register_page((PrefsPage *) &privacy_page);
 }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 static void register_ssl_page(void)
 {
        static gchar *path[3];
@@ -3100,7 +3100,7 @@ void prefs_account_init()
        register_compose_page();
        register_templates_page();
        register_privacy_page();
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        register_ssl_page();
 #endif
        register_advanced_page();
@@ -3564,7 +3564,7 @@ static void prefs_account_protocol_set_optmenu(PrefParam *pparam)
                gtk_widget_hide(optmenu);
                gtk_widget_show(optlabel);
 #ifndef HAVE_LIBETPAN
-               if (protocol == A_IMAP4) {
+               if (protocol == A_IMAP4 || protocol == A_NNTP) {
                        gtk_widget_show(protocol_optmenu->no_imap_warn_icon);
                        gtk_widget_show(protocol_optmenu->no_imap_warn_label);
                } else {
@@ -3712,8 +3712,13 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
        gtk_widget_hide(protocol_optmenu->no_imap_warn_label);
        switch(protocol) {
        case A_NNTP:
+#ifndef HAVE_LIBETPAN
+               gtk_widget_show(protocol_optmenu->no_imap_warn_icon);
+               gtk_widget_show(protocol_optmenu->no_imap_warn_label);
+#else
                gtk_widget_hide(protocol_optmenu->no_imap_warn_icon);
                gtk_widget_hide(protocol_optmenu->no_imap_warn_label);
+#endif
                gtk_widget_show(basic_page.nntpserv_label);
                gtk_widget_show(basic_page.nntpserv_entry);
                gtk_table_set_row_spacing (GTK_TABLE (basic_page.serv_table),
@@ -3788,7 +3793,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
                                 FALSE);
                }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                gtk_widget_hide(ssl_page.pop_frame);
                gtk_widget_hide(ssl_page.imap_frame);
                gtk_widget_show(ssl_page.nntp_frame);
@@ -3879,7 +3884,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
                                 TRUE);
                }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                gtk_widget_hide(ssl_page.pop_frame);
                gtk_widget_hide(ssl_page.imap_frame);
                gtk_widget_hide(ssl_page.nntp_frame);
@@ -3975,7 +3980,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
                                 FALSE);
                }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                gtk_widget_hide(ssl_page.pop_frame);
                gtk_widget_show(ssl_page.imap_frame);
                gtk_widget_hide(ssl_page.nntp_frame);
@@ -4064,7 +4069,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
                gtk_toggle_button_set_active
                        (GTK_TOGGLE_BUTTON(receive_page.recvatgetall_checkbtn), FALSE);
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                gtk_widget_hide(ssl_page.pop_frame);
                gtk_widget_hide(ssl_page.imap_frame);
                gtk_widget_hide(ssl_page.nntp_frame);
@@ -4159,7 +4164,7 @@ static void prefs_account_protocol_changed(GtkComboBox *combobox, gpointer data)
                                 TRUE);
                }
 
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                gtk_widget_show(ssl_page.pop_frame);
                gtk_widget_hide(ssl_page.imap_frame);
                gtk_widget_hide(ssl_page.nntp_frame);
index ea75b21..8a5384f 100644 (file)
 
 static RecvUIFunc      recv_ui_func;
 static gpointer                recv_ui_func_data;
-static gint recv_write                 (SockInfo       *sock,
-                                        FILE           *fp);
-
-gint recv_write_to_file(SockInfo *sock, const gchar *filename)
-{
-       FILE *fp;
-       gint ret;
-
-       g_return_val_if_fail(filename != NULL, -1);
-
-       if ((fp = g_fopen(filename, "wb")) == NULL) {
-               FILE_OP_ERROR(filename, "fopen");
-               recv_write(sock, NULL);
-               return -1;
-       }
-
-       if (change_file_mode_rw(fp, filename) < 0)
-               FILE_OP_ERROR(filename, "chmod");
-
-       if ((ret = recv_write(sock, fp)) < 0) {
-               fclose(fp);
-               g_unlink(filename);
-               return ret;
-       }
-
-       if (fclose(fp) == EOF) {
-               FILE_OP_ERROR(filename, "fclose");
-               g_unlink(filename);
-               return -1;
-       }
-
-       return 0;
-}
-
-static gint recv_write(SockInfo *sock, FILE *fp)
-{
-       gchar buf[BUFFSIZE];
-       gint len;
-       gint count = 0;
-       gint bytes = 0;
-       struct timeval tv_prev, tv_cur;
-
-       gettimeofday(&tv_prev, NULL);
-
-       for (;;) {
-               if (sock_gets(sock, buf, sizeof(buf)) < 0) {
-                       g_warning("error occurred while retrieving data.\n");
-                       return -2;
-               }
-
-               len = strlen(buf);
-               if (len > 1 && buf[0] == '.' && buf[1] == '\r') {
-                       if (recv_ui_func)
-                               recv_ui_func(sock, count, bytes,
-                                            recv_ui_func_data);
-                       break;
-               }
-               count++;
-               bytes += len;
-
-               if (recv_ui_func) {
-                       gettimeofday(&tv_cur, NULL);
-                       /* if elapsed time from previous update is greater
-                          than 50msec, update UI */
-                       if (tv_cur.tv_sec - tv_prev.tv_sec > 0 ||
-                           tv_cur.tv_usec - tv_prev.tv_usec > UI_REFRESH_INTERVAL) {
-                               gboolean ret;
-                               ret = recv_ui_func(sock, count, bytes,
-                                                  recv_ui_func_data);
-                               if (ret == FALSE) return -1;
-                               gettimeofday(&tv_prev, NULL);
-                       }
-               }
-
-               if (len > 1 && buf[len - 1] == '\n' && buf[len - 2] == '\r') {
-                       buf[len - 2] = '\n';
-                       buf[len - 1] = '\0';
-                       len--;
-               }
-
-               if (buf[0] == '.' && buf[1] == '.')
-                       memmove(buf, buf + 1, len--);
-
-               if (!strncmp(buf, ">From ", 6))
-                       memmove(buf, buf + 1, len--);
-
-               if (fp && fputs(buf, fp) == EOF) {
-                       perror("fputs");
-                       g_warning("Can't write to file.\n");
-                       fp = NULL;
-               }
-       }
-
-       if (!fp) return -1;
-
-       return 0;
-}
 
 void recv_set_ui_func(RecvUIFunc func, gpointer data)
 {
index 2c2c8a4..ccec7a3 100644 (file)
@@ -29,9 +29,6 @@ typedef gboolean (*RecvUIFunc)        (SockInfo       *sock,
                                 gint            read_bytes,
                                 gpointer        data);
 
-gint recv_write_to_file                (SockInfo       *sock,
-                                const gchar    *filename);
-
 void recv_set_ui_func          (RecvUIFunc      func,
                                 gpointer        data);
 
index 3864f9a..72b5b6a 100644 (file)
@@ -288,13 +288,13 @@ gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp, g
                        smtp_session->pass = NULL;
                }
 
-       #if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                port = ac_prefs->set_smtpport ? ac_prefs->smtpport :
                        ac_prefs->ssl_smtp == SSL_TUNNEL ? SSMTP_PORT : SMTP_PORT;
                session->ssl_type = ac_prefs->ssl_smtp;
                if (ac_prefs->ssl_smtp != SSL_NONE)
                        session->nonblocking = ac_prefs->use_nonblocking_ssl;
-       #else
+#else
                if (ac_prefs->ssl_smtp != SSL_NONE) {
                        if (alertpanel_full(_("Insecure connection"),
                                _("This connection is configured to be secured "
@@ -311,7 +311,7 @@ gint send_message_smtp_full(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp, g
                        }
                }
                port = ac_prefs->set_smtpport ? ac_prefs->smtpport : SMTP_PORT;
-       #endif
+#endif
 
                dialog = send_progress_dialog_create();
                dialog->session = session;
index f91923f..40612a0 100644 (file)
@@ -25,7 +25,7 @@
 #include "prefs_account.h"
 
 #define SMTP_PORT      25
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #define SSMTP_PORT     465
 #endif
 
index 82e1e32..b44256f 100644 (file)
@@ -21,7 +21,7 @@
 #  include "config.h"
 #endif
 
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #include <gtk/gtkwidget.h>
 #include <glib.h>
 #include <glib/gi18n.h>
index 9fae65a..f6443f0 100644 (file)
@@ -20,7 +20,7 @@
 
 #ifndef SSL_MANAGER_H
 #define SSL_MANAGER_H
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #include "mainwindow.h"
 
 void ssl_manager_create (void); 
index b0f20cb..78119b5 100644 (file)
@@ -57,7 +57,7 @@
 #include "setup.h"
 #include "folder.h"
 #include "alertpanel.h"
-#ifdef USE_OPENSSL                     
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
 #include "ssl.h"
 #endif
 #include "prefs_common.h"
@@ -116,7 +116,7 @@ typedef struct
        GtkWidget *recv_imap_subdir;
        GtkWidget *subsonly_checkbtn;
        GtkWidget *no_imap_warning;
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        GtkWidget *smtp_use_ssl;
        GtkWidget *recv_use_ssl;
        GtkWidget *smtp_use_tls;
@@ -574,7 +574,7 @@ static gboolean wizard_write_config(WizardWindow *wizard)
        GtkWidget *menu, *menuitem;
        gchar *smtp_server, *recv_server;
        gint smtp_port, recv_port;
-#ifdef USE_OPENSSL                     
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        SSLType smtp_ssl_type, recv_ssl_type;
 #endif
 
@@ -752,7 +752,7 @@ static gboolean wizard_write_config(WizardWindow *wizard)
                prefs_account->use_smtp_auth = TRUE;
        }
 
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        smtp_ssl_type = SSL_NONE;
        recv_ssl_type = SSL_NONE;       
 
@@ -1230,7 +1230,7 @@ static GtkWidget* smtp_page (WizardWindow * wizard)
                gtk_misc_set_alignment(GTK_MISC(wizard->smtp_password_label), 1, 0.5);        
        gtk_box_pack_start(GTK_BOX(hbox), wizard->smtp_password_label, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), wizard->smtp_password, TRUE, TRUE, 0);
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        hbox = gtk_hbox_new(FALSE, VSPACING_NARROW);
        gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
        wizard->smtp_use_ssl = gtk_check_button_new_with_label(
@@ -1267,7 +1267,7 @@ static void wizard_protocol_change(WizardWindow *wizard, RecvProtocol protocol)
                gtk_widget_show(wizard->recv_username_label);
                gtk_widget_show(wizard->recv_password_label);
                gtk_widget_hide(wizard->no_imap_warning);
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                gtk_widget_show(wizard->recv_use_ssl);
                gtk_widget_show(wizard->recv_use_tls);
 #endif
@@ -1291,7 +1291,7 @@ static void wizard_protocol_change(WizardWindow *wizard, RecvProtocol protocol)
                gtk_widget_show(wizard->recv_username_label);
                gtk_widget_show(wizard->recv_password_label);
                gtk_widget_hide(wizard->no_imap_warning);
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                gtk_widget_show(wizard->recv_use_ssl);
                gtk_widget_show(wizard->recv_use_tls);
 #endif
@@ -1316,7 +1316,7 @@ static void wizard_protocol_change(WizardWindow *wizard, RecvProtocol protocol)
                        gtk_widget_hide(wizard->mailbox_label);
                        gtk_widget_hide(wizard->mailbox_name);
                }
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                gtk_widget_hide(wizard->recv_use_ssl);
                gtk_widget_hide(wizard->recv_use_tls);
 #endif
@@ -1334,7 +1334,7 @@ static void wizard_protocol_change(WizardWindow *wizard, RecvProtocol protocol)
                gtk_widget_hide(wizard->recv_password);
                gtk_widget_hide(wizard->recv_username_label);
                gtk_widget_hide(wizard->recv_password_label);
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
                gtk_widget_hide(wizard->recv_use_ssl);
                gtk_widget_hide(wizard->recv_use_tls);
 #endif
@@ -1457,7 +1457,7 @@ static GtkWidget* recv_page (WizardWindow * wizard)
        gtk_box_pack_start(GTK_BOX(hbox), wizard->recv_password_label, FALSE, FALSE, 0);
        gtk_box_pack_start(GTK_BOX(hbox), wizard->recv_password, TRUE, TRUE, 0);
        
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
        hbox = gtk_hbox_new(FALSE, VSPACING_NARROW);
        gtk_box_pack_start (GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
        wizard->recv_use_ssl = gtk_check_button_new_with_label(