diff options
Diffstat (limited to 'camel')
-rw-r--r-- | camel/ChangeLog | 23 | ||||
-rw-r--r-- | camel/camel-service.c | 18 | ||||
-rw-r--r-- | camel/camel-service.h | 6 | ||||
-rw-r--r-- | camel/camel-session.c | 62 | ||||
-rw-r--r-- | camel/camel-session.h | 2 | ||||
-rw-r--r-- | camel/camel-url.c | 6 | ||||
-rw-r--r-- | camel/camel-url.h | 2 | ||||
-rw-r--r-- | camel/providers/pop3/Makefile.am | 4 | ||||
-rw-r--r-- | camel/providers/pop3/camel-pop3-store.c | 133 | ||||
-rw-r--r-- | camel/providers/smtp/camel-smtp-transport.c | 40 |
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 |