aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
Diffstat (limited to 'camel')
-rw-r--r--camel/ChangeLog23
-rw-r--r--camel/camel-service.c18
-rw-r--r--camel/camel-service.h6
-rw-r--r--camel/camel-session.c62
-rw-r--r--camel/camel-session.h2
-rw-r--r--camel/camel-url.c6
-rw-r--r--camel/camel-url.h2
-rw-r--r--camel/providers/pop3/Makefile.am4
-rw-r--r--camel/providers/pop3/camel-pop3-store.c133
-rw-r--r--camel/providers/smtp/camel-smtp-transport.c40
10 files changed, 265 insertions, 31 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 5a655a3aa7..7754a6ce59 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,26 @@
+2000-05-04 Dan Winship <danw@helixcode.com>
+
+ * camel-session.c (camel_session_list_providers): New function to
+ replace camel_provider_scan. Returns a list of either (a) all
+ currently-loaded providers, or (b) all available providers.
+
+ * camel-url.[ch]: Add an "empty" flag to CamelURL (indicating that
+ it contains only a protocol).
+
+ * camel-service.c (camel_service_query_auth_types): Make this take
+ a CamelException (since it may have to try to connect to the
+ server, and it might not able to.)
+
+ * providers/pop3/camel-pop3-store.c: add KPOP (Kerberized POP)
+ support. This is mostly so I have two kinds of authmech to play
+ with instead of just one. (But it does actually work.)
+
+ * providers/smtp/camel-smtp-transport.c (query_auth_types): update
+ for prototype change, but disable the functionality, since it
+ doesn't really support any auth types yet.
+ (camel_smtp_transport_get_type): add an object init function to
+ set the service url_flags.
+
2000-05-04 NotZed <NotZed@HelixCode.com>
* providers/mbox/camel-mbox-summary.c: Yes, and anotherone.
diff --git a/camel/camel-service.c b/camel/camel-service.c
index 77ba709682..edb71d2a78 100644
--- a/camel/camel-service.c
+++ b/camel/camel-service.c
@@ -1,5 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/* camelService.c : Abstract class for an email service */
+/* camel-service.c : Abstract class for an email service */
/*
*
@@ -40,7 +40,7 @@ static gboolean _connect_with_url (CamelService *service, CamelURL *url,
CamelException *ex);
static gboolean _disconnect(CamelService *service, CamelException *ex);
static gboolean _is_connected (CamelService *service);
-static GList * _query_auth_types (CamelService *service);
+static GList * _query_auth_types (CamelService *service, CamelException *ex);
static void _free_auth_types (CamelService *service, GList *authtypes);
static void _finalize (GtkObject *object);
static gboolean _set_url (CamelService *service, CamelURL *url,
@@ -129,7 +129,7 @@ camel_service_new (GtkType type, CamelSession *session, CamelURL *url,
service = CAMEL_SERVICE (gtk_object_new (type, NULL));
service->session = session;
gtk_object_ref (GTK_OBJECT (session));
- if (url) {
+ if (!url->empty) {
if (!_set_url (service, url, ex))
return NULL;
}
@@ -372,7 +372,7 @@ camel_service_get_session (CamelService *service)
GList *
-_query_auth_types (CamelService *service)
+_query_auth_types (CamelService *service, CamelException *ex)
{
return NULL;
}
@@ -381,6 +381,7 @@ _query_auth_types (CamelService *service)
* camel_service_query_auth_types: return a list of supported
* authentication types.
* @service: a CamelService
+ * @ex: a CamelException
*
* This is used by the mail source wizard to get the list of
* authentication types supported by the protocol, and information
@@ -388,17 +389,18 @@ _query_auth_types (CamelService *service)
*
* This may be called on a service with or without an associated URL.
* If there is no URL, the routine must return a generic answer. If
- * the service does have a URL, the routine MAY connect to the server
- * and query what authentication mechanisms it supports.
+ * the service does have a URL, the routine SHOULD connect to the
+ * server and query what authentication mechanisms it supports. If
+ * it cannot do that for any reason, it should set @ex accordingly.
*
* Return value: a list of CamelServiceAuthType records. The caller
* must free the list by calling camel_service_free_auth_types when
* it is done.
**/
GList *
-camel_service_query_auth_types (CamelService *service)
+camel_service_query_auth_types (CamelService *service, CamelException *ex)
{
- return CSERV_CLASS (service)->query_auth_types (service);
+ return CSERV_CLASS (service)->query_auth_types (service, ex);
}
static void
diff --git a/camel/camel-service.h b/camel/camel-service.h
index 7b04ef24a8..ffaf177543 100644
--- a/camel/camel-service.h
+++ b/camel/camel-service.h
@@ -71,7 +71,8 @@ typedef struct {
gboolean (*is_connected) (CamelService *service);
- GList * (*query_auth_types) (CamelService *service);
+ GList * (*query_auth_types) (CamelService *service,
+ CamelException *ex);
void (*free_auth_types) (CamelService *service,
GList *authtypes);
@@ -111,7 +112,8 @@ gboolean camel_service_is_connected (CamelService *service);
char * camel_service_get_url (CamelService *service);
CamelSession * camel_service_get_session (CamelService *service);
-GList * camel_service_query_auth_types (CamelService *service);
+GList * camel_service_query_auth_types (CamelService *service,
+ CamelException *ex);
void camel_service_free_auth_types (CamelService *service,
GList *authtypes);
diff --git a/camel/camel-session.c b/camel/camel-session.c
index 06a708b752..bddd22bfe2 100644
--- a/camel/camel-session.c
+++ b/camel/camel-session.c
@@ -95,6 +95,68 @@ camel_session_register_provider (CamelSession *session,
g_hash_table_insert (session->providers, provider->protocol, provider);
}
+static void
+ensure_loaded (gpointer key, gpointer value, gpointer user_data)
+{
+ CamelSession *session = user_data;
+ char *name = key;
+ char *path = value;
+
+ if (!g_hash_table_lookup (session->providers, name)) {
+ CamelException ex;
+
+ camel_exception_init (&ex);
+ camel_provider_load (session, path, &ex);
+ camel_exception_clear (&ex);
+ }
+}
+
+static gint
+provider_compare (gconstpointer a, gconstpointer b)
+{
+ const CamelProvider *cpa = (const CamelProvider *)a;
+ const CamelProvider *cpb = (const CamelProvider *)b;
+
+ return strcmp (cpa->name, cpb->name);
+}
+
+static void
+add_to_list (gpointer key, gpointer value, gpointer user_data)
+{
+ GList **list = user_data;
+ CamelProvider *prov = value;
+
+ *list = g_list_insert_sorted (*list, prov, provider_compare);
+}
+
+/**
+ * camel_session_list_providers:
+ * @session: the session
+ * @load: whether or not to load in providers that are not already loaded
+ *
+ * This returns a list of available providers in this session. If @load
+ * is %TRUE, it will first load in all available providers that haven't
+ * yet been loaded.
+ *
+ * Return value: a GList of providers, which the caller must free.
+ **/
+GList *
+camel_session_list_providers (CamelSession *session, gboolean load)
+{
+ GList *list;
+
+ g_return_val_if_fail (CAMEL_IS_SESSION (session), NULL);
+
+ if (load) {
+ g_hash_table_foreach (session->modules, ensure_loaded,
+ session);
+ }
+
+ list = NULL;
+ g_hash_table_foreach (session->providers, add_to_list, &list);
+ return list;
+}
+
CamelService *
camel_session_get_service (CamelSession *session, const char *url_string,
diff --git a/camel/camel-session.h b/camel/camel-session.h
index 4eff6c94a3..5adb72d65a 100644
--- a/camel/camel-session.h
+++ b/camel/camel-session.h
@@ -74,6 +74,8 @@ CamelSession * camel_session_new (CamelAuthCallback
void camel_session_register_provider (CamelSession *session,
CamelProvider *provider);
+GList * camel_session_list_providers (CamelSession *session,
+ gboolean load);
CamelService * camel_session_get_service (CamelSession *session,
const char *url_string,
diff --git a/camel/camel-url.c b/camel/camel-url.c
index d7e5888592..96721bda24 100644
--- a/camel/camel-url.c
+++ b/camel/camel-url.c
@@ -56,6 +56,9 @@
*
* The port, if present, must be numeric.
*
+ * If nothing but the protocol (and the ":") is present, the "empty"
+ * flag will be set on the returned URL.
+ *
* Return value: a CamelURL structure containing the URL items.
**/
CamelURL *
@@ -95,7 +98,8 @@ camel_url_new (const char *url_string, CamelException *ex)
if (*(colon + 1)) {
url->path = g_strdup (colon + 1);
camel_url_decode (url->path);
- }
+ } else
+ url->empty = TRUE;
return url;
}
diff --git a/camel/camel-url.h b/camel/camel-url.h
index 53b42dfcd9..60012cb90c 100644
--- a/camel/camel-url.h
+++ b/camel/camel-url.h
@@ -45,6 +45,8 @@ typedef struct {
int port;
char *path;
+ /* This is set if the URL contained only a protocol. */
+ gboolean empty;
} CamelURL;
CamelURL *camel_url_new (const char *url_string, CamelException *ex);
diff --git a/camel/providers/pop3/Makefile.am b/camel/providers/pop3/Makefile.am
index 49bb2fc254..f30d73e736 100644
--- a/camel/providers/pop3/Makefile.am
+++ b/camel/providers/pop3/Makefile.am
@@ -17,7 +17,7 @@ INCLUDES = \
-I$(top_srcdir)/intl \
$(GTK_INCLUDEDIR) \
-I$(top_srcdir)/camel \
- -I$(srcdir)/../mbox \
+ $(KRB4_CFLAGS) \
-DG_LOG_DOMAIN=\"camel-pop3-provider\"
libcamelpop3_la_SOURCES = \
@@ -30,6 +30,6 @@ libcamelpop3include_HEADERS = \
camel-pop3-store.h
-libcamelpop3_la_LDFLAGS = -version-info 0:0:0 -rpath $(libdir)
+libcamelpop3_la_LDFLAGS = $(KRB4_LDFLAGS) -version-info 0:0:0 -rpath $(libdir)
EXTRA_DIST = libcamelpop3.urls
diff --git a/camel/providers/pop3/camel-pop3-store.c b/camel/providers/pop3/camel-pop3-store.c
index 4f4410234d..eb5c77558e 100644
--- a/camel/providers/pop3/camel-pop3-store.c
+++ b/camel/providers/pop3/camel-pop3-store.c
@@ -46,13 +46,20 @@
/* Specified in RFC 1939 */
#define POP3_PORT 110
+#ifdef HAVE_KRB4
+/* Specified nowhere */
+#define KPOP_PORT 1109
+
+#include <krb.h>
+#endif
+
static CamelServiceClass *service_class = NULL;
static void finalize (GtkObject *object);
static gboolean pop3_connect (CamelService *service, CamelException *ex);
static gboolean pop3_disconnect (CamelService *service, CamelException *ex);
-static GList *query_auth_types (CamelService *service);
+static GList *query_auth_types (CamelService *service, CamelException *ex);
static void free_auth_types (CamelService *service, GList *authtypes);
static CamelFolder *get_folder (CamelStore *store, const char *folder_name,
@@ -139,7 +146,7 @@ finalize (GtkObject *object)
static CamelServiceAuthType password_authtype = {
- "Password/APOP",
+ "Password",
"This option will connect to the POP server using the APOP "
"protocol if possible, or a plaintext password if not.",
@@ -148,12 +155,78 @@ static CamelServiceAuthType password_authtype = {
TRUE
};
-static GList
-*query_auth_types (CamelService *service)
+#ifdef HAVE_KRB4
+static CamelServiceAuthType kpop_authtype = {
+ "Kerberos 4 (KPOP)",
+
+ "This will connect to the POP server and use Kerberos 4 "
+ "to authenticate to it.",
+
+ "+KPOP",
+ FALSE
+};
+
+static gboolean
+try_connect (CamelService *service, CamelException *ex)
+{
+ struct hostent *h;
+ struct sockaddr_in sin;
+ int fd;
+
+ h = camel_service_gethost (service, ex);
+ if (!h)
+ return FALSE;
+
+ sin.sin_family = h->h_addrtype;
+ if (service->url->port)
+ sin.sin_port = htons (service->url->port);
+ else
+ sin.sin_port = htons (POP3_PORT);
+ memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr));
+
+ fd = socket (h->h_addrtype, SOCK_STREAM, 0);
+ if (fd == -1 ||
+ connect (fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+ if (fd > -1)
+ close (fd);
+ return FALSE;
+ }
+
+ close (fd);
+ return TRUE;
+}
+#endif
+
+static GList *
+query_auth_types (CamelService *service, CamelException *ex)
{
- GList *ret;
+ GList *ret = NULL;
+ gboolean passwd = TRUE;
+#ifdef HAVE_KRB4
+ gboolean kpop = TRUE;
+ int saved_port;
+#endif
+
+ if (service->url) {
+ passwd = try_connect (service, ex);
+ if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
+ return NULL;
+#ifdef HAVE_KRB4
+ saved_port = service->url->port;
+ service->url->port = KPOP_PORT;
+ kpop = try_connect (service, ex);
+ service->url->port = saved_port;
+ if (camel_exception_get_id (ex) != CAMEL_EXCEPTION_NONE)
+ return NULL;
+#endif
+ }
- ret = g_list_append (NULL, &password_authtype);
+ if (passwd)
+ ret = g_list_append (ret, &password_authtype);
+#ifdef HAVE_KRB4
+ if (kpop)
+ ret = g_list_append (ret, &kpop_authtype);
+#endif
return ret;
}
@@ -213,12 +286,16 @@ pop3_connect (CamelService *service, CamelException *ex)
int fd, status;
char *buf, *apoptime, *apopend;
CamelPop3Store *store = CAMEL_POP3_STORE (service);
+#ifdef HAVE_KRB4
+ gboolean kpop = (service->url->authmech &&
+ !strcmp (service->url->authmech, "+KPOP"));
+#endif
h = camel_service_gethost (service, ex);
if (!h)
return FALSE;
- if (!service->url->passwd) {
+ if (!service->url->authmech && !service->url->passwd) {
char *prompt = g_strdup_printf ("Please enter the POP3 password for %s@%s",
service->url->user, h->h_name);
service->url->passwd =
@@ -232,7 +309,15 @@ pop3_connect (CamelService *service, CamelException *ex)
}
sin.sin_family = h->h_addrtype;
- sin.sin_port = htons (service->url->port ? service->url->port : POP3_PORT);
+ if (service->url->port)
+ sin.sin_port = service->url->port;
+#ifdef HAVE_KRB4
+ else if (kpop)
+ sin.sin_port = KPOP_PORT;
+#endif
+ else
+ sin.sin_port = POP3_PORT;
+ sin.sin_port = htons (sin.sin_port);
memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr));
fd = socket (h->h_addrtype, SOCK_STREAM, 0);
@@ -247,6 +332,38 @@ pop3_connect (CamelService *service, CamelException *ex)
return FALSE;
}
+#ifdef HAVE_KRB4
+ if (kpop) {
+ KTEXT_ST ticket_st;
+ MSG_DAT msg_data;
+ CREDENTIALS cred;
+ Key_schedule schedule;
+ char *hostname;
+
+ /* Need to copy hostname, because krb_realmofhost will
+ * call gethostbyname as well, and gethostbyname uses
+ * static storage.
+ */
+ hostname = g_strdup (h->h_name);
+ status = krb_sendauth (0, fd, &ticket_st, "pop", hostname,
+ krb_realmofhost (hostname), 0,
+ &msg_data, &cred, schedule,
+ NULL, NULL, "KPOPV0.1");
+ g_free (hostname);
+ if (status != KSUCCESS) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+ "Could not authenticate to KPOP "
+ "server: %s",
+ krb_err_txt[status]);
+ close (fd);
+ return FALSE;
+ }
+
+ if (!service->url->passwd)
+ service->url->passwd = g_strdup (service->url->user);
+ }
+#endif /* HAVE_KRB4 */
+
store->ostream = camel_stream_fs_new_with_fd (fd);
store->istream = camel_stream_buffer_new (store->ostream,
CAMEL_STREAM_BUFFER_READ);
diff --git a/camel/providers/smtp/camel-smtp-transport.c b/camel/providers/smtp/camel-smtp-transport.c
index cc57e29b1d..992948560e 100644
--- a/camel/providers/smtp/camel-smtp-transport.c
+++ b/camel/providers/smtp/camel-smtp-transport.c
@@ -57,7 +57,7 @@ static gboolean _send_to (CamelTransport *transport, CamelMedium *message, GList
static gboolean smtp_connect (CamelService *service, CamelException *ex);
static gboolean smtp_disconnect (CamelService *service, CamelException *ex);
static GList *esmtp_get_authtypes(gchar *buffer);
-static GList *query_auth_types (CamelService *service);
+static GList *query_auth_types (CamelService *service, CamelException *ex);
static void free_auth_types (CamelService *service, GList *authtypes);
static gchar *smtp_get_email_addr_from_text (gchar *text);
static gboolean smtp_helo (CamelSmtpTransport *transport, CamelException *ex);
@@ -89,6 +89,14 @@ camel_smtp_transport_class_init (CamelSmtpTransportClass *camel_smtp_transport_c
camel_transport_class->send_to = _send_to;
}
+static void
+camel_smtp_transport_init (gpointer object, gpointer klass)
+{
+ CamelService *service = CAMEL_SERVICE (object);
+
+ service->url_flags = CAMEL_SERVICE_URL_NEED_HOST;
+}
+
GtkType
camel_smtp_transport_get_type (void)
{
@@ -101,7 +109,7 @@ camel_smtp_transport_get_type (void)
sizeof (CamelSmtpTransport),
sizeof (CamelSmtpTransportClass),
(GtkClassInitFunc) camel_smtp_transport_class_init,
- (GtkObjectInitFunc) NULL,
+ (GtkObjectInitFunc) camel_smtp_transport_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
@@ -209,23 +217,35 @@ static GList
return ret;
}
-static CamelServiceAuthType password_authtype = {
- "Password/CRAM-MD5",
+static CamelServiceAuthType no_authtype = {
+ "No authentication required",
- "This option will connect to the ESMTP server using the CRAM-MD5 "
- "authentication if possible.",
+ "This option will connect to the SMTP server without using any "
+ "kind of authentication. This should be fine for connecting to "
+ "most SMTP servers."
"",
+ FALSE
+};
+
+static CamelServiceAuthType cram_md5_authtype = {
+ "CRAM-MD5",
+
+ "This option will connect to the SMTP server using CRAM-MD5 "
+ "authentication.",
+
+ "CRAM-MD5",
TRUE
};
static GList
-*query_auth_types (CamelService *service)
+*query_auth_types (CamelService *service, CamelException *ex)
{
- GList *ret;
+ /* FIXME: Re-enable this when auth types are actually
+ * implemented.
+ */
- ret = g_list_append (NULL, &password_authtype);
- return ret;
+ return NULL;
}
static void