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 CamelProvider *provider;
65 gchar *user_cache_dir;
69 GMutex *connection_lock;
70 ConnectionOp *connection_op;
71 CamelServiceConnectionStatus status;
74 /* This is copied from EAsyncClosure in libedataserver.
75 * If this proves useful elsewhere in Camel we may want
76 * to split this out and make it part of the public API. */
77 struct _AsyncClosure {
79 GMainContext *context;
83 struct _AsyncContext {
85 gchar *auth_mechanism;
86 CamelAuthenticationResult auth_result;
89 /* The GQueue is only modified while CamelService's
90 * connection_lock is held, so it does not need its
92 struct _ConnectionOp {
93 volatile gint ref_count;
96 GSimpleAsyncResult *simple;
97 GCancellable *cancellable;
103 PROP_CONNECTION_STATUS,
112 /* Forward Declarations */
113 static void camel_service_initable_init (GInitableIface *interface);
115 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
116 CamelService, camel_service, CAMEL_TYPE_OBJECT,
117 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, camel_service_initable_init))
119 static AsyncClosure *
120 async_closure_new (void)
122 AsyncClosure *closure;
124 closure = g_slice_new0 (AsyncClosure);
125 closure->context = g_main_context_new ();
126 closure->loop = g_main_loop_new (closure->context, FALSE);
128 g_main_context_push_thread_default (closure->context);
133 static GAsyncResult *
134 async_closure_wait (AsyncClosure *closure)
136 g_return_val_if_fail (closure != NULL, NULL);
138 g_main_loop_run (closure->loop);
140 return closure->result;
144 async_closure_free (AsyncClosure *closure)
146 g_return_if_fail (closure != NULL);
148 g_main_context_pop_thread_default (closure->context);
150 g_main_loop_unref (closure->loop);
151 g_main_context_unref (closure->context);
153 if (closure->result != NULL)
154 g_object_unref (closure->result);
156 g_slice_free (AsyncClosure, closure);
160 async_closure_callback (GObject *object,
161 GAsyncResult *result,
164 AsyncClosure *real_closure;
166 g_return_if_fail (G_IS_OBJECT (object));
167 g_return_if_fail (G_IS_ASYNC_RESULT (result));
168 g_return_if_fail (closure != NULL);
170 real_closure = closure;
172 /* Replace any previous result. */
173 if (real_closure->result != NULL)
174 g_object_unref (real_closure->result);
175 real_closure->result = g_object_ref (result);
177 g_main_loop_quit (real_closure->loop);
181 async_context_free (AsyncContext *async_context)
183 g_list_free (async_context->auth_types);
185 g_free (async_context->auth_mechanism);
187 g_slice_free (AsyncContext, async_context);
190 static ConnectionOp *
191 connection_op_new (GSimpleAsyncResult *simple,
192 GCancellable *cancellable)
196 op = g_slice_new0 (ConnectionOp);
198 g_mutex_init (&op->simple_lock);
199 op->simple = g_object_ref (simple);
201 if (G_IS_CANCELLABLE (cancellable))
202 op->cancellable = g_object_ref (cancellable);
207 static ConnectionOp *
208 connection_op_ref (ConnectionOp *op)
210 g_return_val_if_fail (op != NULL, NULL);
211 g_return_val_if_fail (op->ref_count > 0, NULL);
213 g_atomic_int_inc (&op->ref_count);
219 connection_op_unref (ConnectionOp *op)
221 g_return_if_fail (op != NULL);
222 g_return_if_fail (op->ref_count > 0);
224 if (g_atomic_int_dec_and_test (&op->ref_count)) {
226 /* The pending queue should be empty. */
227 g_warn_if_fail (g_queue_is_empty (&op->pending));
229 g_mutex_clear (&op->simple_lock);
231 if (op->simple != NULL)
232 g_object_unref (op->simple);
234 if (op->cancel_id > 0)
235 g_cancellable_disconnect (
236 op->cancellable, op->cancel_id);
238 if (op->cancellable != NULL)
239 g_object_unref (op->cancellable);
241 g_slice_free (ConnectionOp, op);
246 connection_op_complete (ConnectionOp *op,
249 g_mutex_lock (&op->simple_lock);
251 if (op->simple != NULL && error != NULL)
252 g_simple_async_result_set_from_error (op->simple, error);
254 if (op->simple != NULL) {
255 g_simple_async_result_complete_in_idle (op->simple);
256 g_object_unref (op->simple);
260 g_mutex_unlock (&op->simple_lock);
264 connection_op_cancelled (GCancellable *cancellable,
267 /* Because we called g_simple_async_result_set_check_cancellable()
268 * we don't need to explicitly set a G_IO_ERROR_CANCELLED here. */
269 connection_op_complete (op, NULL);
273 connection_op_add_pending (ConnectionOp *op,
274 GSimpleAsyncResult *simple,
275 GCancellable *cancellable)
277 ConnectionOp *pending_op;
279 g_return_if_fail (op != NULL);
281 pending_op = connection_op_new (simple, cancellable);
283 if (pending_op->cancellable != NULL)
284 pending_op->cancel_id = g_cancellable_connect (
285 pending_op->cancellable,
286 G_CALLBACK (connection_op_cancelled),
287 pending_op, (GDestroyNotify) NULL);
289 g_queue_push_tail (&op->pending, pending_op);
293 connection_op_complete_pending (ConnectionOp *op,
296 ConnectionOp *pending_op;
298 g_return_if_fail (op != NULL);
300 while (!g_queue_is_empty (&op->pending)) {
301 pending_op = g_queue_pop_head (&op->pending);
302 connection_op_complete (pending_op, error);
303 connection_op_unref (pending_op);
308 service_find_old_data_dir (CamelService *service)
310 CamelProvider *provider;
311 CamelSession *session;
314 gboolean allows_host;
315 gboolean allows_user;
319 const gchar *base_dir;
322 provider = camel_service_get_provider (service);
323 session = camel_service_get_session (service);
324 url = camel_service_new_camel_url (service);
326 allows_host = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST);
327 allows_user = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_USER);
329 needs_host = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST);
330 needs_path = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH);
331 needs_user = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER);
333 /* This function reproduces the way service data directories used
334 * to be determined before we moved to just using the UID. If the
335 * old data directory exists, try renaming it to the new form.
337 * A virtual class method was used to determine the directory path,
338 * but no known CamelProviders ever overrode the default algorithm
339 * below. So this should work for everyone. */
341 path = g_string_new (provider->protocol);
344 g_string_append_c (path, '/');
345 if (url->user != NULL)
346 g_string_append (path, url->user);
348 g_string_append_c (path, '@');
349 if (url->host != NULL)
350 g_string_append (path, url->host);
352 g_string_append_c (path, ':');
353 g_string_append_printf (path, "%d", url->port);
355 } else if (!needs_user) {
356 g_string_append_c (path, '@');
359 } else if (allows_host) {
360 g_string_append_c (path, '/');
362 g_string_append_c (path, '@');
363 if (url->host != NULL)
364 g_string_append (path, url->host);
366 g_string_append_c (path, ':');
367 g_string_append_printf (path, "%d", url->port);
371 if (needs_path && url->path) {
372 if (*url->path != '/')
373 g_string_append_c (path, '/');
374 g_string_append (path, url->path);
377 base_dir = camel_session_get_user_data_dir (session);
378 old_data_dir = g_build_filename (base_dir, path->str, NULL);
380 g_string_free (path, TRUE);
382 if (!g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) {
383 g_free (old_data_dir);
387 camel_url_free (url);
393 service_notify_connection_status_cb (gpointer user_data)
395 CamelService *service = CAMEL_SERVICE (user_data);
397 g_object_notify (G_OBJECT (service), "connection-status");
403 service_queue_notify_connection_status (CamelService *service)
405 CamelSession *session;
407 session = camel_service_get_session (service);
409 camel_session_idle_add (
410 session, G_PRIORITY_DEFAULT_IDLE,
411 service_notify_connection_status_cb,
412 g_object_ref (service),
413 (GDestroyNotify) g_object_unref);
417 service_shared_connect_cb (GObject *source_object,
418 GAsyncResult *result,
421 CamelService *service;
422 CamelServiceClass *class;
423 ConnectionOp *op = user_data;
425 GError *error = NULL;
427 /* This avoids a compiler warning
428 * in the CAMEL_CHECK_GERROR macro. */
429 GError **p_error = &error;
431 service = CAMEL_SERVICE (source_object);
432 class = CAMEL_SERVICE_GET_CLASS (service);
433 g_return_if_fail (class->connect_finish != NULL);
435 success = class->connect_finish (service, result, &error);
436 CAMEL_CHECK_GERROR (service, connect_sync, success, p_error);
438 g_mutex_lock (service->priv->connection_lock);
440 if (service->priv->connection_op == op) {
441 connection_op_unref (service->priv->connection_op);
442 service->priv->connection_op = NULL;
444 service->priv->status = CAMEL_SERVICE_CONNECTED;
446 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
447 service_queue_notify_connection_status (service);
450 connection_op_complete (op, error);
451 connection_op_complete_pending (op, error);
453 g_mutex_unlock (service->priv->connection_lock);
455 connection_op_unref (op);
456 g_clear_error (&error);
460 service_shared_disconnect_cb (GObject *source_object,
461 GAsyncResult *result,
464 CamelService *service;
465 CamelServiceClass *class;
466 ConnectionOp *op = user_data;
468 GError *error = NULL;
470 /* This avoids a compiler warning
471 * in the CAMEL_CHECK_GERROR macro. */
472 GError **p_error = &error;
474 service = CAMEL_SERVICE (source_object);
475 class = CAMEL_SERVICE_GET_CLASS (service);
476 g_return_if_fail (class->disconnect_finish != NULL);
478 success = class->disconnect_finish (service, result, &error);
479 CAMEL_CHECK_GERROR (service, disconnect_sync, success, p_error);
481 g_mutex_lock (service->priv->connection_lock);
483 if (service->priv->connection_op == op) {
484 connection_op_unref (service->priv->connection_op);
485 service->priv->connection_op = NULL;
487 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
489 service->priv->status = CAMEL_SERVICE_CONNECTED;
490 service_queue_notify_connection_status (service);
493 connection_op_complete (op, error);
494 connection_op_complete_pending (op, error);
496 g_mutex_unlock (service->priv->connection_lock);
498 connection_op_unref (op);
499 g_clear_error (&error);
503 service_set_provider (CamelService *service,
504 CamelProvider *provider)
506 g_return_if_fail (provider != NULL);
507 g_return_if_fail (service->priv->provider == NULL);
509 service->priv->provider = provider;
513 service_set_session (CamelService *service,
514 CamelSession *session)
516 g_return_if_fail (CAMEL_IS_SESSION (session));
517 g_return_if_fail (service->priv->session == NULL);
519 service->priv->session = session;
521 g_object_add_weak_pointer (
522 G_OBJECT (session), &service->priv->session);
526 service_set_uid (CamelService *service,
529 g_return_if_fail (uid != NULL);
530 g_return_if_fail (service->priv->uid == NULL);
532 service->priv->uid = g_strdup (uid);
536 service_set_property (GObject *object,
541 switch (property_id) {
542 case PROP_DISPLAY_NAME:
543 camel_service_set_display_name (
544 CAMEL_SERVICE (object),
545 g_value_get_string (value));
549 camel_service_set_password (
550 CAMEL_SERVICE (object),
551 g_value_get_string (value));
555 service_set_provider (
556 CAMEL_SERVICE (object),
557 g_value_get_pointer (value));
561 service_set_session (
562 CAMEL_SERVICE (object),
563 g_value_get_object (value));
567 camel_service_set_settings (
568 CAMEL_SERVICE (object),
569 g_value_get_object (value));
574 CAMEL_SERVICE (object),
575 g_value_get_string (value));
579 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
583 service_get_property (GObject *object,
588 switch (property_id) {
589 case PROP_CONNECTION_STATUS:
591 value, camel_service_get_connection_status (
592 CAMEL_SERVICE (object)));
595 case PROP_DISPLAY_NAME:
597 value, camel_service_get_display_name (
598 CAMEL_SERVICE (object)));
603 value, camel_service_get_password (
604 CAMEL_SERVICE (object)));
608 g_value_set_pointer (
609 value, camel_service_get_provider (
610 CAMEL_SERVICE (object)));
615 value, camel_service_get_session (
616 CAMEL_SERVICE (object)));
621 value, camel_service_get_settings (
622 CAMEL_SERVICE (object)));
627 value, camel_service_get_uid (
628 CAMEL_SERVICE (object)));
632 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
636 service_dispose (GObject *object)
638 CamelServicePrivate *priv;
640 priv = CAMEL_SERVICE_GET_PRIVATE (object);
642 if (priv->session != NULL) {
643 g_object_remove_weak_pointer (
644 G_OBJECT (priv->session), &priv->session);
645 priv->session = NULL;
648 if (priv->settings != NULL) {
649 g_object_unref (priv->settings);
650 priv->settings = NULL;
653 /* Chain up to parent's dispose() method. */
654 G_OBJECT_CLASS (camel_service_parent_class)->dispose (object);
658 service_finalize (GObject *object)
660 CamelServicePrivate *priv;
662 priv = CAMEL_SERVICE_GET_PRIVATE (object);
664 if (priv->status == CAMEL_SERVICE_CONNECTED)
665 CAMEL_SERVICE_GET_CLASS (object)->disconnect_sync (
666 CAMEL_SERVICE (object), TRUE, NULL, NULL);
668 g_free (priv->display_name);
669 g_free (priv->user_data_dir);
670 g_free (priv->user_cache_dir);
672 g_free (priv->password);
674 /* There should be no outstanding connection operations. */
675 g_warn_if_fail (priv->connection_op == NULL);
676 g_mutex_free (priv->connection_lock);
678 /* Chain up to parent's finalize() method. */
679 G_OBJECT_CLASS (camel_service_parent_class)->finalize (object);
683 service_constructed (GObject *object)
685 CamelService *service;
686 CamelSession *session;
687 const gchar *base_dir;
690 /* Chain up to parent's constructed() method. */
691 G_OBJECT_CLASS (camel_service_parent_class)->constructed (object);
693 service = CAMEL_SERVICE (object);
694 session = camel_service_get_session (service);
696 uid = camel_service_get_uid (service);
698 base_dir = camel_session_get_user_data_dir (session);
699 service->priv->user_data_dir = g_build_filename (base_dir, uid, NULL);
701 base_dir = camel_session_get_user_cache_dir (session);
702 service->priv->user_cache_dir = g_build_filename (base_dir, uid, NULL);
706 service_get_name (CamelService *service,
710 "%s does not implement CamelServiceClass::get_name()",
711 G_OBJECT_TYPE_NAME (service));
713 return g_strdup (G_OBJECT_TYPE_NAME (service));
717 service_connect_sync (CamelService *service,
718 GCancellable *cancellable,
721 /* Default behavior for local storage providers. */
726 service_disconnect_sync (CamelService *service,
728 GCancellable *cancellable,
731 /* Default behavior for local storage providers. */
736 service_query_auth_types_sync (CamelService *service,
737 GCancellable *cancellable,
744 service_connect_thread (GSimpleAsyncResult *simple,
746 GCancellable *cancellable)
748 CamelService *service;
749 CamelServiceClass *class;
750 GError *error = NULL;
752 /* Note we call the class method directly here. */
754 service = CAMEL_SERVICE (object);
756 class = CAMEL_SERVICE_GET_CLASS (service);
757 g_return_if_fail (class->connect_sync != NULL);
759 class->connect_sync (service, cancellable, &error);
762 g_simple_async_result_take_error (simple, error);
766 service_connect (CamelService *service,
768 GCancellable *cancellable,
769 GAsyncReadyCallback callback,
772 GSimpleAsyncResult *simple;
774 simple = g_simple_async_result_new (
775 G_OBJECT (service), callback, user_data, service_connect);
777 g_simple_async_result_set_check_cancellable (simple, cancellable);
779 g_simple_async_result_run_in_thread (
780 simple, service_connect_thread, io_priority, cancellable);
782 g_object_unref (simple);
786 service_connect_finish (CamelService *service,
787 GAsyncResult *result,
790 GSimpleAsyncResult *simple;
792 g_return_val_if_fail (
793 g_simple_async_result_is_valid (
794 result, G_OBJECT (service), service_connect), FALSE);
796 simple = G_SIMPLE_ASYNC_RESULT (result);
798 /* Assume success unless a GError is set. */
799 return !g_simple_async_result_propagate_error (simple, error);
803 service_disconnect_thread (GSimpleAsyncResult *simple,
805 GCancellable *cancellable)
807 CamelService *service;
808 CamelServiceClass *class;
810 GError *error = NULL;
812 /* Note we call the class method directly here. */
814 service = CAMEL_SERVICE (object);
815 clean = g_simple_async_result_get_op_res_gboolean (simple);
817 class = CAMEL_SERVICE_GET_CLASS (service);
818 g_return_if_fail (class->disconnect_sync != NULL);
820 class->disconnect_sync (service, clean, cancellable, &error);
823 g_simple_async_result_take_error (simple, error);
827 service_disconnect (CamelService *service,
830 GCancellable *cancellable,
831 GAsyncReadyCallback callback,
834 GSimpleAsyncResult *simple;
836 simple = g_simple_async_result_new (
837 G_OBJECT (service), callback, user_data, service_disconnect);
839 g_simple_async_result_set_check_cancellable (simple, cancellable);
841 g_simple_async_result_set_op_res_gboolean (simple, clean);
843 g_simple_async_result_run_in_thread (
844 simple, service_disconnect_thread, io_priority, cancellable);
846 g_object_unref (simple);
850 service_disconnect_finish (CamelService *service,
851 GAsyncResult *result,
854 GSimpleAsyncResult *simple;
856 g_return_val_if_fail (
857 g_simple_async_result_is_valid (
858 result, G_OBJECT (service), service_disconnect), FALSE);
860 simple = G_SIMPLE_ASYNC_RESULT (result);
862 /* Assume success unless a GError is set. */
863 return !g_simple_async_result_propagate_error (simple, error);
867 service_authenticate_thread (GSimpleAsyncResult *simple,
869 GCancellable *cancellable)
871 AsyncContext *async_context;
872 GError *error = NULL;
874 async_context = g_simple_async_result_get_op_res_gpointer (simple);
876 async_context->auth_result = camel_service_authenticate_sync (
877 CAMEL_SERVICE (object), async_context->auth_mechanism,
878 cancellable, &error);
881 g_simple_async_result_take_error (simple, error);
885 service_authenticate (CamelService *service,
886 const gchar *mechanism,
888 GCancellable *cancellable,
889 GAsyncReadyCallback callback,
892 GSimpleAsyncResult *simple;
893 AsyncContext *async_context;
895 async_context = g_slice_new0 (AsyncContext);
896 async_context->auth_mechanism = g_strdup (mechanism);
898 simple = g_simple_async_result_new (
899 G_OBJECT (service), callback, user_data, service_authenticate);
901 g_simple_async_result_set_check_cancellable (simple, cancellable);
903 g_simple_async_result_set_op_res_gpointer (
904 simple, async_context, (GDestroyNotify) async_context_free);
906 g_simple_async_result_run_in_thread (
907 simple, service_authenticate_thread, io_priority, cancellable);
909 g_object_unref (simple);
912 static CamelAuthenticationResult
913 service_authenticate_finish (CamelService *service,
914 GAsyncResult *result,
917 GSimpleAsyncResult *simple;
918 AsyncContext *async_context;
920 g_return_val_if_fail (
921 g_simple_async_result_is_valid (
922 result, G_OBJECT (service), service_authenticate),
923 CAMEL_AUTHENTICATION_REJECTED);
925 simple = G_SIMPLE_ASYNC_RESULT (result);
926 async_context = g_simple_async_result_get_op_res_gpointer (simple);
928 if (g_simple_async_result_propagate_error (simple, error))
929 return CAMEL_AUTHENTICATION_ERROR;
931 return async_context->auth_result;
935 service_query_auth_types_thread (GSimpleAsyncResult *simple,
937 GCancellable *cancellable)
939 AsyncContext *async_context;
940 GError *error = NULL;
942 async_context = g_simple_async_result_get_op_res_gpointer (simple);
944 async_context->auth_types = camel_service_query_auth_types_sync (
945 CAMEL_SERVICE (object), cancellable, &error);
948 g_simple_async_result_take_error (simple, error);
952 service_query_auth_types (CamelService *service,
954 GCancellable *cancellable,
955 GAsyncReadyCallback callback,
958 GSimpleAsyncResult *simple;
959 AsyncContext *async_context;
961 async_context = g_slice_new0 (AsyncContext);
963 simple = g_simple_async_result_new (
964 G_OBJECT (service), callback,
965 user_data, service_query_auth_types);
967 g_simple_async_result_set_check_cancellable (simple, cancellable);
969 g_simple_async_result_set_op_res_gpointer (
970 simple, async_context, (GDestroyNotify) async_context_free);
972 g_simple_async_result_run_in_thread (
973 simple, service_query_auth_types_thread,
974 io_priority, cancellable);
976 g_object_unref (simple);
980 service_query_auth_types_finish (CamelService *service,
981 GAsyncResult *result,
984 GSimpleAsyncResult *simple;
985 AsyncContext *async_context;
987 g_return_val_if_fail (
988 g_simple_async_result_is_valid (
989 result, G_OBJECT (service),
990 service_query_auth_types), NULL);
992 simple = G_SIMPLE_ASYNC_RESULT (result);
993 async_context = g_simple_async_result_get_op_res_gpointer (simple);
995 if (g_simple_async_result_propagate_error (simple, error))
998 return g_list_copy (async_context->auth_types);
1002 service_initable_init (GInitable *initable,
1003 GCancellable *cancellable,
1006 /* Nothing to do here, but we may need add something in the future.
1007 * For now this is a placeholder so subclasses can safely chain up. */
1013 camel_service_class_init (CamelServiceClass *class)
1015 GObjectClass *object_class;
1017 g_type_class_add_private (class, sizeof (CamelServicePrivate));
1019 object_class = G_OBJECT_CLASS (class);
1020 object_class->set_property = service_set_property;
1021 object_class->get_property = service_get_property;
1022 object_class->dispose = service_dispose;
1023 object_class->finalize = service_finalize;
1024 object_class->constructed = service_constructed;
1026 class->settings_type = CAMEL_TYPE_SETTINGS;
1027 class->get_name = service_get_name;
1028 class->connect_sync = service_connect_sync;
1029 class->disconnect_sync = service_disconnect_sync;
1030 class->query_auth_types_sync = service_query_auth_types_sync;
1032 class->connect = service_connect;
1033 class->connect_finish = service_connect_finish;
1034 class->disconnect = service_disconnect;
1035 class->disconnect_finish = service_disconnect_finish;
1036 class->authenticate = service_authenticate;
1037 class->authenticate_finish = service_authenticate_finish;
1038 class->query_auth_types = service_query_auth_types;
1039 class->query_auth_types_finish = service_query_auth_types_finish;
1041 g_object_class_install_property (
1043 PROP_CONNECTION_STATUS,
1045 "connection-status",
1046 "Connection Status",
1047 "The connection status for the service",
1048 CAMEL_TYPE_SERVICE_CONNECTION_STATUS,
1049 CAMEL_SERVICE_DISCONNECTED,
1051 G_PARAM_STATIC_STRINGS));
1053 g_object_class_install_property (
1056 g_param_spec_string (
1059 "The display name for the service",
1063 G_PARAM_STATIC_STRINGS));
1065 g_object_class_install_property (
1068 g_param_spec_string (
1071 "The password for the service",
1075 G_PARAM_STATIC_STRINGS));
1077 g_object_class_install_property (
1080 g_param_spec_pointer (
1083 "The CamelProvider for the service",
1085 G_PARAM_CONSTRUCT_ONLY |
1086 G_PARAM_STATIC_STRINGS));
1088 g_object_class_install_property (
1091 g_param_spec_object (
1094 "A CamelSession instance",
1097 G_PARAM_CONSTRUCT_ONLY |
1098 G_PARAM_STATIC_STRINGS));
1100 g_object_class_install_property (
1103 g_param_spec_object (
1106 "A CamelSettings instance",
1107 CAMEL_TYPE_SETTINGS,
1110 G_PARAM_STATIC_STRINGS));
1112 g_object_class_install_property (
1115 g_param_spec_string (
1118 "The unique identity of the service",
1121 G_PARAM_CONSTRUCT_ONLY |
1122 G_PARAM_STATIC_STRINGS));
1126 camel_service_initable_init (GInitableIface *interface)
1128 interface->init = service_initable_init;
1132 camel_service_init (CamelService *service)
1134 service->priv = CAMEL_SERVICE_GET_PRIVATE (service);
1136 service->priv->connection_lock = g_mutex_new ();
1137 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
1141 camel_service_error_quark (void)
1143 static GQuark quark = 0;
1145 if (G_UNLIKELY (quark == 0)) {
1146 const gchar *string = "camel-service-error-quark";
1147 quark = g_quark_from_static_string (string);
1154 * camel_service_migrate_files:
1155 * @service: a #CamelService
1157 * Performs any necessary file migrations for @service. This should be
1158 * called after installing or configuring the @service's #CamelSettings,
1159 * since it requires building a URL string for @service.
1164 camel_service_migrate_files (CamelService *service)
1166 const gchar *new_data_dir;
1167 gchar *old_data_dir;
1169 g_return_if_fail (CAMEL_IS_SERVICE (service));
1171 new_data_dir = camel_service_get_user_data_dir (service);
1172 old_data_dir = service_find_old_data_dir (service);
1174 /* If the old data directory name exists, try renaming
1175 * it to the new data directory. Failure is non-fatal. */
1176 if (old_data_dir != NULL) {
1177 g_rename (old_data_dir, new_data_dir);
1178 g_free (old_data_dir);
1183 * camel_service_new_camel_url:
1184 * @service: a #CamelService
1186 * Returns a new #CamelURL representing @service.
1187 * Free the returned #CamelURL with camel_url_free().
1189 * Returns: a new #CamelURL
1194 camel_service_new_camel_url (CamelService *service)
1197 CamelProvider *provider;
1198 CamelSettings *settings;
1204 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1206 provider = camel_service_get_provider (service);
1207 settings = camel_service_get_settings (service);
1209 g_return_val_if_fail (provider != NULL, NULL);
1211 /* Allocate as camel_url_new_with_base() does. */
1212 url = g_new0 (CamelURL, 1);
1214 if (CAMEL_IS_NETWORK_SETTINGS (settings)) {
1215 CamelNetworkSettings *network_settings;
1217 network_settings = CAMEL_NETWORK_SETTINGS (settings);
1218 host = camel_network_settings_dup_host (network_settings);
1219 port = camel_network_settings_get_port (network_settings);
1220 user = camel_network_settings_dup_user (network_settings);
1223 if (CAMEL_IS_LOCAL_SETTINGS (settings)) {
1224 CamelLocalSettings *local_settings;
1226 local_settings = CAMEL_LOCAL_SETTINGS (settings);
1227 path = camel_local_settings_dup_path (local_settings);
1230 camel_url_set_protocol (url, provider->protocol);
1231 camel_url_set_host (url, host);
1232 camel_url_set_port (url, port);
1233 camel_url_set_user (url, user);
1234 camel_url_set_path (url, path);
1244 * camel_service_get_connection_status:
1245 * @service: a #CamelService
1247 * Returns the connection status for @service.
1249 * Returns: the connection status
1253 CamelServiceConnectionStatus
1254 camel_service_get_connection_status (CamelService *service)
1256 g_return_val_if_fail (
1257 CAMEL_IS_SERVICE (service),
1258 CAMEL_SERVICE_DISCONNECTED);
1260 return service->priv->status;
1264 * camel_service_get_display_name:
1265 * @service: a #CamelService
1267 * Returns the display name for @service, or %NULL if @service has not
1268 * been given a display name. The display name is intended for use in
1269 * a user interface and should generally be given a user-defined name.
1271 * Compare this with camel_service_get_name(), which returns a built-in
1272 * description of the type of service (IMAP, SMTP, etc.).
1274 * Returns: the display name for @service, or %NULL
1279 camel_service_get_display_name (CamelService *service)
1281 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1283 return service->priv->display_name;
1287 * camel_service_set_display_name:
1288 * @service: a #CamelService
1289 * @display_name: a valid UTF-8 string, or %NULL
1291 * Assigns a UTF-8 display name to @service. The display name is intended
1292 * for use in a user interface and should generally be given a user-defined
1295 * Compare this with camel_service_get_name(), which returns a built-in
1296 * description of the type of service (IMAP, SMTP, etc.).
1301 camel_service_set_display_name (CamelService *service,
1302 const gchar *display_name)
1304 g_return_if_fail (CAMEL_IS_SERVICE (service));
1306 if (g_strcmp0 (service->priv->display_name, display_name) == 0)
1309 if (display_name != NULL)
1310 g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
1312 g_free (service->priv->display_name);
1313 service->priv->display_name = g_strdup (display_name);
1315 g_object_notify (G_OBJECT (service), "display-name");
1319 * camel_service_get_password:
1320 * @service: a #CamelService
1322 * Returns the password for @service. Some SASL mechanisms use this
1323 * when attempting to authenticate.
1325 * Returns: the password for @service
1330 camel_service_get_password (CamelService *service)
1332 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1334 return service->priv->password;
1338 * camel_service_set_password:
1339 * @service: a #CamelService
1340 * @password: the password for @service
1342 * Sets the password for @service. Use this function to cache the password
1343 * in memory after obtaining it through camel_session_get_password(). Some
1344 * SASL mechanisms use this when attempting to authenticate.
1349 camel_service_set_password (CamelService *service,
1350 const gchar *password)
1352 g_return_if_fail (CAMEL_IS_SERVICE (service));
1354 if (g_strcmp0 (service->priv->password, password) == 0)
1357 g_free (service->priv->password);
1358 service->priv->password = g_strdup (password);
1360 g_object_notify (G_OBJECT (service), "password");
1364 * camel_service_get_user_data_dir:
1365 * @service: a #CamelService
1367 * Returns the base directory under which to store user-specific data
1368 * for @service. The directory is formed by appending the directory
1369 * returned by camel_session_get_user_data_dir() with the service's
1370 * #CamelService:uid value.
1372 * Returns: the base directory for @service
1377 camel_service_get_user_data_dir (CamelService *service)
1379 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1381 return service->priv->user_data_dir;
1385 * camel_service_get_user_cache_dir:
1386 * @service: a #CamelService
1388 * Returns the base directory under which to store cache data
1389 * for @service. The directory is formed by appending the directory
1390 * returned by camel_session_get_user_cache_dir() with the service's
1391 * #CamelService:uid value.
1393 * Returns: the base cache directory for @service
1398 camel_service_get_user_cache_dir (CamelService *service)
1400 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1402 return service->priv->user_cache_dir;
1406 * camel_service_get_name:
1407 * @service: a #CamelService
1408 * @brief: whether or not to use a briefer form
1410 * This gets the name of the service in a "friendly" (suitable for
1411 * humans) form. If @brief is %TRUE, this should be a brief description
1412 * such as for use in the folder tree. If @brief is %FALSE, it should
1413 * be a more complete and mostly unambiguous description.
1415 * Returns: a description of the service which the caller must free
1418 camel_service_get_name (CamelService *service,
1421 CamelServiceClass *class;
1423 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1425 class = CAMEL_SERVICE_GET_CLASS (service);
1426 g_return_val_if_fail (class->get_name != NULL, NULL);
1428 return class->get_name (service, brief);
1432 * camel_service_get_provider:
1433 * @service: a #CamelService
1435 * Gets the #CamelProvider associated with the service.
1437 * Returns: the #CamelProvider
1440 camel_service_get_provider (CamelService *service)
1442 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1444 return service->priv->provider;
1448 * camel_service_get_session:
1449 * @service: a #CamelService
1451 * Gets the #CamelSession associated with the service.
1453 * Returns: the #CamelSession
1456 camel_service_get_session (CamelService *service)
1458 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1460 return CAMEL_SESSION (service->priv->session);
1464 * camel_service_get_settings:
1465 * @service: a #CamelService
1467 * Returns the #CamelSettings instance associated with the service.
1469 * Returns: the #CamelSettings
1474 camel_service_get_settings (CamelService *service)
1476 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1478 /* Every service should have a settings object. */
1479 g_warn_if_fail (service->priv->settings != NULL);
1481 return service->priv->settings;
1485 * camel_service_set_settings:
1486 * @service: a #CamelService
1487 * @settings: an instance derviced from #CamelSettings, or %NULL
1489 * Associates a new #CamelSettings instance with the service.
1490 * The @settings instance must match the settings type defined in
1491 * #CamelServiceClass. If @settings is %NULL, a new #CamelSettings
1492 * instance of the appropriate type is created with all properties
1498 camel_service_set_settings (CamelService *service,
1499 CamelSettings *settings)
1501 CamelServiceClass *class;
1503 g_return_if_fail (CAMEL_IS_SERVICE (service));
1505 if (service->priv->settings == settings)
1508 class = CAMEL_SERVICE_GET_CLASS (service);
1510 if (settings != NULL) {
1513 G_OBJECT_TYPE (settings),
1514 class->settings_type));
1515 g_object_ref (settings);
1520 class->settings_type,
1521 CAMEL_TYPE_SETTINGS));
1522 settings = g_object_new (class->settings_type, NULL);
1525 if (service->priv->settings != NULL)
1526 g_object_unref (service->priv->settings);
1528 service->priv->settings = settings;
1530 g_object_notify (G_OBJECT (service), "settings");
1534 * camel_service_get_uid:
1535 * @service: a #CamelService
1537 * Gets the unique identifier string associated with the service.
1539 * Returns: the UID string
1544 camel_service_get_uid (CamelService *service)
1546 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1548 return service->priv->uid;
1552 * camel_service_connect_sync:
1553 * @service: a #CamelService
1554 * @cancellable: optional #GCancellable object, or %NULL
1555 * @error: return location for a #GError, or %NULL
1557 * Connects @service to a remote server using the information in its
1558 * #CamelService:settings instance.
1560 * If a connect operation is already in progress when this function is
1561 * called, its results will be reflected in this connect operation.
1563 * Returns: %TRUE if the connection is made or %FALSE otherwise
1568 camel_service_connect_sync (CamelService *service,
1569 GCancellable *cancellable,
1572 AsyncClosure *closure;
1573 GAsyncResult *result;
1576 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1578 closure = async_closure_new ();
1580 camel_service_connect (
1581 service, G_PRIORITY_DEFAULT, cancellable,
1582 async_closure_callback, closure);
1584 result = async_closure_wait (closure);
1586 success = camel_service_connect_finish (service, result, error);
1588 async_closure_free (closure);
1594 * camel_service_connect:
1595 * @service: a #CamelService
1596 * @io_priority: the I/O priority of the request
1597 * @cancellable: optional #GCancellable object, or %NULL
1598 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1599 * @user_data: data to pass to the callback function
1601 * Asynchronously connects @service to a remote server using the information
1602 * in its #CamelService:settings instance.
1604 * If a connect operation is already in progress when this function is
1605 * called, its results will be reflected in this connect operation.
1607 * If any disconnect operations are in progress when this function is
1608 * called, they will be cancelled.
1610 * When the operation is finished, @callback will be called. You can
1611 * then call camel_service_connect_finish() to get the result of the
1617 camel_service_connect (CamelService *service,
1619 GCancellable *cancellable,
1620 GAsyncReadyCallback callback,
1624 CamelServiceClass *class;
1625 GSimpleAsyncResult *simple;
1627 g_return_if_fail (CAMEL_IS_SERVICE (service));
1629 class = CAMEL_SERVICE_GET_CLASS (service);
1630 g_return_if_fail (class->connect != NULL);
1632 simple = g_simple_async_result_new (
1633 G_OBJECT (service), callback,
1634 user_data, camel_service_connect);
1636 g_simple_async_result_set_check_cancellable (simple, cancellable);
1638 g_mutex_lock (service->priv->connection_lock);
1640 switch (service->priv->status) {
1642 /* If a connect operation is already in progress,
1643 * queue this operation so it completes at the same
1644 * time the first connect operation completes. */
1645 case CAMEL_SERVICE_CONNECTING:
1646 connection_op_add_pending (
1647 service->priv->connection_op,
1648 simple, cancellable);
1651 /* If we're already connected, just report success. */
1652 case CAMEL_SERVICE_CONNECTED:
1653 g_simple_async_result_complete_in_idle (simple);
1656 /* If a disconnect operation is currently in progress,
1657 * cancel it and make room for the connect operation. */
1658 case CAMEL_SERVICE_DISCONNECTING:
1660 service->priv->connection_op != NULL);
1661 g_cancellable_cancel (
1662 service->priv->connection_op->cancellable);
1663 connection_op_unref (service->priv->connection_op);
1664 service->priv->connection_op = NULL;
1667 /* Start a new connect operation. Subsequent connect
1668 * operations are queued until this operation completes
1669 * and will share this operation's result. */
1670 case CAMEL_SERVICE_DISCONNECTED:
1672 service->priv->connection_op == NULL);
1674 op = connection_op_new (simple, cancellable);
1675 service->priv->connection_op = op;
1677 service->priv->status = CAMEL_SERVICE_CONNECTING;
1678 service_queue_notify_connection_status (service);
1684 service_shared_connect_cb,
1685 connection_op_ref (op));
1689 g_warn_if_reached ();
1692 g_mutex_unlock (service->priv->connection_lock);
1694 g_object_unref (simple);
1698 * camel_service_connect_finish:
1699 * @service: a #CamelService
1700 * @result: a #GAsyncResult
1701 * @error: return location for a #GError, or %NULL
1703 * Finishes the operation started with camel_service_connect().
1705 * Returns: %TRUE if the connection was made or %FALSE otherwise
1710 camel_service_connect_finish (CamelService *service,
1711 GAsyncResult *result,
1714 GSimpleAsyncResult *simple;
1716 g_return_val_if_fail (
1717 g_simple_async_result_is_valid (
1718 result, G_OBJECT (service), camel_service_connect), FALSE);
1720 simple = G_SIMPLE_ASYNC_RESULT (result);
1722 /* Assume success unless a GError is set. */
1723 return !g_simple_async_result_propagate_error (simple, error);
1727 * camel_service_disconnect_sync:
1728 * @service: a #CamelService
1729 * @clean: whether or not to try to disconnect cleanly
1730 * @cancellable: optional #GCancellable object, or %NULL
1731 * @error: return location for a #GError, or %NULL
1733 * Disconnect from the service. If @clean is %FALSE, it should not
1734 * try to do any synchronizing or other cleanup of the connection.
1736 * If a disconnect operation is already in progress when this function is
1737 * called, its results will be reflected in this disconnect operation.
1739 * If any connect operations are in progress when this function is called,
1740 * they will be cancelled.
1742 * Returns: %TRUE if the connection was severed or %FALSE otherwise
1745 camel_service_disconnect_sync (CamelService *service,
1747 GCancellable *cancellable,
1750 AsyncClosure *closure;
1751 GAsyncResult *result;
1754 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1756 closure = async_closure_new ();
1758 camel_service_disconnect (
1759 service, clean, G_PRIORITY_DEFAULT,
1760 cancellable, async_closure_callback, closure);
1762 result = async_closure_wait (closure);
1764 success = camel_service_disconnect_finish (service, result, error);
1766 async_closure_free (closure);
1772 * camel_service_disconnect:
1773 * @service: a #CamelService
1774 * @clean: whether or not to try to disconnect cleanly
1775 * @io_priority: the I/O priority of the request
1776 * @cancellable: optional #GCancellable object, or %NULL
1777 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1778 * @user_data: data to pass to the callback function
1780 * If a disconnect operation is already in progress when this function is
1781 * called, its results will be reflected in this disconnect operation.
1783 * If any connect operations are in progress when this function is called,
1784 * they will be cancelled.
1786 * When the operation is finished, @callback will be called. You can
1787 * then call camel_service_disconnect_finish() to get the result of the
1793 camel_service_disconnect (CamelService *service,
1796 GCancellable *cancellable,
1797 GAsyncReadyCallback callback,
1801 CamelServiceClass *class;
1802 GSimpleAsyncResult *simple;
1804 g_return_if_fail (CAMEL_IS_SERVICE (service));
1806 class = CAMEL_SERVICE_GET_CLASS (service);
1807 g_return_if_fail (class->disconnect != NULL);
1809 simple = g_simple_async_result_new (
1810 G_OBJECT (service), callback,
1811 user_data, camel_service_disconnect);
1813 g_simple_async_result_set_check_cancellable (simple, cancellable);
1815 g_mutex_lock (service->priv->connection_lock);
1817 switch (service->priv->status) {
1819 /* If a connect operation is currently in progress,
1820 * cancel it and make room for the disconnect operation. */
1821 case CAMEL_SERVICE_CONNECTING:
1823 service->priv->connection_op != NULL);
1824 g_cancellable_cancel (
1825 service->priv->connection_op->cancellable);
1826 connection_op_unref (service->priv->connection_op);
1827 service->priv->connection_op = NULL;
1830 /* Start a new disconnect operation. Subsequent disconnect
1831 * operations are queued until this operation completes and
1832 * will share this operation's result. */
1833 case CAMEL_SERVICE_CONNECTED:
1835 service->priv->connection_op == NULL);
1837 op = connection_op_new (simple, cancellable);
1838 service->priv->connection_op = op;
1840 service->priv->status = CAMEL_SERVICE_DISCONNECTING;
1841 service_queue_notify_connection_status (service);
1847 service_shared_disconnect_cb,
1848 connection_op_ref (op));
1851 /* If a disconnect operation is already in progress,
1852 * queue this operation so it completes at the same
1853 * time the first disconnect operation completes. */
1854 case CAMEL_SERVICE_DISCONNECTING:
1855 connection_op_add_pending (
1856 service->priv->connection_op,
1857 simple, cancellable);
1860 /* If we're already disconnected, just report success. */
1861 case CAMEL_SERVICE_DISCONNECTED:
1862 g_simple_async_result_complete_in_idle (simple);
1866 g_warn_if_reached ();
1869 g_mutex_unlock (service->priv->connection_lock);
1871 g_object_unref (simple);
1875 * camel_service_disconnect_finish:
1876 * @service: a #CamelService
1877 * @result: a #GAsyncResult
1878 * @error: return location for a #GError, or %NULL
1880 * Finishes the operation started with camel_service_disconnect().
1882 * Returns: %TRUE if the connection was severed or %FALSE otherwise
1887 camel_service_disconnect_finish (CamelService *service,
1888 GAsyncResult *result,
1891 GSimpleAsyncResult *simple;
1893 g_return_val_if_fail (
1894 g_simple_async_result_is_valid (
1895 result, G_OBJECT (service), camel_service_disconnect), FALSE);
1897 simple = G_SIMPLE_ASYNC_RESULT (result);
1899 /* Assume success unless a GError is set. */
1900 return !g_simple_async_result_propagate_error (simple, error);
1904 * camel_service_authenticate_sync:
1905 * @service: a #CamelService
1906 * @mechanism: a SASL mechanism name, or %NULL
1907 * @cancellable: optional #GCancellable object, or %NULL
1908 * @error: return location for a #GError, or %NULL
1910 * Attempts to authenticate @service using @mechanism and, if necessary,
1911 * @service's #CamelService:password property. The function makes only
1912 * ONE attempt at authentication and does not loop.
1914 * If the authentication attempt completed and the server accepted the
1915 * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
1917 * If the authentication attempt completed but the server rejected the
1918 * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
1920 * If the authentication attempt failed to complete due to a network
1921 * communication issue or some other mishap, the function sets @error
1922 * and returns #CAMEL_AUTHENTICATION_ERROR.
1924 * Generally this function should only be called from a #CamelSession
1925 * subclass in order to implement its own authentication loop.
1927 * Returns: the authentication result
1931 CamelAuthenticationResult
1932 camel_service_authenticate_sync (CamelService *service,
1933 const gchar *mechanism,
1934 GCancellable *cancellable,
1937 CamelServiceClass *class;
1938 CamelAuthenticationResult result;
1940 g_return_val_if_fail (
1941 CAMEL_IS_SERVICE (service),
1942 CAMEL_AUTHENTICATION_REJECTED);
1944 class = CAMEL_SERVICE_GET_CLASS (service);
1945 g_return_val_if_fail (
1946 class->authenticate_sync != NULL,
1947 CAMEL_AUTHENTICATION_REJECTED);
1949 result = class->authenticate_sync (
1950 service, mechanism, cancellable, error);
1951 CAMEL_CHECK_GERROR (
1952 service, authenticate_sync,
1953 result != CAMEL_AUTHENTICATION_ERROR, error);
1959 * camel_service_authenticate:
1960 * @service: a #CamelService
1961 * @mechanism: a SASL mechanism name, or %NULL
1962 * @io_priority: the I/O priority of the request
1963 * @cancellable: optional #GCancellable object, or %NULL
1964 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1965 * @user_data: data to pass to the callback function
1967 * Asynchronously attempts to authenticate @service using @mechanism and,
1968 * if necessary, @service's #CamelService:password property. The function
1969 * makes only ONE attempt at authentication and does not loop.
1971 * Generally this function should only be called from a #CamelSession
1972 * subclass in order to implement its own authentication loop.
1974 * When the operation is finished, @callback will be called. You can
1975 * then call camel_service_authenticate_finish() to get the result of
1981 camel_service_authenticate (CamelService *service,
1982 const gchar *mechanism,
1984 GCancellable *cancellable,
1985 GAsyncReadyCallback callback,
1988 CamelServiceClass *class;
1990 g_return_if_fail (CAMEL_IS_SERVICE (service));
1992 class = CAMEL_SERVICE_GET_CLASS (service);
1993 g_return_if_fail (class->authenticate != NULL);
1995 class->authenticate (
1996 service, mechanism, io_priority,
1997 cancellable, callback, user_data);
2001 * camel_service_authenticate_finish:
2002 * @service: a #CamelService
2003 * @result: a #GAsyncResult
2004 * @error: return location for a #GError, or %NULL
2006 * Finishes the operation started with camel_service_authenticate().
2008 * If the authentication attempt completed and the server accepted the
2009 * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
2011 * If the authentication attempt completed but the server rejected the
2012 * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
2014 * If the authentication attempt failed to complete due to a network
2015 * communication issue or some other mishap, the function sets @error
2016 * and returns #CAMEL_AUTHENTICATION_ERROR.
2018 * Returns: the authentication result
2022 CamelAuthenticationResult
2023 camel_service_authenticate_finish (CamelService *service,
2024 GAsyncResult *result,
2027 CamelServiceClass *class;
2029 g_return_val_if_fail (
2030 CAMEL_IS_SERVICE (service),
2031 CAMEL_AUTHENTICATION_REJECTED);
2032 g_return_val_if_fail (
2033 G_IS_ASYNC_RESULT (result),
2034 CAMEL_AUTHENTICATION_REJECTED);
2036 class = CAMEL_SERVICE_GET_CLASS (service);
2037 g_return_val_if_fail (
2038 class->authenticate_finish,
2039 CAMEL_AUTHENTICATION_REJECTED);
2041 return class->authenticate_finish (service, result, error);
2045 * camel_service_query_auth_types_sync:
2046 * @service: a #CamelService
2047 * @cancellable: optional #GCancellable object, or %NULL
2048 * @error: return location for a #GError, or %NULL
2050 * Obtains a list of authentication types supported by @service.
2051 * Free the returned list with g_list_free().
2053 * Returns: a list of #CamelServiceAuthType structs
2056 camel_service_query_auth_types_sync (CamelService *service,
2057 GCancellable *cancellable,
2060 CamelServiceClass *class;
2062 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
2064 class = CAMEL_SERVICE_GET_CLASS (service);
2065 g_return_val_if_fail (class->query_auth_types_sync != NULL, NULL);
2067 return class->query_auth_types_sync (service, cancellable, error);
2071 * camel_service_query_auth_types:
2072 * @service: a #CamelService
2073 * @io_priority: the I/O priority of the request
2074 * @cancellable: optional #GCancellable object, or %NULL
2075 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2076 * @user_data: data to pass to the callback function
2078 * Asynchronously obtains a list of authentication types supported by
2081 * When the operation is finished, @callback will be called. You can
2082 * then call camel_service_query_auth_types_finish() to get the result
2088 camel_service_query_auth_types (CamelService *service,
2090 GCancellable *cancellable,
2091 GAsyncReadyCallback callback,
2094 CamelServiceClass *class;
2096 g_return_if_fail (CAMEL_IS_SERVICE (service));
2098 class = CAMEL_SERVICE_GET_CLASS (service);
2099 g_return_if_fail (class->query_auth_types != NULL);
2101 class->query_auth_types (
2102 service, io_priority,
2103 cancellable, callback, user_data);
2107 * camel_service_query_auth_types_finish:
2108 * @service: a #CamelService
2109 * @result: a #GAsyncResult
2110 * @error: return location for a #GError, or %NULL
2112 * Finishes the operation started with camel_service_query_auth_types().
2113 * Free the returned list with g_list_free().
2115 * Returns: a list of #CamelServiceAuthType structs
2120 camel_service_query_auth_types_finish (CamelService *service,
2121 GAsyncResult *result,
2124 CamelServiceClass *class;
2126 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
2127 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
2129 class = CAMEL_SERVICE_GET_CLASS (service);
2130 g_return_val_if_fail (class->query_auth_types_finish != NULL, NULL);
2132 return class->query_auth_types_finish (service, result, error);