diff options
Diffstat (limited to 'camel/providers/nntp/camel-nntp-store.c')
-rw-r--r-- | camel/providers/nntp/camel-nntp-store.c | 155 |
1 files changed, 81 insertions, 74 deletions
diff --git a/camel/providers/nntp/camel-nntp-store.c b/camel/providers/nntp/camel-nntp-store.c index f9daad8515..3e911ec1c5 100644 --- a/camel/providers/nntp/camel-nntp-store.c +++ b/camel/providers/nntp/camel-nntp-store.c @@ -53,8 +53,6 @@ #include "camel-nntp-folder.h" #include "camel-nntp-private.h" #include "camel-nntp-resp-codes.h" -#include "camel-i18n.h" -#include "camel-net-utils.h" #define w(x) #define dd(x) (camel_debug("nntp")?(x):0) @@ -85,6 +83,12 @@ nntp_can_work_offline(CamelDiscoStore *store) return TRUE; } +enum { + USE_SSL_NEVER, + USE_SSL_ALWAYS, + USE_SSL_WHEN_POSSIBLE +}; + static struct { const char *name; int type; @@ -149,17 +153,8 @@ xover_setup(CamelNNTPStore *store, CamelException *ex) return ret; } -enum { - MODE_CLEAR, - MODE_SSL, - MODE_TLS, -}; - -#define SSL_PORT_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3) -#define STARTTLS_FLAGS (CAMEL_TCP_STREAM_SSL_ENABLE_TLS) - static gboolean -connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, CamelException *ex) +connect_to_server (CamelService *service, int ssl_mode, CamelException *ex) { CamelNNTPStore *store = (CamelNNTPStore *) service; CamelDiscoStore *disco_store = (CamelDiscoStore*) service; @@ -169,6 +164,9 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam unsigned int len; int ret; char *path; + struct addrinfo *ai, hints = { 0 }; + char *serv; + const char *port = NULL; CAMEL_SERVICE_LOCK(store, connect_lock); @@ -185,34 +183,50 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam camel_data_cache_set_expire_age (store->cache, 60*60*24*14); camel_data_cache_set_expire_access (store->cache, 60*60*24*5); } + + if (service->url->port) { + serv = g_alloca(16); + sprintf(serv, "%d", service->url->port); + } else { + serv = "nntp"; + port = NNTP_PORT; + } - if (ssl_mode != MODE_CLEAR) { #ifdef HAVE_SSL - if (ssl_mode == MODE_TLS) { - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, STARTTLS_FLAGS); - } else { - tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, SSL_PORT_FLAGS); + if (ssl_mode != USE_SSL_NEVER) { + if (service->url->port == 0) { + serv = "nntps"; + port = NNTPS_PORT; } -#else - camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, _("SSL unavailable")); - - goto fail; -#endif /* HAVE_SSL */ + tcp_stream = camel_tcp_stream_ssl_new (service->session, service->url->host, CAMEL_TCP_STREAM_SSL_ENABLE_SSL2 | CAMEL_TCP_STREAM_SSL_ENABLE_SSL3); } else { tcp_stream = camel_tcp_stream_raw_new (); } +#else + tcp_stream = camel_tcp_stream_raw_new (); +#endif /* HAVE_SSL */ + + hints.ai_socktype = SOCK_STREAM; + ai = camel_getaddrinfo(service->url->host, serv, &hints, ex); + if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { + camel_exception_clear(ex); + ai = camel_getaddrinfo(service->url->host, port, &hints, ex); + } + if (ai == NULL) { + camel_object_unref(tcp_stream); + goto fail; + } - if ((ret = camel_tcp_stream_connect ((CamelTcpStream *) tcp_stream, ai)) == -1) { + ret = camel_tcp_stream_connect(CAMEL_TCP_STREAM(tcp_stream), ai); + camel_freeaddrinfo(ai); + if (ret == -1) { if (errno == EINTR) camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Connection cancelled")); else camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, - _("Could not connect to %s: %s"), - service->url->host, - g_strerror (errno)); + _("Could not connect to %s (port %s): %s"), + service->url->host, serv, g_strerror (errno)); camel_object_unref (tcp_stream); @@ -254,11 +268,11 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam if (service->url->user != NULL && camel_nntp_try_authenticate(store, ex) != NNTP_AUTH_ACCEPTED) goto fail; - - /* set 'reader' mode & ignore return code, also ping the server, inn goes offline very quickly otherwise */ + + /* set 'reader' mode & ignore return code, also ping the server, inn goes offline very quickly otherwise */ if (camel_nntp_raw_command_auth (store, ex, (char **) &buf, "mode reader") == -1 || camel_nntp_raw_command_auth (store, ex, (char **) &buf, "date") == -1) - goto fail; + goto fail; if (xover_setup(store, ex) == -1) goto fail; @@ -279,61 +293,54 @@ connect_to_server (CamelService *service, struct addrinfo *ai, int ssl_mode, Cam static struct { char *value; - char *serv; - char *port; int mode; } ssl_options[] = { - { "", "nntps", NNTPS_PORT, MODE_SSL }, /* really old (1.x) */ - { "always", "nntps", NNTPS_PORT, MODE_SSL }, - { "when-possible", "nntp", NNTP_PORT, MODE_TLS }, - { "never", "nntp", NNTP_PORT, MODE_CLEAR }, - { NULL, "nntp", NNTP_PORT, MODE_CLEAR }, + { "", USE_SSL_ALWAYS }, + { "always", USE_SSL_ALWAYS }, + { "when-possible", USE_SSL_WHEN_POSSIBLE }, + { "never", USE_SSL_NEVER }, + { NULL, USE_SSL_NEVER }, }; static gboolean nntp_connect_online (CamelService *service, CamelException *ex) { - struct addrinfo hints, *ai; - const char *ssl_mode; - int mode, ret, i; - char *serv; - const char *port; +#ifdef HAVE_SSL + const char *use_ssl; + int i, ssl_mode; - if ((ssl_mode = camel_url_get_param (service->url, "use_ssl"))) { + use_ssl = camel_url_get_param (service->url, "use_ssl"); + if (use_ssl) { for (i = 0; ssl_options[i].value; i++) - if (!strcmp (ssl_options[i].value, ssl_mode)) + if (!strcmp (ssl_options[i].value, use_ssl)) break; - mode = ssl_options[i].mode; - serv = ssl_options[i].serv; - port = ssl_options[i].port; + ssl_mode = ssl_options[i].mode; + } else + ssl_mode = USE_SSL_NEVER; + + if (ssl_mode == USE_SSL_ALWAYS) { + /* Connect via SSL */ + return connect_to_server (service, ssl_mode, ex); + } else if (ssl_mode == USE_SSL_WHEN_POSSIBLE) { + /* If the server supports SSL, use it */ + if (!connect_to_server (service, ssl_mode, ex)) { + if (camel_exception_get_id (ex) == CAMEL_EXCEPTION_SERVICE_UNAVAILABLE) { + /* The ssl port seems to be unavailable, fall back to plain NNTP */ + camel_exception_clear (ex); + return connect_to_server (service, USE_SSL_NEVER, ex); + } else { + return FALSE; + } + } + + return TRUE; } else { - mode = MODE_CLEAR; - serv = "nntp"; - port = NNTP_PORT; + /* User doesn't care about SSL */ + return connect_to_server (service, ssl_mode, ex); } - - if (service->url->port) { - serv = g_alloca (16); - sprintf (serv, "%d", service->url->port); - port = NULL; - } - - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_STREAM; - hints.ai_family = PF_UNSPEC; - ai = camel_getaddrinfo(service->url->host, serv, &hints, ex); - if (ai == NULL && port != NULL && camel_exception_get_id(ex) != CAMEL_EXCEPTION_USER_CANCEL) { - camel_exception_clear (ex); - ai = camel_getaddrinfo(service->url->host, port, &hints, ex); - } - if (ai == NULL) - return FALSE; - - ret = connect_to_server (service, ai, mode, ex); - - camel_freeaddrinfo (ai); - - return ret; +#else + return connect_to_server (service, USE_SSL_NEVER, ex); +#endif } static gboolean |