[evolution-data-server] Camel: New authentication API.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] Camel: New authentication API.
- Date: Sat, 15 Oct 2011 14:59:33 +0000 (UTC)
commit 8226427259799ab6f8c9a6669a5ddf2cb4d40893
Author: Matthew Barnes <mbarnes redhat com>
Date: Sat Oct 15 09:35:43 2011 -0400
Camel: New authentication API.
Currently each provider has to implement its own authentication loop.
The idea for these changes is add a CamelSession method that executes
a common authentication loop for all providers:
CamelSessionClass:
gboolean (*authenticate_sync) (CamelSession *session,
CamelService *service,
const gchar *mechanism,
GCancellable *cancellable,
GError **error);
void (*authenticate) (CamelSession *session,
CamelService *service,
const gchar *mechanism,
gint io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean (*authenticate_finish) (CamelSession *session,
GAsyncResult *result,
GError **error);
Each CamelService is then responsible for implementing a new
authenticate method that makes only ONE authentication attempt and
returns an appropriate status code:
CamelServiceClass:
CamelAuthenticationResult
(*authenticate_sync) (CamelService *service,
const gchar *mechanism,
GCancellable *cancellable,
GError **error);
void (*authenticate) (CamelService *service,
const gchar *mechanism,
gint io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
CamelAuthenticationResult
(*authenticate_finish) (CamelService *service,
GAsyncResult *result,
GError **error);
The status codes are defined by the CamelAuthenticationResult enum:
CAMEL_AUTHENTICATION_SUCCESS : auth credentials were accepted
CAMEL_AUTHENTICATION_FAILURE : auth credentials were rejected
CAMEL_AUTHENTICATION_ERROR : something went horribly wrong!
CAMEL_AUTHENTICATION_SUCCESS and CAMEL_AUTHENTICATION_ERROR both
terminate the authentication loop, but CAMEL_AUTHENTICATION_FAILURE
cycles the loop and asks the CamelService to retry authentication,
usually after prompting the user to enter a different password.
camel/camel-enums.h | 19 ++
camel/camel-service.c | 213 +++++++++++++++++
camel/camel-service.h | 31 +++
camel/camel-session.c | 315 +++++++++++++++++++++++++-
camel/camel-session.h | 36 +++
docs/reference/camel/camel-sections.txt | 7 +
docs/reference/camel/tmpl/camel-service.sgml | 45 ++++
docs/reference/camel/tmpl/camel-session.sgml | 49 ++++-
8 files changed, 703 insertions(+), 12 deletions(-)
---
diff --git a/camel/camel-enums.h b/camel/camel-enums.h
index b0dd07e..3335be0 100644
--- a/camel/camel-enums.h
+++ b/camel/camel-enums.h
@@ -23,6 +23,25 @@
#ifndef CAMEL_ENUMS_H
#define CAMEL_ENUMS_H
+/**
+ * CamelAuthenticationResult:
+ * @CAMEL_AUTHENTICATION_ERROR:
+ * An error occurred while authenticating.
+ * @CAMEL_AUTHENTICATION_ACCEPTED:
+ * Server accepted our authentication attempt.
+ * @CAMEL_AUTHENTICATION_REJECTED:
+ * Server rejected our authentication attempt.
+ *
+ * Authentication result codes used by #CamelService.
+ *
+ * Since: 3.4
+ **/
+typedef enum {
+ CAMEL_AUTHENTICATION_ERROR,
+ CAMEL_AUTHENTICATION_ACCEPTED,
+ CAMEL_AUTHENTICATION_REJECTED
+} CamelAuthenticationResult;
+
typedef enum { /*< flags >*/
CAMEL_FOLDER_HAS_SUMMARY_CAPABILITY = 1 << 0,
CAMEL_FOLDER_HAS_SEARCH_CAPABILITY = 1 << 1,
diff --git a/camel/camel-service.c b/camel/camel-service.c
index f905b38..fe60401 100644
--- a/camel/camel-service.c
+++ b/camel/camel-service.c
@@ -71,6 +71,8 @@ struct _CamelServicePrivate {
struct _AsyncContext {
GList *auth_types;
+ gchar *auth_mechanism;
+ CamelAuthenticationResult auth_result;
};
enum {
@@ -96,6 +98,8 @@ async_context_free (AsyncContext *async_context)
{
g_list_free (async_context->auth_types);
+ g_free (async_context->auth_mechanism);
+
g_slice_free (AsyncContext, async_context);
}
@@ -450,6 +454,72 @@ service_query_auth_types_sync (CamelService *service,
}
static void
+service_authenticate_thread (GSimpleAsyncResult *simple,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ AsyncContext *async_context;
+ GError *error = NULL;
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ async_context->auth_result = camel_service_authenticate_sync (
+ CAMEL_SERVICE (object), async_context->auth_mechanism,
+ cancellable, &error);
+
+ if (error != NULL)
+ g_simple_async_result_take_error (simple, error);
+}
+
+static void
+service_authenticate (CamelService *service,
+ const gchar *mechanism,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->auth_mechanism = g_strdup (mechanism);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (service), callback, user_data, service_authenticate);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ g_simple_async_result_run_in_thread (
+ simple, service_authenticate_thread, io_priority, cancellable);
+
+ g_object_unref (simple);
+}
+
+static CamelAuthenticationResult
+service_authenticate_finish (CamelService *service,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (service), service_authenticate),
+ CAMEL_AUTHENTICATION_REJECTED);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return CAMEL_AUTHENTICATION_ERROR;
+
+ return async_context->auth_result;
+}
+
+static void
service_query_auth_types_thread (GSimpleAsyncResult *simple,
GObject *object,
GCancellable *cancellable)
@@ -605,6 +675,8 @@ camel_service_class_init (CamelServiceClass *class)
class->disconnect_sync = service_disconnect_sync;
class->query_auth_types_sync = service_query_auth_types_sync;
+ class->authenticate = service_authenticate;
+ class->authenticate_finish = service_authenticate_finish;
class->query_auth_types = service_query_auth_types;
class->query_auth_types_finish = service_query_auth_types_finish;
@@ -1250,6 +1322,147 @@ camel_service_unlock (CamelService *service,
}
/**
+ * camel_service_authenticate_sync:
+ * @service: a #CamelService
+ * @mechanism: a SASL mechanism name, or %NULL
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Attempts to authenticate @service using @mechanism and, if necessary,
+ * @service's #CamelService:password property. The function makes only
+ * ONE attempt at authentication and does not loop.
+ *
+ * If the authentication attempt completed and the server accepted the
+ * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
+ *
+ * If the authentication attempt completed but the server rejected the
+ * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
+ *
+ * If the authentication attempt failed to complete due to a network
+ * communication issue or some other mishap, the function sets @error
+ * and returns #CAMEL_AUTHENTICATION_ERROR.
+ *
+ * Generally this function should only be called from a #CamelSession
+ * subclass in order to implement its own authentication loop.
+ *
+ * Returns: the authentication result
+ *
+ * Since: 3.4
+ **/
+CamelAuthenticationResult
+camel_service_authenticate_sync (CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelServiceClass *class;
+ CamelAuthenticationResult result;
+
+ g_return_val_if_fail (
+ CAMEL_IS_SERVICE (service),
+ CAMEL_AUTHENTICATION_REJECTED);
+
+ class = CAMEL_SERVICE_GET_CLASS (service);
+ g_return_val_if_fail (
+ class->authenticate_sync != NULL,
+ CAMEL_AUTHENTICATION_REJECTED);
+
+ result = class->authenticate_sync (
+ service, mechanism, cancellable, error);
+ CAMEL_CHECK_GERROR (
+ service, authenticate_sync,
+ result != CAMEL_AUTHENTICATION_ERROR, error);
+
+ return result;
+}
+
+/**
+ * camel_service_authenticate:
+ * @service: a #CamelService
+ * @mechanism: a SASL mechanism name, or %NULL
+ * @io_priority: the I/O priority of the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously attempts to authenticate @service using @mechanism and,
+ * if necessary, @service's #CamelService:password property. The function
+ * makes only ONE attempt at authentication and does not loop.
+ *
+ * Generally this function should only be called from a #CamelSession
+ * subclass in order to implement its own authentication loop.
+ *
+ * When the operation is finished, @callback will be called. You can
+ * then call camel_service_authenticate_finish() to get the result of
+ * the operation.
+ *
+ * Since: 3.4
+ **/
+void
+camel_service_authenticate (CamelService *service,
+ const gchar *mechanism,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ CamelServiceClass *class;
+
+ g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+ class = CAMEL_SERVICE_GET_CLASS (service);
+ g_return_if_fail (class->authenticate != NULL);
+
+ class->authenticate (
+ service, mechanism, io_priority,
+ cancellable, callback, user_data);
+}
+
+/**
+ * camel_service_authenticate_finish:
+ * @service: a #CamelService
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_service_authenticate().
+ *
+ * If the authentication attempt completed and the server accepted the
+ * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
+ *
+ * If the authentication attempt completed but the server rejected the
+ * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
+ *
+ * If the authentication attempt failed to complete due to a network
+ * communication issue or some other mishap, the function sets @error
+ * and returns #CAMEL_AUTHENTICATION_ERROR.
+ *
+ * Returns: the authentication result
+ *
+ * Since: 3.4
+ **/
+CamelAuthenticationResult
+camel_service_authenticate_finish (CamelService *service,
+ GAsyncResult *result,
+ GError **error)
+{
+ CamelServiceClass *class;
+
+ g_return_val_if_fail (
+ CAMEL_IS_SERVICE (service),
+ CAMEL_AUTHENTICATION_REJECTED);
+ g_return_val_if_fail (
+ G_IS_ASYNC_RESULT (result),
+ CAMEL_AUTHENTICATION_REJECTED);
+
+ class = CAMEL_SERVICE_GET_CLASS (service);
+ g_return_val_if_fail (
+ class->authenticate_finish,
+ CAMEL_AUTHENTICATION_REJECTED);
+
+ return class->authenticate_finish (service, result, error);
+}
+
+/**
* camel_service_query_auth_types_sync:
* @service: a #CamelService
* @cancellable: optional #GCancellable object, or %NULL
diff --git a/camel/camel-service.h b/camel/camel-service.h
index c072998..7020471 100644
--- a/camel/camel-service.h
+++ b/camel/camel-service.h
@@ -117,12 +117,27 @@ struct _CamelServiceClass {
gboolean clean,
GCancellable *cancellable,
GError **error);
+ CamelAuthenticationResult
+ (*authenticate_sync) (CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error);
GList * (*query_auth_types_sync)
(CamelService *service,
GCancellable *cancellable,
GError **error);
/* Asynchronous I/O Methods (all have defaults) */
+ void (*authenticate) (CamelService *service,
+ const gchar *mechanism,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ CamelAuthenticationResult
+ (*authenticate_finish) (CamelService *service,
+ GAsyncResult *result,
+ GError **error);
void (*query_auth_types) (CamelService *service,
gint io_priority,
GCancellable *cancellable,
@@ -179,6 +194,22 @@ void camel_service_lock (CamelService *service,
void camel_service_unlock (CamelService *service,
CamelServiceLock lock);
+CamelAuthenticationResult
+ camel_service_authenticate_sync (CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error);
+void camel_service_authenticate (CamelService *service,
+ const gchar *mechanism,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+CamelAuthenticationResult
+ camel_service_authenticate_finish
+ (CamelService *service,
+ GAsyncResult *result,
+ GError **error);
GList * camel_service_query_auth_types_sync
(CamelService *service,
GCancellable *cancellable,
diff --git a/camel/camel-session.c b/camel/camel-session.c
index 93284d0..f9df499 100644
--- a/camel/camel-session.c
+++ b/camel/camel-session.c
@@ -39,14 +39,15 @@
#include "camel-debug.h"
#include "camel-file-utils.h"
+#include "camel-folder.h"
#include "camel-marshal.h"
+#include "camel-mime-message.h"
+#include "camel-sasl.h"
#include "camel-session.h"
#include "camel-store.h"
#include "camel-string-utils.h"
#include "camel-transport.h"
#include "camel-url.h"
-#include "camel-folder.h"
-#include "camel-mime-message.h"
#define CAMEL_SESSION_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
@@ -56,6 +57,7 @@
#define d(x)
+typedef struct _AsyncContext AsyncContext;
typedef struct _JobData JobData;
struct _CamelSessionPrivate {
@@ -76,6 +78,11 @@ struct _CamelSessionPrivate {
guint online : 1;
};
+struct _AsyncContext {
+ CamelService *service;
+ gchar *auth_mechanism;
+};
+
struct _JobData {
CamelSession *session;
GCancellable *cancellable;
@@ -105,6 +112,17 @@ static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE (CamelSession, camel_session, CAMEL_TYPE_OBJECT)
static void
+async_context_free (AsyncContext *async_context)
+{
+ if (async_context->service != NULL)
+ g_object_unref (async_context->service);
+
+ g_free (async_context->auth_mechanism);
+
+ g_slice_free (AsyncContext, async_context);
+}
+
+static void
job_data_free (JobData *job_data)
{
g_object_unref (job_data->session);
@@ -410,6 +428,174 @@ session_add_service (CamelSession *session,
return service;
}
+static gboolean
+session_authenticate_sync (CamelSession *session,
+ CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelServiceAuthType *authtype = NULL;
+ CamelAuthenticationResult result;
+ GError *local_error = NULL;
+
+ /* XXX This authenticate_sync() implementation serves only as
+ * a rough example and is not intended to be used as is.
+ *
+ * Any CamelSession subclass should override this method
+ * and implement a more complete authentication loop that
+ * handles user prompts and password storage.
+ */
+
+ g_warning (
+ "The default CamelSession.authenticate_sync() "
+ "method is not intended for production use.");
+
+ /* If a SASL mechanism was given and we can't find
+ * a CamelServiceAuthType for it, fail immediately. */
+ if (mechanism != NULL) {
+ authtype = camel_sasl_authtype (mechanism);
+ if (authtype == NULL) {
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("No support for %s authentication"),
+ mechanism);
+ return FALSE;
+ }
+ }
+
+ /* If the SASL mechanism does not involve a user
+ * password, then it gets one shot to authenticate. */
+ if (authtype != NULL && !authtype->need_password) {
+ result = camel_service_authenticate_sync (
+ service, mechanism, cancellable, error);
+ if (result == CAMEL_AUTHENTICATION_REJECTED)
+ g_set_error (
+ error, CAMEL_SERVICE_ERROR,
+ CAMEL_SERVICE_ERROR_CANT_AUTHENTICATE,
+ _("%s authentication failed"), mechanism);
+ return (result == CAMEL_AUTHENTICATION_ACCEPTED);
+ }
+
+ /* Some SASL mechanisms can attempt to authenticate without a
+ * user password being provided (e.g. single-sign-on credentials),
+ * but can fall back to a user password. Handle that case next. */
+ if (mechanism != NULL) {
+ CamelProvider *provider;
+ CamelSasl *sasl;
+ const gchar *service_name;
+ gboolean success = FALSE;
+
+ provider = camel_service_get_provider (service);
+ service_name = provider->protocol;
+
+ /* XXX Would be nice if camel_sasl_try_empty_password_sync()
+ * returned CamelAuthenticationResult so it's easier to
+ * detect errors. */
+ sasl = camel_sasl_new (service_name, mechanism, service);
+ if (sasl != NULL) {
+ success = camel_sasl_try_empty_password_sync (
+ sasl, cancellable, &local_error);
+ g_object_unref (sasl);
+ }
+
+ if (success)
+ return TRUE;
+ }
+
+ /* Abort authentication if we got cancelled.
+ * Otherwise clear any errors and press on. */
+ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return FALSE;
+
+ g_clear_error (&local_error);
+
+retry:
+ /* XXX This is where things get bogus. In a real implementation you
+ * would want to fetch a stored password or prompt the user here.
+ * Password should be stashed using camel_service_set_password()
+ * before calling camel_service_authenticate_sync(). */
+
+ result = camel_service_authenticate_sync (
+ service, mechanism, cancellable, error);
+
+ if (result == CAMEL_AUTHENTICATION_REJECTED) {
+ /* XXX Request a different password here. */
+ goto retry;
+ }
+
+ if (result == CAMEL_AUTHENTICATION_ACCEPTED) {
+ /* XXX Possibly store the password here using
+ * GNOME Keyring or something equivalent. */
+ }
+
+ return (result == CAMEL_AUTHENTICATION_ACCEPTED);
+}
+
+static void
+session_authenticate_thread (GSimpleAsyncResult *simple,
+ GObject *object,
+ GCancellable *cancellable)
+{
+ AsyncContext *async_context;
+ GError *error = NULL;
+
+ async_context = g_simple_async_result_get_op_res_gpointer (simple);
+
+ camel_session_authenticate_sync (
+ CAMEL_SESSION (object), async_context->service,
+ async_context->auth_mechanism, cancellable, &error);
+
+ if (error != NULL)
+ g_simple_async_result_take_error (simple, error);
+}
+
+static void
+session_authenticate (CamelSession *session,
+ CamelService *service,
+ const gchar *mechanism,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple;
+ AsyncContext *async_context;
+
+ async_context = g_slice_new0 (AsyncContext);
+ async_context->service = g_object_ref (service);
+ async_context->auth_mechanism = g_strdup (mechanism);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (session), callback, user_data, session_authenticate);
+
+ g_simple_async_result_set_op_res_gpointer (
+ simple, async_context, (GDestroyNotify) async_context_free);
+
+ g_simple_async_result_run_in_thread (
+ simple, session_authenticate_thread, io_priority, cancellable);
+
+ g_object_unref (simple);
+}
+
+static gboolean
+session_authenticate_finish (CamelSession *session,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (
+ result, G_OBJECT (session), session_authenticate), FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ /* Assume success unless a GError is set. */
+ return !g_simple_async_result_propagate_error (simple, error);
+}
+
static void
camel_session_class_init (CamelSessionClass *class)
{
@@ -425,6 +611,11 @@ camel_session_class_init (CamelSessionClass *class)
class->add_service = session_add_service;
+ class->authenticate_sync = session_authenticate_sync;
+
+ class->authenticate = session_authenticate;
+ class->authenticate_finish = session_authenticate_finish;
+
g_object_class_install_property (
object_class,
PROP_CHECK_JUNK,
@@ -1394,3 +1585,123 @@ camel_session_get_socks_proxy (CamelSession *session,
klass->get_socks_proxy (session, for_host, host_ret, port_ret);
}
+
+/**
+ * camel_session_authenticate_sync:
+ * @session: a #CamelSession
+ * @service: a #CamelService
+ * @mechanism: a SASL mechanism name, or %NULL
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Authenticates @service, which may involve repeated calls to
+ * camel_service_authenticate() or camel_service_authenticate_sync().
+ * A #CamelSession subclass is largely responsible for implementing this,
+ * and should handle things like user prompts and secure password storage.
+ * These issues are out-of-scope for Camel.
+ *
+ * If an error occurs, or if authentication is aborted, the function sets
+ * @error and returns %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.4
+ **/
+gboolean
+camel_session_authenticate_sync (CamelSession *session,
+ CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error)
+{
+ CamelSessionClass *class;
+ gboolean success;
+
+ g_return_val_if_fail (CAMEL_IS_SESSION (session), FALSE);
+ g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
+
+ class = CAMEL_SESSION_GET_CLASS (session);
+ g_return_val_if_fail (class->authenticate_sync != NULL, FALSE);
+
+ success = class->authenticate_sync (
+ session, service, mechanism, cancellable, error);
+ CAMEL_CHECK_GERROR (session, authenticate_sync, success, error);
+
+ return success;
+}
+
+/**
+ * camel_session_authenticate:
+ * @session: a #CamelSession
+ * @service: a #CamelService
+ * @mechanism: a SASL mechanism name, or %NULL
+ * @io_priority: the I/O priority for the request
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @callback: a #GAsyncReadyCallback to call when the request is satisfied
+ * @user_data: data to pass to the callback function
+ *
+ * Asynchronously authenticates @service, which may involve repeated calls
+ * to camel_service_authenticate() or camel_service_authenticate_sync().
+ * A #CamelSession subclass is largely responsible for implementing this,
+ * and should handle things like user prompts and secure password storage.
+ * These issues are out-of-scope for Camel.
+ *
+ * When the operation is finished, @callback will be called. You can
+ * then call camel_session_authenticate_finish() to get the result of
+ * the operation.
+ *
+ * Since: 3.4
+ **/
+void
+camel_session_authenticate (CamelSession *session,
+ CamelService *service,
+ const gchar *mechanism,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ CamelSessionClass *class;
+
+ g_return_if_fail (CAMEL_IS_SESSION (session));
+ g_return_if_fail (CAMEL_IS_SERVICE (service));
+
+ class = CAMEL_SESSION_GET_CLASS (session);
+ g_return_if_fail (class->authenticate != NULL);
+
+ class->authenticate (
+ session, service, mechanism, io_priority,
+ cancellable, callback, user_data);
+}
+
+/**
+ * camel_session_authenticate_finish:
+ * @session: a #CamelSession
+ * @result: a #GAsyncResult
+ * @error: return location for a #GError, or %NULL
+ *
+ * Finishes the operation started with camel_session_authenticate().
+ *
+ * If an error occurred, or if authentication was aborted, the function
+ * sets @error and returns %FALSE.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 3.4
+ **/
+gboolean
+camel_session_authenticate_finish (CamelSession *session,
+ GAsyncResult *result,
+ GError **error)
+{
+ CamelSessionClass *class;
+
+ g_return_val_if_fail (CAMEL_IS_SESSION (session), FALSE);
+ g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
+
+ class = CAMEL_SESSION_GET_CLASS (session);
+ g_return_val_if_fail (class->authenticate_finish != NULL, FALSE);
+
+ return class->authenticate_finish (session, result, error);
+}
+
diff --git a/camel/camel-session.h b/camel/camel-session.h
index 26861b2..d53ce44 100644
--- a/camel/camel-session.h
+++ b/camel/camel-session.h
@@ -140,6 +140,25 @@ struct _CamelSessionClass {
gchar **host_ret,
gint *port_ret);
+ /* Synchronous I/O Methods */
+ gboolean (*authenticate_sync) (CamelSession *session,
+ CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error);
+
+ /* Asynchronous I/O Methods (all have defaults) */
+ void (*authenticate) (CamelSession *session,
+ CamelService *service,
+ const gchar *mechanism,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (*authenticate_finish) (CamelSession *session,
+ GAsyncResult *result,
+ GError **error);
+
/* Signals */
void (*job_started) (CamelSession *session,
GCancellable *cancellable);
@@ -230,6 +249,23 @@ void camel_session_lock (CamelSession *session,
void camel_session_unlock (CamelSession *session,
CamelSessionLock lock);
+gboolean camel_session_authenticate_sync (CamelSession *session,
+ CamelService *service,
+ const gchar *mechanism,
+ GCancellable *cancellable,
+ GError **error);
+void camel_session_authenticate (CamelSession *session,
+ CamelService *service,
+ const gchar *mechanism,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean camel_session_authenticate_finish
+ (CamelSession *session,
+ GAsyncResult *result,
+ GError **error);
+
G_END_DECLS
#endif /* CAMEL_SESSION_H */
diff --git a/docs/reference/camel/camel-sections.txt b/docs/reference/camel/camel-sections.txt
index b68550c..194c36f 100644
--- a/docs/reference/camel/camel-sections.txt
+++ b/docs/reference/camel/camel-sections.txt
@@ -1971,6 +1971,10 @@ camel_service_get_connection_status
CamelServiceLock
camel_service_lock
camel_service_unlock
+CamelAuthenticationResult
+camel_service_authenticate_sync
+camel_service_authenticate
+camel_service_authenticate_finish
camel_service_query_auth_types_sync
camel_service_query_auth_types
camel_service_query_auth_types_finish
@@ -2024,6 +2028,9 @@ camel_session_forward_to
CamelSessionLock
camel_session_lock
camel_session_unlock
+camel_session_authenticate_sync
+camel_session_authenticate
+camel_session_authenticate_finish
<SUBSECTION Standard>
CAMEL_SESSION
CAMEL_IS_SESSION
diff --git a/docs/reference/camel/tmpl/camel-service.sgml b/docs/reference/camel/tmpl/camel-service.sgml
index f9d6c93..b3b8517 100644
--- a/docs/reference/camel/tmpl/camel-service.sgml
+++ b/docs/reference/camel/tmpl/camel-service.sgml
@@ -281,6 +281,51 @@ CamelService
@lock:
+<!-- ##### ENUM CamelAuthenticationResult ##### -->
+<para>
+
+</para>
+
+ CAMEL_AUTHENTICATION_ERROR:
+ CAMEL_AUTHENTICATION_ACCEPTED:
+ CAMEL_AUTHENTICATION_REJECTED:
+
+<!-- ##### FUNCTION camel_service_authenticate_sync ##### -->
+<para>
+
+</para>
+
+ service:
+ mechanism:
+ cancellable:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION camel_service_authenticate ##### -->
+<para>
+
+</para>
+
+ service:
+ mechanism:
+ io_priority:
+ cancellable:
+ callback:
+ user_data:
+
+
+<!-- ##### FUNCTION camel_service_authenticate_finish ##### -->
+<para>
+
+</para>
+
+ service:
+ result:
+ error:
+ Returns:
+
+
<!-- ##### FUNCTION camel_service_query_auth_types_sync ##### -->
<para>
diff --git a/docs/reference/camel/tmpl/camel-session.sgml b/docs/reference/camel/tmpl/camel-session.sgml
index 3589b46..a979b69 100644
--- a/docs/reference/camel/tmpl/camel-session.sgml
+++ b/docs/reference/camel/tmpl/camel-session.sgml
@@ -91,22 +91,13 @@ CamelSession
@Returns:
-<!-- ##### FUNCTION camel_session_set_socks_proxy ##### -->
-<para>
-
-</para>
-
- session:
- socks_host:
- socks_port:
-
-
<!-- ##### FUNCTION camel_session_get_socks_proxy ##### -->
<para>
</para>
@session:
+ for_host:
@host_ret:
@port_ret:
@@ -395,3 +386,41 @@ CamelSession
@lock:
+<!-- ##### FUNCTION camel_session_authenticate_sync ##### -->
+<para>
+
+</para>
+
+ session:
+ service:
+ mechanism:
+ cancellable:
+ error:
+ Returns:
+
+
+<!-- ##### FUNCTION camel_session_authenticate ##### -->
+<para>
+
+</para>
+
+ session:
+ service:
+ mechanism:
+ io_priority:
+ cancellable:
+ callback:
+ user_data:
+
+
+<!-- ##### FUNCTION camel_session_authenticate_finish ##### -->
+<para>
+
+</para>
+
+ session:
+ result:
+ error:
+ Returns:
+
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]