1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-service.c : Abstract class for an email service */
7 * Bertrand Guiheneuf <bertrand@helixcode.com>
9 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU Lesser General Public
13 * License as published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
35 #include <glib/gstdio.h>
36 #include <glib/gi18n-lib.h>
38 #include "camel-debug.h"
39 #include "camel-enumtypes.h"
40 #include "camel-local-settings.h"
41 #include "camel-network-settings.h"
42 #include "camel-operation.h"
43 #include "camel-service.h"
44 #include "camel-session.h"
49 #define CAMEL_SERVICE_GET_PRIVATE(obj) \
50 (G_TYPE_INSTANCE_GET_PRIVATE \
51 ((obj), CAMEL_TYPE_SERVICE, CamelServicePrivate))
53 typedef struct _AsyncClosure AsyncClosure;
54 typedef struct _AsyncContext AsyncContext;
55 typedef struct _ConnectionOp ConnectionOp;
57 struct _CamelServicePrivate {
58 gpointer session; /* weak pointer */
60 CamelSettings *settings;
61 GMutex *settings_lock;
63 CamelProvider *provider;
67 gchar *user_cache_dir;
71 GMutex *connection_lock;
72 ConnectionOp *connection_op;
73 CamelServiceConnectionStatus status;
76 /* This is copied from EAsyncClosure in libedataserver.
77 * If this proves useful elsewhere in Camel we may want
78 * to split this out and make it part of the public API. */
79 struct _AsyncClosure {
81 GMainContext *context;
85 struct _AsyncContext {
87 gchar *auth_mechanism;
88 CamelAuthenticationResult auth_result;
91 /* The GQueue is only modified while CamelService's
92 * connection_lock is held, so it does not need its
94 struct _ConnectionOp {
95 volatile gint ref_count;
98 GSimpleAsyncResult *simple;
99 GCancellable *cancellable;
105 PROP_CONNECTION_STATUS,
114 /* Forward Declarations */
115 static void camel_service_initable_init (GInitableIface *interface);
117 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
118 CamelService, camel_service, CAMEL_TYPE_OBJECT,
119 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, camel_service_initable_init))
121 static AsyncClosure *
122 async_closure_new (void)
124 AsyncClosure *closure;
126 closure = g_slice_new0 (AsyncClosure);
127 closure->context = g_main_context_new ();
128 closure->loop = g_main_loop_new (closure->context, FALSE);
130 g_main_context_push_thread_default (closure->context);
135 static GAsyncResult *
136 async_closure_wait (AsyncClosure *closure)
138 g_return_val_if_fail (closure != NULL, NULL);
140 g_main_loop_run (closure->loop);
142 return closure->result;
146 async_closure_free (AsyncClosure *closure)
148 g_return_if_fail (closure != NULL);
150 g_main_context_pop_thread_default (closure->context);
152 g_main_loop_unref (closure->loop);
153 g_main_context_unref (closure->context);
155 if (closure->result != NULL)
156 g_object_unref (closure->result);
158 g_slice_free (AsyncClosure, closure);
162 async_closure_callback (GObject *object,
163 GAsyncResult *result,
166 AsyncClosure *real_closure;
168 g_return_if_fail (G_IS_OBJECT (object));
169 g_return_if_fail (G_IS_ASYNC_RESULT (result));
170 g_return_if_fail (closure != NULL);
172 real_closure = closure;
174 /* Replace any previous result. */
175 if (real_closure->result != NULL)
176 g_object_unref (real_closure->result);
177 real_closure->result = g_object_ref (result);
179 g_main_loop_quit (real_closure->loop);
183 async_context_free (AsyncContext *async_context)
185 g_list_free (async_context->auth_types);
187 g_free (async_context->auth_mechanism);
189 g_slice_free (AsyncContext, async_context);
192 static ConnectionOp *
193 connection_op_new (GSimpleAsyncResult *simple,
194 GCancellable *cancellable)
198 op = g_slice_new0 (ConnectionOp);
200 g_mutex_init (&op->simple_lock);
201 op->simple = g_object_ref (simple);
203 if (G_IS_CANCELLABLE (cancellable))
204 op->cancellable = g_object_ref (cancellable);
209 static ConnectionOp *
210 connection_op_ref (ConnectionOp *op)
212 g_return_val_if_fail (op != NULL, NULL);
213 g_return_val_if_fail (op->ref_count > 0, NULL);
215 g_atomic_int_inc (&op->ref_count);
221 connection_op_unref (ConnectionOp *op)
223 g_return_if_fail (op != NULL);
224 g_return_if_fail (op->ref_count > 0);
226 if (g_atomic_int_dec_and_test (&op->ref_count)) {
228 /* The pending queue should be empty. */
229 g_warn_if_fail (g_queue_is_empty (&op->pending));
231 g_mutex_clear (&op->simple_lock);
233 if (op->simple != NULL)
234 g_object_unref (op->simple);
236 if (op->cancel_id > 0)
237 g_cancellable_disconnect (
238 op->cancellable, op->cancel_id);
240 if (op->cancellable != NULL)
241 g_object_unref (op->cancellable);
243 g_slice_free (ConnectionOp, op);
248 connection_op_complete (ConnectionOp *op,
251 g_mutex_lock (&op->simple_lock);
253 if (op->simple != NULL && error != NULL)
254 g_simple_async_result_set_from_error (op->simple, error);
256 if (op->simple != NULL) {
257 g_simple_async_result_complete_in_idle (op->simple);
258 g_object_unref (op->simple);
262 g_mutex_unlock (&op->simple_lock);
266 connection_op_cancelled (GCancellable *cancellable,
269 /* Because we called g_simple_async_result_set_check_cancellable()
270 * we don't need to explicitly set a G_IO_ERROR_CANCELLED here. */
271 connection_op_complete (op, NULL);
275 connection_op_add_pending (ConnectionOp *op,
276 GSimpleAsyncResult *simple,
277 GCancellable *cancellable)
279 ConnectionOp *pending_op;
281 g_return_if_fail (op != NULL);
283 pending_op = connection_op_new (simple, cancellable);
285 if (pending_op->cancellable != NULL)
286 pending_op->cancel_id = g_cancellable_connect (
287 pending_op->cancellable,
288 G_CALLBACK (connection_op_cancelled),
289 pending_op, (GDestroyNotify) NULL);
291 g_queue_push_tail (&op->pending, pending_op);
295 connection_op_complete_pending (ConnectionOp *op,
298 ConnectionOp *pending_op;
300 g_return_if_fail (op != NULL);
302 while (!g_queue_is_empty (&op->pending)) {
303 pending_op = g_queue_pop_head (&op->pending);
304 connection_op_complete (pending_op, error);
305 connection_op_unref (pending_op);
310 service_find_old_data_dir (CamelService *service)
312 CamelProvider *provider;
313 CamelSession *session;
316 gboolean allows_host;
317 gboolean allows_user;
321 const gchar *base_dir;
324 provider = camel_service_get_provider (service);
325 session = camel_service_get_session (service);
326 url = camel_service_new_camel_url (service);
328 allows_host = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST);
329 allows_user = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_USER);
331 needs_host = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST);
332 needs_path = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH);
333 needs_user = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER);
335 /* This function reproduces the way service data directories used
336 * to be determined before we moved to just using the UID. If the
337 * old data directory exists, try renaming it to the new form.
339 * A virtual class method was used to determine the directory path,
340 * but no known CamelProviders ever overrode the default algorithm
341 * below. So this should work for everyone. */
343 path = g_string_new (provider->protocol);
346 g_string_append_c (path, '/');
347 if (url->user != NULL)
348 g_string_append (path, url->user);
350 g_string_append_c (path, '@');
351 if (url->host != NULL)
352 g_string_append (path, url->host);
354 g_string_append_c (path, ':');
355 g_string_append_printf (path, "%d", url->port);
357 } else if (!needs_user) {
358 g_string_append_c (path, '@');
361 } else if (allows_host) {
362 g_string_append_c (path, '/');
364 g_string_append_c (path, '@');
365 if (url->host != NULL)
366 g_string_append (path, url->host);
368 g_string_append_c (path, ':');
369 g_string_append_printf (path, "%d", url->port);
373 if (needs_path && url->path) {
374 if (*url->path != '/')
375 g_string_append_c (path, '/');
376 g_string_append (path, url->path);
379 base_dir = camel_session_get_user_data_dir (session);
380 old_data_dir = g_build_filename (base_dir, path->str, NULL);
382 g_string_free (path, TRUE);
384 if (!g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) {
385 g_free (old_data_dir);
389 camel_url_free (url);
395 service_notify_connection_status_cb (gpointer user_data)
397 CamelService *service = CAMEL_SERVICE (user_data);
399 g_object_notify (G_OBJECT (service), "connection-status");
405 service_queue_notify_connection_status (CamelService *service)
407 CamelSession *session;
409 session = camel_service_get_session (service);
411 camel_session_idle_add (
412 session, G_PRIORITY_DEFAULT_IDLE,
413 service_notify_connection_status_cb,
414 g_object_ref (service),
415 (GDestroyNotify) g_object_unref);
419 service_shared_connect_cb (GObject *source_object,
420 GAsyncResult *result,
423 CamelService *service;
424 CamelServiceClass *class;
425 ConnectionOp *op = user_data;
427 GError *error = NULL;
429 /* This avoids a compiler warning
430 * in the CAMEL_CHECK_GERROR macro. */
431 GError **p_error = &error;
433 service = CAMEL_SERVICE (source_object);
434 class = CAMEL_SERVICE_GET_CLASS (service);
435 g_return_if_fail (class->connect_finish != NULL);
437 success = class->connect_finish (service, result, &error);
438 CAMEL_CHECK_GERROR (service, connect_sync, success, p_error);
440 g_mutex_lock (service->priv->connection_lock);
442 if (service->priv->connection_op == op) {
443 connection_op_unref (service->priv->connection_op);
444 service->priv->connection_op = NULL;
446 service->priv->status = CAMEL_SERVICE_CONNECTED;
448 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
449 service_queue_notify_connection_status (service);
452 connection_op_complete (op, error);
453 connection_op_complete_pending (op, error);
455 g_mutex_unlock (service->priv->connection_lock);
457 connection_op_unref (op);
458 g_clear_error (&error);
462 service_shared_disconnect_cb (GObject *source_object,
463 GAsyncResult *result,
466 CamelService *service;
467 CamelServiceClass *class;
468 ConnectionOp *op = user_data;
470 GError *error = NULL;
472 /* This avoids a compiler warning
473 * in the CAMEL_CHECK_GERROR macro. */
474 GError **p_error = &error;
476 service = CAMEL_SERVICE (source_object);
477 class = CAMEL_SERVICE_GET_CLASS (service);
478 g_return_if_fail (class->disconnect_finish != NULL);
480 success = class->disconnect_finish (service, result, &error);
481 CAMEL_CHECK_GERROR (service, disconnect_sync, success, p_error);
483 g_mutex_lock (service->priv->connection_lock);
485 if (service->priv->connection_op == op) {
486 connection_op_unref (service->priv->connection_op);
487 service->priv->connection_op = NULL;
489 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
491 service->priv->status = CAMEL_SERVICE_CONNECTED;
492 service_queue_notify_connection_status (service);
495 connection_op_complete (op, error);
496 connection_op_complete_pending (op, error);
498 g_mutex_unlock (service->priv->connection_lock);
500 connection_op_unref (op);
501 g_clear_error (&error);
505 service_set_provider (CamelService *service,
506 CamelProvider *provider)
508 g_return_if_fail (provider != NULL);
509 g_return_if_fail (service->priv->provider == NULL);
511 service->priv->provider = provider;
515 service_set_session (CamelService *service,
516 CamelSession *session)
518 g_return_if_fail (CAMEL_IS_SESSION (session));
519 g_return_if_fail (service->priv->session == NULL);
521 service->priv->session = session;
523 g_object_add_weak_pointer (
524 G_OBJECT (session), &service->priv->session);
528 service_set_uid (CamelService *service,
531 g_return_if_fail (uid != NULL);
532 g_return_if_fail (service->priv->uid == NULL);
534 service->priv->uid = g_strdup (uid);
538 service_set_property (GObject *object,
543 switch (property_id) {
544 case PROP_DISPLAY_NAME:
545 camel_service_set_display_name (
546 CAMEL_SERVICE (object),
547 g_value_get_string (value));
551 camel_service_set_password (
552 CAMEL_SERVICE (object),
553 g_value_get_string (value));
557 service_set_provider (
558 CAMEL_SERVICE (object),
559 g_value_get_pointer (value));
563 service_set_session (
564 CAMEL_SERVICE (object),
565 g_value_get_object (value));
569 camel_service_set_settings (
570 CAMEL_SERVICE (object),
571 g_value_get_object (value));
576 CAMEL_SERVICE (object),
577 g_value_get_string (value));
581 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
585 service_get_property (GObject *object,
590 switch (property_id) {
591 case PROP_CONNECTION_STATUS:
593 value, camel_service_get_connection_status (
594 CAMEL_SERVICE (object)));
597 case PROP_DISPLAY_NAME:
599 value, camel_service_get_display_name (
600 CAMEL_SERVICE (object)));
605 value, camel_service_get_password (
606 CAMEL_SERVICE (object)));
610 g_value_set_pointer (
611 value, camel_service_get_provider (
612 CAMEL_SERVICE (object)));
617 value, camel_service_get_session (
618 CAMEL_SERVICE (object)));
622 g_value_take_object (
623 value, camel_service_ref_settings (
624 CAMEL_SERVICE (object)));
629 value, camel_service_get_uid (
630 CAMEL_SERVICE (object)));
634 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
638 service_dispose (GObject *object)
640 CamelServicePrivate *priv;
642 priv = CAMEL_SERVICE_GET_PRIVATE (object);
644 if (priv->session != NULL) {
645 g_object_remove_weak_pointer (
646 G_OBJECT (priv->session), &priv->session);
647 priv->session = NULL;
650 if (priv->settings != NULL) {
651 g_object_unref (priv->settings);
652 priv->settings = NULL;
655 /* Chain up to parent's dispose() method. */
656 G_OBJECT_CLASS (camel_service_parent_class)->dispose (object);
660 service_finalize (GObject *object)
662 CamelServicePrivate *priv;
664 priv = CAMEL_SERVICE_GET_PRIVATE (object);
666 if (priv->status == CAMEL_SERVICE_CONNECTED)
667 CAMEL_SERVICE_GET_CLASS (object)->disconnect_sync (
668 CAMEL_SERVICE (object), TRUE, NULL, NULL);
670 g_mutex_free (priv->settings_lock);
672 g_free (priv->display_name);
673 g_free (priv->user_data_dir);
674 g_free (priv->user_cache_dir);
676 g_free (priv->password);
678 /* There should be no outstanding connection operations. */
679 g_warn_if_fail (priv->connection_op == NULL);
680 g_mutex_free (priv->connection_lock);
682 /* Chain up to parent's finalize() method. */
683 G_OBJECT_CLASS (camel_service_parent_class)->finalize (object);
687 service_constructed (GObject *object)
689 CamelService *service;
690 CamelSession *session;
691 const gchar *base_dir;
694 /* Chain up to parent's constructed() method. */
695 G_OBJECT_CLASS (camel_service_parent_class)->constructed (object);
697 service = CAMEL_SERVICE (object);
698 session = camel_service_get_session (service);
700 uid = camel_service_get_uid (service);
702 base_dir = camel_session_get_user_data_dir (session);
703 service->priv->user_data_dir = g_build_filename (base_dir, uid, NULL);
705 base_dir = camel_session_get_user_cache_dir (session);
706 service->priv->user_cache_dir = g_build_filename (base_dir, uid, NULL);
710 service_get_name (CamelService *service,
714 "%s does not implement CamelServiceClass::get_name()",
715 G_OBJECT_TYPE_NAME (service));
717 return g_strdup (G_OBJECT_TYPE_NAME (service));
721 service_connect_sync (CamelService *service,
722 GCancellable *cancellable,
725 /* Default behavior for local storage providers. */
730 service_disconnect_sync (CamelService *service,
732 GCancellable *cancellable,
735 /* Default behavior for local storage providers. */
740 service_query_auth_types_sync (CamelService *service,
741 GCancellable *cancellable,
748 service_connect_thread (GSimpleAsyncResult *simple,
750 GCancellable *cancellable)
752 CamelService *service;
753 CamelServiceClass *class;
754 GError *error = NULL;
756 /* Note we call the class method directly here. */
758 service = CAMEL_SERVICE (object);
760 class = CAMEL_SERVICE_GET_CLASS (service);
761 g_return_if_fail (class->connect_sync != NULL);
763 class->connect_sync (service, cancellable, &error);
766 g_simple_async_result_take_error (simple, error);
770 service_connect (CamelService *service,
772 GCancellable *cancellable,
773 GAsyncReadyCallback callback,
776 GSimpleAsyncResult *simple;
778 simple = g_simple_async_result_new (
779 G_OBJECT (service), callback, user_data, service_connect);
781 g_simple_async_result_set_check_cancellable (simple, cancellable);
783 g_simple_async_result_run_in_thread (
784 simple, service_connect_thread, io_priority, cancellable);
786 g_object_unref (simple);
790 service_connect_finish (CamelService *service,
791 GAsyncResult *result,
794 GSimpleAsyncResult *simple;
796 g_return_val_if_fail (
797 g_simple_async_result_is_valid (
798 result, G_OBJECT (service), service_connect), FALSE);
800 simple = G_SIMPLE_ASYNC_RESULT (result);
802 /* Assume success unless a GError is set. */
803 return !g_simple_async_result_propagate_error (simple, error);
807 service_disconnect_thread (GSimpleAsyncResult *simple,
809 GCancellable *cancellable)
811 CamelService *service;
812 CamelServiceClass *class;
814 GError *error = NULL;
816 /* Note we call the class method directly here. */
818 service = CAMEL_SERVICE (object);
819 clean = g_simple_async_result_get_op_res_gboolean (simple);
821 class = CAMEL_SERVICE_GET_CLASS (service);
822 g_return_if_fail (class->disconnect_sync != NULL);
824 class->disconnect_sync (service, clean, cancellable, &error);
827 g_simple_async_result_take_error (simple, error);
831 service_disconnect (CamelService *service,
834 GCancellable *cancellable,
835 GAsyncReadyCallback callback,
838 GSimpleAsyncResult *simple;
840 simple = g_simple_async_result_new (
841 G_OBJECT (service), callback, user_data, service_disconnect);
843 g_simple_async_result_set_check_cancellable (simple, cancellable);
845 g_simple_async_result_set_op_res_gboolean (simple, clean);
847 g_simple_async_result_run_in_thread (
848 simple, service_disconnect_thread, io_priority, cancellable);
850 g_object_unref (simple);
854 service_disconnect_finish (CamelService *service,
855 GAsyncResult *result,
858 GSimpleAsyncResult *simple;
860 g_return_val_if_fail (
861 g_simple_async_result_is_valid (
862 result, G_OBJECT (service), service_disconnect), FALSE);
864 simple = G_SIMPLE_ASYNC_RESULT (result);
866 /* Assume success unless a GError is set. */
867 return !g_simple_async_result_propagate_error (simple, error);
871 service_authenticate_thread (GSimpleAsyncResult *simple,
873 GCancellable *cancellable)
875 AsyncContext *async_context;
876 GError *error = NULL;
878 async_context = g_simple_async_result_get_op_res_gpointer (simple);
880 async_context->auth_result = camel_service_authenticate_sync (
881 CAMEL_SERVICE (object), async_context->auth_mechanism,
882 cancellable, &error);
885 g_simple_async_result_take_error (simple, error);
889 service_authenticate (CamelService *service,
890 const gchar *mechanism,
892 GCancellable *cancellable,
893 GAsyncReadyCallback callback,
896 GSimpleAsyncResult *simple;
897 AsyncContext *async_context;
899 async_context = g_slice_new0 (AsyncContext);
900 async_context->auth_mechanism = g_strdup (mechanism);
902 simple = g_simple_async_result_new (
903 G_OBJECT (service), callback, user_data, service_authenticate);
905 g_simple_async_result_set_check_cancellable (simple, cancellable);
907 g_simple_async_result_set_op_res_gpointer (
908 simple, async_context, (GDestroyNotify) async_context_free);
910 g_simple_async_result_run_in_thread (
911 simple, service_authenticate_thread, io_priority, cancellable);
913 g_object_unref (simple);
916 static CamelAuthenticationResult
917 service_authenticate_finish (CamelService *service,
918 GAsyncResult *result,
921 GSimpleAsyncResult *simple;
922 AsyncContext *async_context;
924 g_return_val_if_fail (
925 g_simple_async_result_is_valid (
926 result, G_OBJECT (service), service_authenticate),
927 CAMEL_AUTHENTICATION_REJECTED);
929 simple = G_SIMPLE_ASYNC_RESULT (result);
930 async_context = g_simple_async_result_get_op_res_gpointer (simple);
932 if (g_simple_async_result_propagate_error (simple, error))
933 return CAMEL_AUTHENTICATION_ERROR;
935 return async_context->auth_result;
939 service_query_auth_types_thread (GSimpleAsyncResult *simple,
941 GCancellable *cancellable)
943 AsyncContext *async_context;
944 GError *error = NULL;
946 async_context = g_simple_async_result_get_op_res_gpointer (simple);
948 async_context->auth_types = camel_service_query_auth_types_sync (
949 CAMEL_SERVICE (object), cancellable, &error);
952 g_simple_async_result_take_error (simple, error);
956 service_query_auth_types (CamelService *service,
958 GCancellable *cancellable,
959 GAsyncReadyCallback callback,
962 GSimpleAsyncResult *simple;
963 AsyncContext *async_context;
965 async_context = g_slice_new0 (AsyncContext);
967 simple = g_simple_async_result_new (
968 G_OBJECT (service), callback,
969 user_data, service_query_auth_types);
971 g_simple_async_result_set_check_cancellable (simple, cancellable);
973 g_simple_async_result_set_op_res_gpointer (
974 simple, async_context, (GDestroyNotify) async_context_free);
976 g_simple_async_result_run_in_thread (
977 simple, service_query_auth_types_thread,
978 io_priority, cancellable);
980 g_object_unref (simple);
984 service_query_auth_types_finish (CamelService *service,
985 GAsyncResult *result,
988 GSimpleAsyncResult *simple;
989 AsyncContext *async_context;
991 g_return_val_if_fail (
992 g_simple_async_result_is_valid (
993 result, G_OBJECT (service),
994 service_query_auth_types), NULL);
996 simple = G_SIMPLE_ASYNC_RESULT (result);
997 async_context = g_simple_async_result_get_op_res_gpointer (simple);
999 if (g_simple_async_result_propagate_error (simple, error))
1002 return g_list_copy (async_context->auth_types);
1006 service_initable_init (GInitable *initable,
1007 GCancellable *cancellable,
1010 /* Nothing to do here, but we may need add something in the future.
1011 * For now this is a placeholder so subclasses can safely chain up. */
1017 camel_service_class_init (CamelServiceClass *class)
1019 GObjectClass *object_class;
1021 g_type_class_add_private (class, sizeof (CamelServicePrivate));
1023 object_class = G_OBJECT_CLASS (class);
1024 object_class->set_property = service_set_property;
1025 object_class->get_property = service_get_property;
1026 object_class->dispose = service_dispose;
1027 object_class->finalize = service_finalize;
1028 object_class->constructed = service_constructed;
1030 class->settings_type = CAMEL_TYPE_SETTINGS;
1031 class->get_name = service_get_name;
1032 class->connect_sync = service_connect_sync;
1033 class->disconnect_sync = service_disconnect_sync;
1034 class->query_auth_types_sync = service_query_auth_types_sync;
1036 class->connect = service_connect;
1037 class->connect_finish = service_connect_finish;
1038 class->disconnect = service_disconnect;
1039 class->disconnect_finish = service_disconnect_finish;
1040 class->authenticate = service_authenticate;
1041 class->authenticate_finish = service_authenticate_finish;
1042 class->query_auth_types = service_query_auth_types;
1043 class->query_auth_types_finish = service_query_auth_types_finish;
1045 g_object_class_install_property (
1047 PROP_CONNECTION_STATUS,
1049 "connection-status",
1050 "Connection Status",
1051 "The connection status for the service",
1052 CAMEL_TYPE_SERVICE_CONNECTION_STATUS,
1053 CAMEL_SERVICE_DISCONNECTED,
1055 G_PARAM_STATIC_STRINGS));
1057 g_object_class_install_property (
1060 g_param_spec_string (
1063 "The display name for the service",
1067 G_PARAM_STATIC_STRINGS));
1069 g_object_class_install_property (
1072 g_param_spec_string (
1075 "The password for the service",
1079 G_PARAM_STATIC_STRINGS));
1081 g_object_class_install_property (
1084 g_param_spec_pointer (
1087 "The CamelProvider for the service",
1089 G_PARAM_CONSTRUCT_ONLY |
1090 G_PARAM_STATIC_STRINGS));
1092 g_object_class_install_property (
1095 g_param_spec_object (
1098 "A CamelSession instance",
1101 G_PARAM_CONSTRUCT_ONLY |
1102 G_PARAM_STATIC_STRINGS));
1104 g_object_class_install_property (
1107 g_param_spec_object (
1110 "A CamelSettings instance",
1111 CAMEL_TYPE_SETTINGS,
1114 G_PARAM_STATIC_STRINGS));
1116 g_object_class_install_property (
1119 g_param_spec_string (
1122 "The unique identity of the service",
1125 G_PARAM_CONSTRUCT_ONLY |
1126 G_PARAM_STATIC_STRINGS));
1130 camel_service_initable_init (GInitableIface *interface)
1132 interface->init = service_initable_init;
1136 camel_service_init (CamelService *service)
1138 service->priv = CAMEL_SERVICE_GET_PRIVATE (service);
1140 service->priv->settings_lock = g_mutex_new ();
1141 service->priv->connection_lock = g_mutex_new ();
1142 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
1146 camel_service_error_quark (void)
1148 static GQuark quark = 0;
1150 if (G_UNLIKELY (quark == 0)) {
1151 const gchar *string = "camel-service-error-quark";
1152 quark = g_quark_from_static_string (string);
1159 * camel_service_migrate_files:
1160 * @service: a #CamelService
1162 * Performs any necessary file migrations for @service. This should be
1163 * called after installing or configuring the @service's #CamelSettings,
1164 * since it requires building a URL string for @service.
1169 camel_service_migrate_files (CamelService *service)
1171 const gchar *new_data_dir;
1172 gchar *old_data_dir;
1174 g_return_if_fail (CAMEL_IS_SERVICE (service));
1176 new_data_dir = camel_service_get_user_data_dir (service);
1177 old_data_dir = service_find_old_data_dir (service);
1179 /* If the old data directory name exists, try renaming
1180 * it to the new data directory. Failure is non-fatal. */
1181 if (old_data_dir != NULL) {
1182 g_rename (old_data_dir, new_data_dir);
1183 g_free (old_data_dir);
1188 * camel_service_new_camel_url:
1189 * @service: a #CamelService
1191 * Returns a new #CamelURL representing @service.
1192 * Free the returned #CamelURL with camel_url_free().
1194 * Returns: a new #CamelURL
1199 camel_service_new_camel_url (CamelService *service)
1202 CamelProvider *provider;
1203 CamelSettings *settings;
1209 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1211 provider = camel_service_get_provider (service);
1212 g_return_val_if_fail (provider != NULL, NULL);
1214 settings = camel_service_ref_settings (service);
1216 /* Allocate as camel_url_new_with_base() does. */
1217 url = g_new0 (CamelURL, 1);
1219 if (CAMEL_IS_NETWORK_SETTINGS (settings)) {
1220 CamelNetworkSettings *network_settings;
1222 network_settings = CAMEL_NETWORK_SETTINGS (settings);
1223 host = camel_network_settings_dup_host (network_settings);
1224 port = camel_network_settings_get_port (network_settings);
1225 user = camel_network_settings_dup_user (network_settings);
1228 if (CAMEL_IS_LOCAL_SETTINGS (settings)) {
1229 CamelLocalSettings *local_settings;
1231 local_settings = CAMEL_LOCAL_SETTINGS (settings);
1232 path = camel_local_settings_dup_path (local_settings);
1235 camel_url_set_protocol (url, provider->protocol);
1236 camel_url_set_host (url, host);
1237 camel_url_set_port (url, port);
1238 camel_url_set_user (url, user);
1239 camel_url_set_path (url, path);
1245 g_object_unref (settings);
1251 * camel_service_get_connection_status:
1252 * @service: a #CamelService
1254 * Returns the connection status for @service.
1256 * Returns: the connection status
1260 CamelServiceConnectionStatus
1261 camel_service_get_connection_status (CamelService *service)
1263 g_return_val_if_fail (
1264 CAMEL_IS_SERVICE (service),
1265 CAMEL_SERVICE_DISCONNECTED);
1267 return service->priv->status;
1271 * camel_service_get_display_name:
1272 * @service: a #CamelService
1274 * Returns the display name for @service, or %NULL if @service has not
1275 * been given a display name. The display name is intended for use in
1276 * a user interface and should generally be given a user-defined name.
1278 * Compare this with camel_service_get_name(), which returns a built-in
1279 * description of the type of service (IMAP, SMTP, etc.).
1281 * Returns: the display name for @service, or %NULL
1286 camel_service_get_display_name (CamelService *service)
1288 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1290 return service->priv->display_name;
1294 * camel_service_set_display_name:
1295 * @service: a #CamelService
1296 * @display_name: a valid UTF-8 string, or %NULL
1298 * Assigns a UTF-8 display name to @service. The display name is intended
1299 * for use in a user interface and should generally be given a user-defined
1302 * Compare this with camel_service_get_name(), which returns a built-in
1303 * description of the type of service (IMAP, SMTP, etc.).
1308 camel_service_set_display_name (CamelService *service,
1309 const gchar *display_name)
1311 g_return_if_fail (CAMEL_IS_SERVICE (service));
1313 if (g_strcmp0 (service->priv->display_name, display_name) == 0)
1316 if (display_name != NULL)
1317 g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
1319 g_free (service->priv->display_name);
1320 service->priv->display_name = g_strdup (display_name);
1322 g_object_notify (G_OBJECT (service), "display-name");
1326 * camel_service_get_password:
1327 * @service: a #CamelService
1329 * Returns the password for @service. Some SASL mechanisms use this
1330 * when attempting to authenticate.
1332 * Returns: the password for @service
1337 camel_service_get_password (CamelService *service)
1339 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1341 return service->priv->password;
1345 * camel_service_set_password:
1346 * @service: a #CamelService
1347 * @password: the password for @service
1349 * Sets the password for @service. Use this function to cache the password
1350 * in memory after obtaining it through camel_session_get_password(). Some
1351 * SASL mechanisms use this when attempting to authenticate.
1356 camel_service_set_password (CamelService *service,
1357 const gchar *password)
1359 g_return_if_fail (CAMEL_IS_SERVICE (service));
1361 if (g_strcmp0 (service->priv->password, password) == 0)
1364 g_free (service->priv->password);
1365 service->priv->password = g_strdup (password);
1367 g_object_notify (G_OBJECT (service), "password");
1371 * camel_service_get_user_data_dir:
1372 * @service: a #CamelService
1374 * Returns the base directory under which to store user-specific data
1375 * for @service. The directory is formed by appending the directory
1376 * returned by camel_session_get_user_data_dir() with the service's
1377 * #CamelService:uid value.
1379 * Returns: the base directory for @service
1384 camel_service_get_user_data_dir (CamelService *service)
1386 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1388 return service->priv->user_data_dir;
1392 * camel_service_get_user_cache_dir:
1393 * @service: a #CamelService
1395 * Returns the base directory under which to store cache data
1396 * for @service. The directory is formed by appending the directory
1397 * returned by camel_session_get_user_cache_dir() with the service's
1398 * #CamelService:uid value.
1400 * Returns: the base cache directory for @service
1405 camel_service_get_user_cache_dir (CamelService *service)
1407 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1409 return service->priv->user_cache_dir;
1413 * camel_service_get_name:
1414 * @service: a #CamelService
1415 * @brief: whether or not to use a briefer form
1417 * This gets the name of the service in a "friendly" (suitable for
1418 * humans) form. If @brief is %TRUE, this should be a brief description
1419 * such as for use in the folder tree. If @brief is %FALSE, it should
1420 * be a more complete and mostly unambiguous description.
1422 * Returns: a description of the service which the caller must free
1425 camel_service_get_name (CamelService *service,
1428 CamelServiceClass *class;
1430 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1432 class = CAMEL_SERVICE_GET_CLASS (service);
1433 g_return_val_if_fail (class->get_name != NULL, NULL);
1435 return class->get_name (service, brief);
1439 * camel_service_get_provider:
1440 * @service: a #CamelService
1442 * Gets the #CamelProvider associated with the service.
1444 * Returns: the #CamelProvider
1447 camel_service_get_provider (CamelService *service)
1449 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1451 return service->priv->provider;
1455 * camel_service_get_session:
1456 * @service: a #CamelService
1458 * Gets the #CamelSession associated with the service.
1460 * Returns: the #CamelSession
1463 camel_service_get_session (CamelService *service)
1465 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1467 return CAMEL_SESSION (service->priv->session);
1471 * camel_service_ref_settings:
1472 * @service: a #CamelService
1474 * Returns the #CamelSettings instance associated with the service.
1476 * The returned #CamelSettings is referenced for thread-safety and must
1477 * be unreferenced with g_object_unref() when finished with it.
1479 * Returns: the #CamelSettings
1484 camel_service_ref_settings (CamelService *service)
1486 CamelSettings *settings;
1488 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1490 /* Every service should have a settings object. */
1491 g_return_val_if_fail (service->priv->settings != NULL, NULL);
1493 g_mutex_lock (service->priv->settings_lock);
1495 settings = g_object_ref (service->priv->settings);
1497 g_mutex_unlock (service->priv->settings_lock);
1503 * camel_service_set_settings:
1504 * @service: a #CamelService
1505 * @settings: an instance derviced from #CamelSettings, or %NULL
1507 * Associates a new #CamelSettings instance with the service.
1508 * The @settings instance must match the settings type defined in
1509 * #CamelServiceClass. If @settings is %NULL, a new #CamelSettings
1510 * instance of the appropriate type is created with all properties
1516 camel_service_set_settings (CamelService *service,
1517 CamelSettings *settings)
1519 CamelServiceClass *class;
1521 g_return_if_fail (CAMEL_IS_SERVICE (service));
1523 class = CAMEL_SERVICE_GET_CLASS (service);
1525 if (settings != NULL) {
1528 G_OBJECT_TYPE (settings),
1529 class->settings_type));
1530 g_object_ref (settings);
1535 class->settings_type,
1536 CAMEL_TYPE_SETTINGS));
1537 settings = g_object_new (class->settings_type, NULL);
1540 g_mutex_lock (service->priv->settings_lock);
1542 if (service->priv->settings != NULL)
1543 g_object_unref (service->priv->settings);
1545 service->priv->settings = settings; /* takes ownership */
1547 g_mutex_unlock (service->priv->settings_lock);
1549 g_object_notify (G_OBJECT (service), "settings");
1553 * camel_service_get_uid:
1554 * @service: a #CamelService
1556 * Gets the unique identifier string associated with the service.
1558 * Returns: the UID string
1563 camel_service_get_uid (CamelService *service)
1565 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1567 return service->priv->uid;
1571 * camel_service_connect_sync:
1572 * @service: a #CamelService
1573 * @cancellable: optional #GCancellable object, or %NULL
1574 * @error: return location for a #GError, or %NULL
1576 * Connects @service to a remote server using the information in its
1577 * #CamelService:settings instance.
1579 * If a connect operation is already in progress when this function is
1580 * called, its results will be reflected in this connect operation.
1582 * Returns: %TRUE if the connection is made or %FALSE otherwise
1587 camel_service_connect_sync (CamelService *service,
1588 GCancellable *cancellable,
1591 AsyncClosure *closure;
1592 GAsyncResult *result;
1595 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1597 closure = async_closure_new ();
1599 camel_service_connect (
1600 service, G_PRIORITY_DEFAULT, cancellable,
1601 async_closure_callback, closure);
1603 result = async_closure_wait (closure);
1605 success = camel_service_connect_finish (service, result, error);
1607 async_closure_free (closure);
1613 * camel_service_connect:
1614 * @service: a #CamelService
1615 * @io_priority: the I/O priority of the request
1616 * @cancellable: optional #GCancellable object, or %NULL
1617 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1618 * @user_data: data to pass to the callback function
1620 * Asynchronously connects @service to a remote server using the information
1621 * in its #CamelService:settings instance.
1623 * If a connect operation is already in progress when this function is
1624 * called, its results will be reflected in this connect operation.
1626 * If any disconnect operations are in progress when this function is
1627 * called, they will be cancelled.
1629 * When the operation is finished, @callback will be called. You can
1630 * then call camel_service_connect_finish() to get the result of the
1636 camel_service_connect (CamelService *service,
1638 GCancellable *cancellable,
1639 GAsyncReadyCallback callback,
1643 CamelServiceClass *class;
1644 GSimpleAsyncResult *simple;
1646 g_return_if_fail (CAMEL_IS_SERVICE (service));
1648 class = CAMEL_SERVICE_GET_CLASS (service);
1649 g_return_if_fail (class->connect != NULL);
1651 simple = g_simple_async_result_new (
1652 G_OBJECT (service), callback,
1653 user_data, camel_service_connect);
1655 g_simple_async_result_set_check_cancellable (simple, cancellable);
1657 g_mutex_lock (service->priv->connection_lock);
1659 switch (service->priv->status) {
1661 /* If a connect operation is already in progress,
1662 * queue this operation so it completes at the same
1663 * time the first connect operation completes. */
1664 case CAMEL_SERVICE_CONNECTING:
1665 connection_op_add_pending (
1666 service->priv->connection_op,
1667 simple, cancellable);
1670 /* If we're already connected, just report success. */
1671 case CAMEL_SERVICE_CONNECTED:
1672 g_simple_async_result_complete_in_idle (simple);
1675 /* If a disconnect operation is currently in progress,
1676 * cancel it and make room for the connect operation. */
1677 case CAMEL_SERVICE_DISCONNECTING:
1679 service->priv->connection_op != NULL);
1680 g_cancellable_cancel (
1681 service->priv->connection_op->cancellable);
1682 connection_op_unref (service->priv->connection_op);
1683 service->priv->connection_op = NULL;
1686 /* Start a new connect operation. Subsequent connect
1687 * operations are queued until this operation completes
1688 * and will share this operation's result. */
1689 case CAMEL_SERVICE_DISCONNECTED:
1691 service->priv->connection_op == NULL);
1693 op = connection_op_new (simple, cancellable);
1694 service->priv->connection_op = op;
1696 service->priv->status = CAMEL_SERVICE_CONNECTING;
1697 service_queue_notify_connection_status (service);
1703 service_shared_connect_cb,
1704 connection_op_ref (op));
1708 g_warn_if_reached ();
1711 g_mutex_unlock (service->priv->connection_lock);
1713 g_object_unref (simple);
1717 * camel_service_connect_finish:
1718 * @service: a #CamelService
1719 * @result: a #GAsyncResult
1720 * @error: return location for a #GError, or %NULL
1722 * Finishes the operation started with camel_service_connect().
1724 * Returns: %TRUE if the connection was made or %FALSE otherwise
1729 camel_service_connect_finish (CamelService *service,
1730 GAsyncResult *result,
1733 GSimpleAsyncResult *simple;
1735 g_return_val_if_fail (
1736 g_simple_async_result_is_valid (
1737 result, G_OBJECT (service), camel_service_connect), FALSE);
1739 simple = G_SIMPLE_ASYNC_RESULT (result);
1741 /* Assume success unless a GError is set. */
1742 return !g_simple_async_result_propagate_error (simple, error);
1746 * camel_service_disconnect_sync:
1747 * @service: a #CamelService
1748 * @clean: whether or not to try to disconnect cleanly
1749 * @cancellable: optional #GCancellable object, or %NULL
1750 * @error: return location for a #GError, or %NULL
1752 * Disconnect from the service. If @clean is %FALSE, it should not
1753 * try to do any synchronizing or other cleanup of the connection.
1755 * If a disconnect operation is already in progress when this function is
1756 * called, its results will be reflected in this disconnect operation.
1758 * If any connect operations are in progress when this function is called,
1759 * they will be cancelled.
1761 * Returns: %TRUE if the connection was severed or %FALSE otherwise
1766 camel_service_disconnect_sync (CamelService *service,
1768 GCancellable *cancellable,
1771 AsyncClosure *closure;
1772 GAsyncResult *result;
1775 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1777 closure = async_closure_new ();
1779 camel_service_disconnect (
1780 service, clean, G_PRIORITY_DEFAULT,
1781 cancellable, async_closure_callback, closure);
1783 result = async_closure_wait (closure);
1785 success = camel_service_disconnect_finish (service, result, error);
1787 async_closure_free (closure);
1793 * camel_service_disconnect:
1794 * @service: a #CamelService
1795 * @clean: whether or not to try to disconnect cleanly
1796 * @io_priority: the I/O priority of the request
1797 * @cancellable: optional #GCancellable object, or %NULL
1798 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1799 * @user_data: data to pass to the callback function
1801 * If a disconnect operation is already in progress when this function is
1802 * called, its results will be reflected in this disconnect operation.
1804 * If any connect operations are in progress when this function is called,
1805 * they will be cancelled.
1807 * When the operation is finished, @callback will be called. You can
1808 * then call camel_service_disconnect_finish() to get the result of the
1814 camel_service_disconnect (CamelService *service,
1817 GCancellable *cancellable,
1818 GAsyncReadyCallback callback,
1822 CamelServiceClass *class;
1823 GSimpleAsyncResult *simple;
1825 g_return_if_fail (CAMEL_IS_SERVICE (service));
1827 class = CAMEL_SERVICE_GET_CLASS (service);
1828 g_return_if_fail (class->disconnect != NULL);
1830 simple = g_simple_async_result_new (
1831 G_OBJECT (service), callback,
1832 user_data, camel_service_disconnect);
1834 g_simple_async_result_set_check_cancellable (simple, cancellable);
1836 g_mutex_lock (service->priv->connection_lock);
1838 switch (service->priv->status) {
1840 /* If a connect operation is currently in progress,
1841 * cancel it and make room for the disconnect operation. */
1842 case CAMEL_SERVICE_CONNECTING:
1844 service->priv->connection_op != NULL);
1845 g_cancellable_cancel (
1846 service->priv->connection_op->cancellable);
1847 connection_op_unref (service->priv->connection_op);
1848 service->priv->connection_op = NULL;
1851 /* Start a new disconnect operation. Subsequent disconnect
1852 * operations are queued until this operation completes and
1853 * will share this operation's result. */
1854 case CAMEL_SERVICE_CONNECTED:
1856 service->priv->connection_op == NULL);
1858 op = connection_op_new (simple, cancellable);
1859 service->priv->connection_op = op;
1861 service->priv->status = CAMEL_SERVICE_DISCONNECTING;
1862 service_queue_notify_connection_status (service);
1868 service_shared_disconnect_cb,
1869 connection_op_ref (op));
1872 /* If a disconnect operation is already in progress,
1873 * queue this operation so it completes at the same
1874 * time the first disconnect operation completes. */
1875 case CAMEL_SERVICE_DISCONNECTING:
1876 connection_op_add_pending (
1877 service->priv->connection_op,
1878 simple, cancellable);
1881 /* If we're already disconnected, just report success. */
1882 case CAMEL_SERVICE_DISCONNECTED:
1883 g_simple_async_result_complete_in_idle (simple);
1887 g_warn_if_reached ();
1890 g_mutex_unlock (service->priv->connection_lock);
1892 g_object_unref (simple);
1896 * camel_service_disconnect_finish:
1897 * @service: a #CamelService
1898 * @result: a #GAsyncResult
1899 * @error: return location for a #GError, or %NULL
1901 * Finishes the operation started with camel_service_disconnect().
1903 * Returns: %TRUE if the connection was severed or %FALSE otherwise
1908 camel_service_disconnect_finish (CamelService *service,
1909 GAsyncResult *result,
1912 GSimpleAsyncResult *simple;
1914 g_return_val_if_fail (
1915 g_simple_async_result_is_valid (
1916 result, G_OBJECT (service), camel_service_disconnect), FALSE);
1918 simple = G_SIMPLE_ASYNC_RESULT (result);
1920 /* Assume success unless a GError is set. */
1921 return !g_simple_async_result_propagate_error (simple, error);
1925 * camel_service_authenticate_sync:
1926 * @service: a #CamelService
1927 * @mechanism: a SASL mechanism name, or %NULL
1928 * @cancellable: optional #GCancellable object, or %NULL
1929 * @error: return location for a #GError, or %NULL
1931 * Attempts to authenticate @service using @mechanism and, if necessary,
1932 * @service's #CamelService:password property. The function makes only
1933 * ONE attempt at authentication and does not loop.
1935 * If the authentication attempt completed and the server accepted the
1936 * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
1938 * If the authentication attempt completed but the server rejected the
1939 * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
1941 * If the authentication attempt failed to complete due to a network
1942 * communication issue or some other mishap, the function sets @error
1943 * and returns #CAMEL_AUTHENTICATION_ERROR.
1945 * Generally this function should only be called from a #CamelSession
1946 * subclass in order to implement its own authentication loop.
1948 * Returns: the authentication result
1952 CamelAuthenticationResult
1953 camel_service_authenticate_sync (CamelService *service,
1954 const gchar *mechanism,
1955 GCancellable *cancellable,
1958 CamelServiceClass *class;
1959 CamelAuthenticationResult result;
1961 g_return_val_if_fail (
1962 CAMEL_IS_SERVICE (service),
1963 CAMEL_AUTHENTICATION_REJECTED);
1965 class = CAMEL_SERVICE_GET_CLASS (service);
1966 g_return_val_if_fail (
1967 class->authenticate_sync != NULL,
1968 CAMEL_AUTHENTICATION_REJECTED);
1970 result = class->authenticate_sync (
1971 service, mechanism, cancellable, error);
1972 CAMEL_CHECK_GERROR (
1973 service, authenticate_sync,
1974 result != CAMEL_AUTHENTICATION_ERROR, error);
1980 * camel_service_authenticate:
1981 * @service: a #CamelService
1982 * @mechanism: a SASL mechanism name, or %NULL
1983 * @io_priority: the I/O priority of the request
1984 * @cancellable: optional #GCancellable object, or %NULL
1985 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1986 * @user_data: data to pass to the callback function
1988 * Asynchronously attempts to authenticate @service using @mechanism and,
1989 * if necessary, @service's #CamelService:password property. The function
1990 * makes only ONE attempt at authentication and does not loop.
1992 * Generally this function should only be called from a #CamelSession
1993 * subclass in order to implement its own authentication loop.
1995 * When the operation is finished, @callback will be called. You can
1996 * then call camel_service_authenticate_finish() to get the result of
2002 camel_service_authenticate (CamelService *service,
2003 const gchar *mechanism,
2005 GCancellable *cancellable,
2006 GAsyncReadyCallback callback,
2009 CamelServiceClass *class;
2011 g_return_if_fail (CAMEL_IS_SERVICE (service));
2013 class = CAMEL_SERVICE_GET_CLASS (service);
2014 g_return_if_fail (class->authenticate != NULL);
2016 class->authenticate (
2017 service, mechanism, io_priority,
2018 cancellable, callback, user_data);
2022 * camel_service_authenticate_finish:
2023 * @service: a #CamelService
2024 * @result: a #GAsyncResult
2025 * @error: return location for a #GError, or %NULL
2027 * Finishes the operation started with camel_service_authenticate().
2029 * If the authentication attempt completed and the server accepted the
2030 * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
2032 * If the authentication attempt completed but the server rejected the
2033 * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
2035 * If the authentication attempt failed to complete due to a network
2036 * communication issue or some other mishap, the function sets @error
2037 * and returns #CAMEL_AUTHENTICATION_ERROR.
2039 * Returns: the authentication result
2043 CamelAuthenticationResult
2044 camel_service_authenticate_finish (CamelService *service,
2045 GAsyncResult *result,
2048 CamelServiceClass *class;
2050 g_return_val_if_fail (
2051 CAMEL_IS_SERVICE (service),
2052 CAMEL_AUTHENTICATION_REJECTED);
2053 g_return_val_if_fail (
2054 G_IS_ASYNC_RESULT (result),
2055 CAMEL_AUTHENTICATION_REJECTED);
2057 class = CAMEL_SERVICE_GET_CLASS (service);
2058 g_return_val_if_fail (
2059 class->authenticate_finish,
2060 CAMEL_AUTHENTICATION_REJECTED);
2062 return class->authenticate_finish (service, result, error);
2066 * camel_service_query_auth_types_sync:
2067 * @service: a #CamelService
2068 * @cancellable: optional #GCancellable object, or %NULL
2069 * @error: return location for a #GError, or %NULL
2071 * Obtains a list of authentication types supported by @service.
2072 * Free the returned list with g_list_free().
2074 * Returns: a list of #CamelServiceAuthType structs
2077 camel_service_query_auth_types_sync (CamelService *service,
2078 GCancellable *cancellable,
2081 CamelServiceClass *class;
2083 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
2085 class = CAMEL_SERVICE_GET_CLASS (service);
2086 g_return_val_if_fail (class->query_auth_types_sync != NULL, NULL);
2088 return class->query_auth_types_sync (service, cancellable, error);
2092 * camel_service_query_auth_types:
2093 * @service: a #CamelService
2094 * @io_priority: the I/O priority of the request
2095 * @cancellable: optional #GCancellable object, or %NULL
2096 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2097 * @user_data: data to pass to the callback function
2099 * Asynchronously obtains a list of authentication types supported by
2102 * When the operation is finished, @callback will be called. You can
2103 * then call camel_service_query_auth_types_finish() to get the result
2109 camel_service_query_auth_types (CamelService *service,
2111 GCancellable *cancellable,
2112 GAsyncReadyCallback callback,
2115 CamelServiceClass *class;
2117 g_return_if_fail (CAMEL_IS_SERVICE (service));
2119 class = CAMEL_SERVICE_GET_CLASS (service);
2120 g_return_if_fail (class->query_auth_types != NULL);
2122 class->query_auth_types (
2123 service, io_priority,
2124 cancellable, callback, user_data);
2128 * camel_service_query_auth_types_finish:
2129 * @service: a #CamelService
2130 * @result: a #GAsyncResult
2131 * @error: return location for a #GError, or %NULL
2133 * Finishes the operation started with camel_service_query_auth_types().
2134 * Free the returned list with g_list_free().
2136 * Returns: a list of #CamelServiceAuthType structs
2141 camel_service_query_auth_types_finish (CamelService *service,
2142 GAsyncResult *result,
2145 CamelServiceClass *class;
2147 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
2148 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
2150 class = CAMEL_SERVICE_GET_CLASS (service);
2151 g_return_val_if_fail (class->query_auth_types_finish != NULL, NULL);
2153 return class->query_auth_types_finish (service, result, error);