+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
( 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
MICRO_VERSION=2
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=81
+EXTRA_VERSION=82
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
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
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 ***])
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=
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"
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)" :
log.c \
md5.c \
mgutils.c \
- nntp.c \
passcrypt.c \
plugin.c \
prefs.c \
log.h \
md5.h \
mgutils.h \
- nntp.h \
passcrypt.h \
plugin.h \
prefs.h \
srand((gint) time(NULL));
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
ssl_init();
#endif
void claws_done(void)
{
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
ssl_done();
#endif
}
+++ /dev/null
-/*
- * 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;
-}
+++ /dev/null
-/*
- * 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__ */
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;
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)) {
return 0;
}
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
gint session_start_tls(Session *session)
{
gboolean nb_mode;
gchar *server;
gushort port;
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
SSLType ssl_type;
#endif
SendDataNotify notify_func,
gpointer data);
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
gint session_start_tls (Session *session);
#endif
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);
session->state = SMTP_READY;
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
session->tls_init_done = FALSE;
#endif
return SM_ERROR;
}
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
static gint smtp_starttls(SMTPSession *session)
{
session->state = SMTP_STARTTLS;
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
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);
#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))
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;
SMTPState state;
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
gboolean tls_init_done;
#endif
#include "socket.h"
#include "utils.h"
#include "log.h"
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
# include "ssl.h"
#endif
condition |= G_IO_IN;
}
}
+#elif USE_GNUTLS
+/* ?? */
#endif
FD_ZERO(&fds);
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,
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)
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
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)
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
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;
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
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;
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)
typedef struct _SockInfo SockInfo;
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
# include "ssl.h"
#endif
#if USE_OPENSSL
SSL *ssl;
guint g_source;
+#elif USE_GNUTLS
+ gnutls_session ssl;
+ guint g_source;
#endif
GIOChannel *sock_ch;
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 */
# 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*/
#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
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;
* 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 */
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
}
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;
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;
}
}
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 {
# 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>
#include "log.h"
#include "socket.h"
#include "hooks.h"
+#include "defs.h"
static GHashTable *warned_expired = NULL;
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)
{
return mktime(&tm)-offset;
}
+#endif
static char * get_fqdn(char *host)
{
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
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)
{
}
-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);
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;
}
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);
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);
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;
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;
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);
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);
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)
# 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"
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;
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 */
#if USE_OPENSSL
" OpenSSL"
#endif
+#if USE_GNUTLS
+ " GnuTLS"
+#endif
#if USE_LDAP
" LDAP"
#endif
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 \
void * result;
int finished;
mailimap *imap;
+ newsnntp *nntp;
};
#endif
op->result = NULL;
op->finished = 0;
op->imap = NULL;
+ op->nntp = NULL;
r = pthread_mutex_init(&op->lock, NULL);
if (r != 0)
}
#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)
}
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) {
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)
--- /dev/null
+/*
+ * 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, ¶m, &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, ¶m, &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, ¶m) < 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, ¶m, &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, ¶m, &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, ¶m, &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, ¶m, &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, ¶m, &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, ¶m, &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, ¶m, &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, ¶m, &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, ¶m, &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
--- /dev/null
+/*
+ * 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
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
# 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"
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);
} 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, <));
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"));
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"));
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"));
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"));
# 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"
# include <iconv.h>
#endif
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
# include "ssl.h"
#endif
#define IMAP4_PORT 143
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
#define IMAPS_PORT 993
#endif
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,
gushort port;
gboolean done;
SockInfo *sock;
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
SSLType ssl_type;
#endif
} thread_data;
int r;
int authenticated = FALSE;
-#ifdef USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
/* FIXME: IMAP over SSL only... */
SSLType ssl_type;
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,
}
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
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;
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) {
return IMAP_SUCCESS;
}
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
static gint imap_cmd_starttls(IMAPSession *session)
{
int r;
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;
#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
#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();
#ifdef HAVE_LIBETPAN
imap_main_done();
+ nntp_main_done();
#endif
/* delete crashfile */
if (!cmd.crash)
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);
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},
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;
{
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)
{
# 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
{
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);
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,
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);
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)
{
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));
}
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)
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);
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) {
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);
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, <)
+ == NEWSNNTP_ERROR_STREAM) {
log_warning(LOG_PROTOCOL, _("NNTP connection to %s:%d has been"
" disconnected. Reconnecting...\n"),
folder->account->nntp_server,
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)
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);
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;
}
}
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;
}
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);
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);
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;
}
/**
*
* 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_;
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);
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,
}
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)
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;
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;
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;
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);
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;
}
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;
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;
}
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;
}
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;
}
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));
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;
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;
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);
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
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__ */
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
return PS_SUCCESS;
}
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
static gint pop3_stls_send(Pop3Session *session)
{
session->state = POP3_STLS;
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;
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
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;
typedef enum {
POP3_READY,
POP3_GREETING,
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
POP3_STLS,
#endif
POP3_GETAUTH_USER,
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;
};
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,
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);
page->page.widget = vbox1;
}
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
#define CREATE_RADIO_BUTTON(box, btn, btn_p, label, data) \
{ \
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);
/* 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; */
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;
cancelled = FALSE;
}
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
static void ssl_save_func(PrefsPage *_page)
{
SSLPage *page = (SSLPage *) _page;
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];
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();
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 {
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),
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);
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);
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);
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);
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);
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)
{
gint read_bytes,
gpointer data);
-gint recv_write_to_file (SockInfo *sock,
- const gchar *filename);
-
void recv_set_ui_func (RecvUIFunc func,
gpointer data);
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 "
}
}
port = ac_prefs->set_smtpport ? ac_prefs->smtpport : SMTP_PORT;
- #endif
+#endif
dialog = send_progress_dialog_create();
dialog->session = session;
#include "prefs_account.h"
#define SMTP_PORT 25
-#if USE_OPENSSL
+#if (defined(USE_OPENSSL) || defined (USE_GNUTLS))
#define SSMTP_PORT 465
#endif
# 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>
#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);
#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"
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;
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
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;
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(
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
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
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
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
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(