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 {
60 CamelSettings *settings;
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 /* Prioritize ahead of GTK+ redraws. */
412 camel_session_idle_add (
413 session, G_PRIORITY_HIGH_IDLE,
414 service_notify_connection_status_cb,
415 g_object_ref (service),
416 (GDestroyNotify) g_object_unref);
420 service_shared_connect_cb (GObject *source_object,
421 GAsyncResult *result,
424 CamelService *service;
425 CamelServiceClass *class;
426 ConnectionOp *op = user_data;
428 GError *error = NULL;
430 /* This avoids a compiler warning
431 * in the CAMEL_CHECK_GERROR macro. */
432 GError **p_error = &error;
434 service = CAMEL_SERVICE (source_object);
435 class = CAMEL_SERVICE_GET_CLASS (service);
436 g_return_if_fail (class->connect_finish != NULL);
438 success = class->connect_finish (service, result, &error);
439 CAMEL_CHECK_GERROR (service, connect_sync, success, p_error);
441 g_mutex_lock (&service->priv->connection_lock);
443 if (service->priv->connection_op == op) {
444 connection_op_unref (service->priv->connection_op);
445 service->priv->connection_op = NULL;
447 service->priv->status = CAMEL_SERVICE_CONNECTED;
449 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
450 service_queue_notify_connection_status (service);
453 connection_op_complete (op, error);
454 connection_op_complete_pending (op, error);
456 g_mutex_unlock (&service->priv->connection_lock);
458 connection_op_unref (op);
459 g_clear_error (&error);
463 service_shared_disconnect_cb (GObject *source_object,
464 GAsyncResult *result,
467 CamelService *service;
468 CamelServiceClass *class;
469 ConnectionOp *op = user_data;
471 GError *error = NULL;
473 /* This avoids a compiler warning
474 * in the CAMEL_CHECK_GERROR macro. */
475 GError **p_error = &error;
477 service = CAMEL_SERVICE (source_object);
478 class = CAMEL_SERVICE_GET_CLASS (service);
479 g_return_if_fail (class->disconnect_finish != NULL);
481 success = class->disconnect_finish (service, result, &error);
482 CAMEL_CHECK_GERROR (service, disconnect_sync, success, p_error);
484 g_mutex_lock (&service->priv->connection_lock);
486 if (service->priv->connection_op == op) {
487 connection_op_unref (service->priv->connection_op);
488 service->priv->connection_op = NULL;
490 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
492 service->priv->status = CAMEL_SERVICE_CONNECTED;
493 service_queue_notify_connection_status (service);
496 connection_op_complete (op, error);
497 connection_op_complete_pending (op, error);
499 g_mutex_unlock (&service->priv->connection_lock);
501 connection_op_unref (op);
502 g_clear_error (&error);
506 service_set_provider (CamelService *service,
507 CamelProvider *provider)
509 g_return_if_fail (provider != NULL);
510 g_return_if_fail (service->priv->provider == NULL);
512 service->priv->provider = provider;
516 service_set_session (CamelService *service,
517 CamelSession *session)
519 g_return_if_fail (CAMEL_IS_SESSION (session));
521 g_weak_ref_set (&service->priv->session, session);
525 service_set_uid (CamelService *service,
528 g_return_if_fail (uid != NULL);
529 g_return_if_fail (service->priv->uid == NULL);
531 service->priv->uid = g_strdup (uid);
535 service_set_property (GObject *object,
540 switch (property_id) {
541 case PROP_DISPLAY_NAME:
542 camel_service_set_display_name (
543 CAMEL_SERVICE (object),
544 g_value_get_string (value));
548 camel_service_set_password (
549 CAMEL_SERVICE (object),
550 g_value_get_string (value));
554 service_set_provider (
555 CAMEL_SERVICE (object),
556 g_value_get_pointer (value));
560 service_set_session (
561 CAMEL_SERVICE (object),
562 g_value_get_object (value));
566 camel_service_set_settings (
567 CAMEL_SERVICE (object),
568 g_value_get_object (value));
573 CAMEL_SERVICE (object),
574 g_value_get_string (value));
578 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
582 service_get_property (GObject *object,
587 switch (property_id) {
588 case PROP_CONNECTION_STATUS:
590 value, camel_service_get_connection_status (
591 CAMEL_SERVICE (object)));
594 case PROP_DISPLAY_NAME:
596 value, camel_service_get_display_name (
597 CAMEL_SERVICE (object)));
602 value, camel_service_get_password (
603 CAMEL_SERVICE (object)));
607 g_value_set_pointer (
608 value, camel_service_get_provider (
609 CAMEL_SERVICE (object)));
614 value, camel_service_get_session (
615 CAMEL_SERVICE (object)));
619 g_value_take_object (
620 value, camel_service_ref_settings (
621 CAMEL_SERVICE (object)));
626 value, camel_service_get_uid (
627 CAMEL_SERVICE (object)));
631 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
635 service_dispose (GObject *object)
637 CamelServicePrivate *priv;
639 priv = CAMEL_SERVICE_GET_PRIVATE (object);
641 g_weak_ref_set (&priv->session, NULL);
643 if (priv->settings != NULL) {
644 g_object_unref (priv->settings);
645 priv->settings = NULL;
648 /* Chain up to parent's dispose() method. */
649 G_OBJECT_CLASS (camel_service_parent_class)->dispose (object);
653 service_finalize (GObject *object)
655 CamelServicePrivate *priv;
657 priv = CAMEL_SERVICE_GET_PRIVATE (object);
659 if (priv->status == CAMEL_SERVICE_CONNECTED)
660 CAMEL_SERVICE_GET_CLASS (object)->disconnect_sync (
661 CAMEL_SERVICE (object), TRUE, NULL, NULL);
663 g_mutex_clear (&priv->settings_lock);
665 g_free (priv->display_name);
666 g_free (priv->user_data_dir);
667 g_free (priv->user_cache_dir);
669 g_free (priv->password);
671 /* There should be no outstanding connection operations. */
672 g_warn_if_fail (priv->connection_op == NULL);
673 g_mutex_clear (&priv->connection_lock);
675 /* Chain up to parent's finalize() method. */
676 G_OBJECT_CLASS (camel_service_parent_class)->finalize (object);
680 service_constructed (GObject *object)
682 CamelService *service;
683 CamelSession *session;
684 const gchar *base_dir;
687 /* Chain up to parent's constructed() method. */
688 G_OBJECT_CLASS (camel_service_parent_class)->constructed (object);
690 service = CAMEL_SERVICE (object);
691 session = camel_service_get_session (service);
693 uid = camel_service_get_uid (service);
695 base_dir = camel_session_get_user_data_dir (session);
696 service->priv->user_data_dir = g_build_filename (base_dir, uid, NULL);
698 base_dir = camel_session_get_user_cache_dir (session);
699 service->priv->user_cache_dir = g_build_filename (base_dir, uid, NULL);
703 service_get_name (CamelService *service,
707 "%s does not implement CamelServiceClass::get_name()",
708 G_OBJECT_TYPE_NAME (service));
710 return g_strdup (G_OBJECT_TYPE_NAME (service));
714 service_connect_sync (CamelService *service,
715 GCancellable *cancellable,
718 /* Default behavior for local storage providers. */
723 service_disconnect_sync (CamelService *service,
725 GCancellable *cancellable,
728 /* Default behavior for local storage providers. */
733 service_query_auth_types_sync (CamelService *service,
734 GCancellable *cancellable,
741 service_connect_thread (GSimpleAsyncResult *simple,
743 GCancellable *cancellable)
745 CamelService *service;
746 CamelServiceClass *class;
747 GError *error = NULL;
749 /* Note we call the class method directly here. */
751 service = CAMEL_SERVICE (object);
753 class = CAMEL_SERVICE_GET_CLASS (service);
754 g_return_if_fail (class->connect_sync != NULL);
756 class->connect_sync (service, cancellable, &error);
759 g_simple_async_result_take_error (simple, error);
763 service_connect (CamelService *service,
765 GCancellable *cancellable,
766 GAsyncReadyCallback callback,
769 GSimpleAsyncResult *simple;
771 simple = g_simple_async_result_new (
772 G_OBJECT (service), callback, user_data, service_connect);
774 g_simple_async_result_set_check_cancellable (simple, cancellable);
776 g_simple_async_result_run_in_thread (
777 simple, service_connect_thread, io_priority, cancellable);
779 g_object_unref (simple);
783 service_connect_finish (CamelService *service,
784 GAsyncResult *result,
787 GSimpleAsyncResult *simple;
789 g_return_val_if_fail (
790 g_simple_async_result_is_valid (
791 result, G_OBJECT (service), service_connect), FALSE);
793 simple = G_SIMPLE_ASYNC_RESULT (result);
795 /* Assume success unless a GError is set. */
796 return !g_simple_async_result_propagate_error (simple, error);
800 service_disconnect_thread (GSimpleAsyncResult *simple,
802 GCancellable *cancellable)
804 CamelService *service;
805 CamelServiceClass *class;
807 GError *error = NULL;
809 /* Note we call the class method directly here. */
811 service = CAMEL_SERVICE (object);
812 clean = g_simple_async_result_get_op_res_gboolean (simple);
814 class = CAMEL_SERVICE_GET_CLASS (service);
815 g_return_if_fail (class->disconnect_sync != NULL);
817 class->disconnect_sync (service, clean, cancellable, &error);
820 g_simple_async_result_take_error (simple, error);
824 service_disconnect (CamelService *service,
827 GCancellable *cancellable,
828 GAsyncReadyCallback callback,
831 GSimpleAsyncResult *simple;
833 simple = g_simple_async_result_new (
834 G_OBJECT (service), callback, user_data, service_disconnect);
836 g_simple_async_result_set_check_cancellable (simple, cancellable);
838 g_simple_async_result_set_op_res_gboolean (simple, clean);
840 g_simple_async_result_run_in_thread (
841 simple, service_disconnect_thread, io_priority, cancellable);
843 g_object_unref (simple);
847 service_disconnect_finish (CamelService *service,
848 GAsyncResult *result,
851 GSimpleAsyncResult *simple;
853 g_return_val_if_fail (
854 g_simple_async_result_is_valid (
855 result, G_OBJECT (service), service_disconnect), FALSE);
857 simple = G_SIMPLE_ASYNC_RESULT (result);
859 /* Assume success unless a GError is set. */
860 return !g_simple_async_result_propagate_error (simple, error);
864 service_authenticate_thread (GSimpleAsyncResult *simple,
866 GCancellable *cancellable)
868 AsyncContext *async_context;
869 GError *error = NULL;
871 async_context = g_simple_async_result_get_op_res_gpointer (simple);
873 async_context->auth_result = camel_service_authenticate_sync (
874 CAMEL_SERVICE (object), async_context->auth_mechanism,
875 cancellable, &error);
878 g_simple_async_result_take_error (simple, error);
882 service_authenticate (CamelService *service,
883 const gchar *mechanism,
885 GCancellable *cancellable,
886 GAsyncReadyCallback callback,
889 GSimpleAsyncResult *simple;
890 AsyncContext *async_context;
892 async_context = g_slice_new0 (AsyncContext);
893 async_context->auth_mechanism = g_strdup (mechanism);
895 simple = g_simple_async_result_new (
896 G_OBJECT (service), callback, user_data, service_authenticate);
898 g_simple_async_result_set_check_cancellable (simple, cancellable);
900 g_simple_async_result_set_op_res_gpointer (
901 simple, async_context, (GDestroyNotify) async_context_free);
903 g_simple_async_result_run_in_thread (
904 simple, service_authenticate_thread, io_priority, cancellable);
906 g_object_unref (simple);
909 static CamelAuthenticationResult
910 service_authenticate_finish (CamelService *service,
911 GAsyncResult *result,
914 GSimpleAsyncResult *simple;
915 AsyncContext *async_context;
917 g_return_val_if_fail (
918 g_simple_async_result_is_valid (
919 result, G_OBJECT (service), service_authenticate),
920 CAMEL_AUTHENTICATION_REJECTED);
922 simple = G_SIMPLE_ASYNC_RESULT (result);
923 async_context = g_simple_async_result_get_op_res_gpointer (simple);
925 if (g_simple_async_result_propagate_error (simple, error))
926 return CAMEL_AUTHENTICATION_ERROR;
928 return async_context->auth_result;
932 service_query_auth_types_thread (GSimpleAsyncResult *simple,
934 GCancellable *cancellable)
936 AsyncContext *async_context;
937 GError *error = NULL;
939 async_context = g_simple_async_result_get_op_res_gpointer (simple);
941 async_context->auth_types = camel_service_query_auth_types_sync (
942 CAMEL_SERVICE (object), cancellable, &error);
945 g_simple_async_result_take_error (simple, error);
949 service_query_auth_types (CamelService *service,
951 GCancellable *cancellable,
952 GAsyncReadyCallback callback,
955 GSimpleAsyncResult *simple;
956 AsyncContext *async_context;
958 async_context = g_slice_new0 (AsyncContext);
960 simple = g_simple_async_result_new (
961 G_OBJECT (service), callback,
962 user_data, service_query_auth_types);
964 g_simple_async_result_set_check_cancellable (simple, cancellable);
966 g_simple_async_result_set_op_res_gpointer (
967 simple, async_context, (GDestroyNotify) async_context_free);
969 g_simple_async_result_run_in_thread (
970 simple, service_query_auth_types_thread,
971 io_priority, cancellable);
973 g_object_unref (simple);
977 service_query_auth_types_finish (CamelService *service,
978 GAsyncResult *result,
981 GSimpleAsyncResult *simple;
982 AsyncContext *async_context;
984 g_return_val_if_fail (
985 g_simple_async_result_is_valid (
986 result, G_OBJECT (service),
987 service_query_auth_types), NULL);
989 simple = G_SIMPLE_ASYNC_RESULT (result);
990 async_context = g_simple_async_result_get_op_res_gpointer (simple);
992 if (g_simple_async_result_propagate_error (simple, error))
995 return g_list_copy (async_context->auth_types);
999 service_initable_init (GInitable *initable,
1000 GCancellable *cancellable,
1003 /* Nothing to do here, but we may need add something in the future.
1004 * For now this is a placeholder so subclasses can safely chain up. */
1010 camel_service_class_init (CamelServiceClass *class)
1012 GObjectClass *object_class;
1014 g_type_class_add_private (class, sizeof (CamelServicePrivate));
1016 object_class = G_OBJECT_CLASS (class);
1017 object_class->set_property = service_set_property;
1018 object_class->get_property = service_get_property;
1019 object_class->dispose = service_dispose;
1020 object_class->finalize = service_finalize;
1021 object_class->constructed = service_constructed;
1023 class->settings_type = CAMEL_TYPE_SETTINGS;
1024 class->get_name = service_get_name;
1025 class->connect_sync = service_connect_sync;
1026 class->disconnect_sync = service_disconnect_sync;
1027 class->query_auth_types_sync = service_query_auth_types_sync;
1029 class->connect = service_connect;
1030 class->connect_finish = service_connect_finish;
1031 class->disconnect = service_disconnect;
1032 class->disconnect_finish = service_disconnect_finish;
1033 class->authenticate = service_authenticate;
1034 class->authenticate_finish = service_authenticate_finish;
1035 class->query_auth_types = service_query_auth_types;
1036 class->query_auth_types_finish = service_query_auth_types_finish;
1038 g_object_class_install_property (
1040 PROP_CONNECTION_STATUS,
1042 "connection-status",
1043 "Connection Status",
1044 "The connection status for the service",
1045 CAMEL_TYPE_SERVICE_CONNECTION_STATUS,
1046 CAMEL_SERVICE_DISCONNECTED,
1048 G_PARAM_STATIC_STRINGS));
1050 g_object_class_install_property (
1053 g_param_spec_string (
1056 "The display name for the service",
1060 G_PARAM_STATIC_STRINGS));
1062 g_object_class_install_property (
1065 g_param_spec_string (
1068 "The password for the service",
1072 G_PARAM_STATIC_STRINGS));
1074 g_object_class_install_property (
1077 g_param_spec_pointer (
1080 "The CamelProvider for the service",
1082 G_PARAM_CONSTRUCT_ONLY |
1083 G_PARAM_STATIC_STRINGS));
1085 g_object_class_install_property (
1088 g_param_spec_object (
1091 "A CamelSession instance",
1094 G_PARAM_CONSTRUCT_ONLY |
1095 G_PARAM_STATIC_STRINGS));
1097 g_object_class_install_property (
1100 g_param_spec_object (
1103 "A CamelSettings instance",
1104 CAMEL_TYPE_SETTINGS,
1107 G_PARAM_STATIC_STRINGS));
1109 g_object_class_install_property (
1112 g_param_spec_string (
1115 "The unique identity of the service",
1118 G_PARAM_CONSTRUCT_ONLY |
1119 G_PARAM_STATIC_STRINGS));
1123 camel_service_initable_init (GInitableIface *interface)
1125 interface->init = service_initable_init;
1129 camel_service_init (CamelService *service)
1131 service->priv = CAMEL_SERVICE_GET_PRIVATE (service);
1133 g_mutex_init (&service->priv->settings_lock);
1134 g_mutex_init (&service->priv->connection_lock);
1135 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
1138 G_DEFINE_QUARK (camel-service-error-quark, camel_service_error)
1141 * camel_service_migrate_files:
1142 * @service: a #CamelService
1144 * Performs any necessary file migrations for @service. This should be
1145 * called after installing or configuring the @service's #CamelSettings,
1146 * since it requires building a URL string for @service.
1151 camel_service_migrate_files (CamelService *service)
1153 const gchar *new_data_dir;
1154 gchar *old_data_dir;
1156 g_return_if_fail (CAMEL_IS_SERVICE (service));
1158 new_data_dir = camel_service_get_user_data_dir (service);
1159 old_data_dir = service_find_old_data_dir (service);
1161 /* If the old data directory name exists, try renaming
1162 * it to the new data directory. Failure is non-fatal. */
1163 if (old_data_dir != NULL) {
1164 g_rename (old_data_dir, new_data_dir);
1165 g_free (old_data_dir);
1170 * camel_service_new_camel_url:
1171 * @service: a #CamelService
1173 * Returns a new #CamelURL representing @service.
1174 * Free the returned #CamelURL with camel_url_free().
1176 * Returns: a new #CamelURL
1181 camel_service_new_camel_url (CamelService *service)
1184 CamelProvider *provider;
1185 CamelSettings *settings;
1191 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1193 provider = camel_service_get_provider (service);
1194 g_return_val_if_fail (provider != NULL, NULL);
1196 settings = camel_service_ref_settings (service);
1198 /* Allocate as camel_url_new_with_base() does. */
1199 url = g_new0 (CamelURL, 1);
1201 if (CAMEL_IS_NETWORK_SETTINGS (settings)) {
1202 CamelNetworkSettings *network_settings;
1204 network_settings = CAMEL_NETWORK_SETTINGS (settings);
1205 host = camel_network_settings_dup_host (network_settings);
1206 port = camel_network_settings_get_port (network_settings);
1207 user = camel_network_settings_dup_user (network_settings);
1210 if (CAMEL_IS_LOCAL_SETTINGS (settings)) {
1211 CamelLocalSettings *local_settings;
1213 local_settings = CAMEL_LOCAL_SETTINGS (settings);
1214 path = camel_local_settings_dup_path (local_settings);
1217 camel_url_set_protocol (url, provider->protocol);
1218 camel_url_set_host (url, host);
1219 camel_url_set_port (url, port);
1220 camel_url_set_user (url, user);
1221 camel_url_set_path (url, path);
1227 g_object_unref (settings);
1233 * camel_service_get_connection_status:
1234 * @service: a #CamelService
1236 * Returns the connection status for @service.
1238 * Returns: the connection status
1242 CamelServiceConnectionStatus
1243 camel_service_get_connection_status (CamelService *service)
1245 g_return_val_if_fail (
1246 CAMEL_IS_SERVICE (service),
1247 CAMEL_SERVICE_DISCONNECTED);
1249 return service->priv->status;
1253 * camel_service_get_display_name:
1254 * @service: a #CamelService
1256 * Returns the display name for @service, or %NULL if @service has not
1257 * been given a display name. The display name is intended for use in
1258 * a user interface and should generally be given a user-defined name.
1260 * Compare this with camel_service_get_name(), which returns a built-in
1261 * description of the type of service (IMAP, SMTP, etc.).
1263 * Returns: the display name for @service, or %NULL
1268 camel_service_get_display_name (CamelService *service)
1270 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1272 return service->priv->display_name;
1276 * camel_service_set_display_name:
1277 * @service: a #CamelService
1278 * @display_name: a valid UTF-8 string, or %NULL
1280 * Assigns a UTF-8 display name to @service. The display name is intended
1281 * for use in a user interface and should generally be given a user-defined
1284 * Compare this with camel_service_get_name(), which returns a built-in
1285 * description of the type of service (IMAP, SMTP, etc.).
1290 camel_service_set_display_name (CamelService *service,
1291 const gchar *display_name)
1293 g_return_if_fail (CAMEL_IS_SERVICE (service));
1295 if (g_strcmp0 (service->priv->display_name, display_name) == 0)
1298 if (display_name != NULL)
1299 g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
1301 g_free (service->priv->display_name);
1302 service->priv->display_name = g_strdup (display_name);
1304 g_object_notify (G_OBJECT (service), "display-name");
1308 * camel_service_get_password:
1309 * @service: a #CamelService
1311 * Returns the password for @service. Some SASL mechanisms use this
1312 * when attempting to authenticate.
1314 * Returns: the password for @service
1319 camel_service_get_password (CamelService *service)
1321 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1323 return service->priv->password;
1327 * camel_service_set_password:
1328 * @service: a #CamelService
1329 * @password: the password for @service
1331 * Sets the password for @service. Use this function to cache the password
1332 * in memory after obtaining it through camel_session_get_password(). Some
1333 * SASL mechanisms use this when attempting to authenticate.
1338 camel_service_set_password (CamelService *service,
1339 const gchar *password)
1341 g_return_if_fail (CAMEL_IS_SERVICE (service));
1343 if (g_strcmp0 (service->priv->password, password) == 0)
1346 g_free (service->priv->password);
1347 service->priv->password = g_strdup (password);
1349 g_object_notify (G_OBJECT (service), "password");
1353 * camel_service_get_user_data_dir:
1354 * @service: a #CamelService
1356 * Returns the base directory under which to store user-specific data
1357 * for @service. The directory is formed by appending the directory
1358 * returned by camel_session_get_user_data_dir() with the service's
1359 * #CamelService:uid value.
1361 * Returns: the base directory for @service
1366 camel_service_get_user_data_dir (CamelService *service)
1368 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1370 return service->priv->user_data_dir;
1374 * camel_service_get_user_cache_dir:
1375 * @service: a #CamelService
1377 * Returns the base directory under which to store cache data
1378 * for @service. The directory is formed by appending the directory
1379 * returned by camel_session_get_user_cache_dir() with the service's
1380 * #CamelService:uid value.
1382 * Returns: the base cache directory for @service
1387 camel_service_get_user_cache_dir (CamelService *service)
1389 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1391 return service->priv->user_cache_dir;
1395 * camel_service_get_name:
1396 * @service: a #CamelService
1397 * @brief: whether or not to use a briefer form
1399 * This gets the name of the service in a "friendly" (suitable for
1400 * humans) form. If @brief is %TRUE, this should be a brief description
1401 * such as for use in the folder tree. If @brief is %FALSE, it should
1402 * be a more complete and mostly unambiguous description.
1404 * Returns: a description of the service which the caller must free
1407 camel_service_get_name (CamelService *service,
1410 CamelServiceClass *class;
1412 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1414 class = CAMEL_SERVICE_GET_CLASS (service);
1415 g_return_val_if_fail (class->get_name != NULL, NULL);
1417 return class->get_name (service, brief);
1421 * camel_service_get_provider:
1422 * @service: a #CamelService
1424 * Gets the #CamelProvider associated with the service.
1426 * Returns: the #CamelProvider
1429 camel_service_get_provider (CamelService *service)
1431 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1433 return service->priv->provider;
1437 * camel_service_ref_session:
1438 * @service: a #CamelService
1440 * Returns the #CamelSession associated with the service.
1442 * The returned #CamelSession is referenced for thread-safety. Unreference
1443 * the #CamelSession with g_object_unref() when finished with it.
1445 * Returns: the #CamelSession
1450 camel_service_ref_session (CamelService *service)
1452 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1454 return g_weak_ref_get (&service->priv->session);
1458 * camel_service_get_session:
1459 * @service: a #CamelService
1461 * Returns the #CamelSession associated with the service.
1463 * Note this function is not thread-safe. The returned #CamelSession could
1464 * be finalized by another thread while the caller is still using it.
1466 * Returns: the #CamelSession
1468 * Deprecated: 3.8: Use camel_service_ref_session() instead.
1471 camel_service_get_session (CamelService *service)
1473 CamelSession *session;
1475 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1477 session = camel_service_ref_session (service);
1479 /* XXX Drop the CamelSession reference for backward-compatibility.
1480 * This is risky. Without a reference, the CamelSession could
1481 * be finalized while the caller is still using it. */
1482 if (session != NULL)
1483 g_object_unref (session);
1489 * camel_service_ref_settings:
1490 * @service: a #CamelService
1492 * Returns the #CamelSettings instance associated with the service.
1494 * The returned #CamelSettings is referenced for thread-safety and must
1495 * be unreferenced with g_object_unref() when finished with it.
1497 * Returns: the #CamelSettings
1502 camel_service_ref_settings (CamelService *service)
1504 CamelSettings *settings;
1506 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1508 /* Every service should have a settings object. */
1509 g_return_val_if_fail (service->priv->settings != NULL, NULL);
1511 g_mutex_lock (&service->priv->settings_lock);
1513 settings = g_object_ref (service->priv->settings);
1515 g_mutex_unlock (&service->priv->settings_lock);
1521 * camel_service_set_settings:
1522 * @service: a #CamelService
1523 * @settings: an instance derviced from #CamelSettings, or %NULL
1525 * Associates a new #CamelSettings instance with the service.
1526 * The @settings instance must match the settings type defined in
1527 * #CamelServiceClass. If @settings is %NULL, a new #CamelSettings
1528 * instance of the appropriate type is created with all properties
1534 camel_service_set_settings (CamelService *service,
1535 CamelSettings *settings)
1537 CamelServiceClass *class;
1539 g_return_if_fail (CAMEL_IS_SERVICE (service));
1541 class = CAMEL_SERVICE_GET_CLASS (service);
1543 if (settings != NULL) {
1546 G_OBJECT_TYPE (settings),
1547 class->settings_type));
1548 g_object_ref (settings);
1553 class->settings_type,
1554 CAMEL_TYPE_SETTINGS));
1555 settings = g_object_new (class->settings_type, NULL);
1558 g_mutex_lock (&service->priv->settings_lock);
1560 if (service->priv->settings != NULL)
1561 g_object_unref (service->priv->settings);
1563 service->priv->settings = settings; /* takes ownership */
1565 g_mutex_unlock (&service->priv->settings_lock);
1567 g_object_notify (G_OBJECT (service), "settings");
1571 * camel_service_get_uid:
1572 * @service: a #CamelService
1574 * Gets the unique identifier string associated with the service.
1576 * Returns: the UID string
1581 camel_service_get_uid (CamelService *service)
1583 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1585 return service->priv->uid;
1589 * camel_service_connect_sync:
1590 * @service: a #CamelService
1591 * @cancellable: optional #GCancellable object, or %NULL
1592 * @error: return location for a #GError, or %NULL
1594 * Connects @service to a remote server using the information in its
1595 * #CamelService:settings instance.
1597 * If a connect operation is already in progress when this function is
1598 * called, its results will be reflected in this connect operation.
1600 * Returns: %TRUE if the connection is made or %FALSE otherwise
1605 camel_service_connect_sync (CamelService *service,
1606 GCancellable *cancellable,
1609 AsyncClosure *closure;
1610 GAsyncResult *result;
1613 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1615 closure = async_closure_new ();
1617 camel_service_connect (
1618 service, G_PRIORITY_DEFAULT, cancellable,
1619 async_closure_callback, closure);
1621 result = async_closure_wait (closure);
1623 success = camel_service_connect_finish (service, result, error);
1625 async_closure_free (closure);
1631 * camel_service_connect:
1632 * @service: a #CamelService
1633 * @io_priority: the I/O priority of the request
1634 * @cancellable: optional #GCancellable object, or %NULL
1635 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1636 * @user_data: data to pass to the callback function
1638 * Asynchronously connects @service to a remote server using the information
1639 * in its #CamelService:settings instance.
1641 * If a connect operation is already in progress when this function is
1642 * called, its results will be reflected in this connect operation.
1644 * If any disconnect operations are in progress when this function is
1645 * called, they will be cancelled.
1647 * When the operation is finished, @callback will be called. You can
1648 * then call camel_service_connect_finish() to get the result of the
1654 camel_service_connect (CamelService *service,
1656 GCancellable *cancellable,
1657 GAsyncReadyCallback callback,
1661 CamelServiceClass *class;
1662 GSimpleAsyncResult *simple;
1664 g_return_if_fail (CAMEL_IS_SERVICE (service));
1666 class = CAMEL_SERVICE_GET_CLASS (service);
1667 g_return_if_fail (class->connect != NULL);
1669 simple = g_simple_async_result_new (
1670 G_OBJECT (service), callback,
1671 user_data, camel_service_connect);
1673 g_simple_async_result_set_check_cancellable (simple, cancellable);
1675 g_mutex_lock (&service->priv->connection_lock);
1677 switch (service->priv->status) {
1679 /* If a connect operation is already in progress,
1680 * queue this operation so it completes at the same
1681 * time the first connect operation completes. */
1682 case CAMEL_SERVICE_CONNECTING:
1683 connection_op_add_pending (
1684 service->priv->connection_op,
1685 simple, cancellable);
1688 /* If we're already connected, just report success. */
1689 case CAMEL_SERVICE_CONNECTED:
1690 g_simple_async_result_complete_in_idle (simple);
1693 /* If a disconnect operation is currently in progress,
1694 * cancel it and make room for the connect operation. */
1695 case CAMEL_SERVICE_DISCONNECTING:
1697 service->priv->connection_op != NULL);
1698 g_cancellable_cancel (
1699 service->priv->connection_op->cancellable);
1700 connection_op_unref (service->priv->connection_op);
1701 service->priv->connection_op = NULL;
1704 /* Start a new connect operation. Subsequent connect
1705 * operations are queued until this operation completes
1706 * and will share this operation's result. */
1707 case CAMEL_SERVICE_DISCONNECTED:
1709 service->priv->connection_op == NULL);
1711 op = connection_op_new (simple, cancellable);
1712 service->priv->connection_op = op;
1714 service->priv->status = CAMEL_SERVICE_CONNECTING;
1715 service_queue_notify_connection_status (service);
1721 service_shared_connect_cb,
1722 connection_op_ref (op));
1726 g_warn_if_reached ();
1729 g_mutex_unlock (&service->priv->connection_lock);
1731 g_object_unref (simple);
1735 * camel_service_connect_finish:
1736 * @service: a #CamelService
1737 * @result: a #GAsyncResult
1738 * @error: return location for a #GError, or %NULL
1740 * Finishes the operation started with camel_service_connect().
1742 * Returns: %TRUE if the connection was made or %FALSE otherwise
1747 camel_service_connect_finish (CamelService *service,
1748 GAsyncResult *result,
1751 GSimpleAsyncResult *simple;
1753 g_return_val_if_fail (
1754 g_simple_async_result_is_valid (
1755 result, G_OBJECT (service), camel_service_connect), FALSE);
1757 simple = G_SIMPLE_ASYNC_RESULT (result);
1759 /* Assume success unless a GError is set. */
1760 return !g_simple_async_result_propagate_error (simple, error);
1764 * camel_service_disconnect_sync:
1765 * @service: a #CamelService
1766 * @clean: whether or not to try to disconnect cleanly
1767 * @cancellable: optional #GCancellable object, or %NULL
1768 * @error: return location for a #GError, or %NULL
1770 * Disconnect from the service. If @clean is %FALSE, it should not
1771 * try to do any synchronizing or other cleanup of the connection.
1773 * If a disconnect operation is already in progress when this function is
1774 * called, its results will be reflected in this disconnect operation.
1776 * If any connect operations are in progress when this function is called,
1777 * they will be cancelled.
1779 * Returns: %TRUE if the connection was severed or %FALSE otherwise
1784 camel_service_disconnect_sync (CamelService *service,
1786 GCancellable *cancellable,
1789 AsyncClosure *closure;
1790 GAsyncResult *result;
1793 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1795 closure = async_closure_new ();
1797 camel_service_disconnect (
1798 service, clean, G_PRIORITY_DEFAULT,
1799 cancellable, async_closure_callback, closure);
1801 result = async_closure_wait (closure);
1803 success = camel_service_disconnect_finish (service, result, error);
1805 async_closure_free (closure);
1811 * camel_service_disconnect:
1812 * @service: a #CamelService
1813 * @clean: whether or not to try to disconnect cleanly
1814 * @io_priority: the I/O priority of the request
1815 * @cancellable: optional #GCancellable object, or %NULL
1816 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1817 * @user_data: data to pass to the callback function
1819 * If a disconnect operation is already in progress when this function is
1820 * called, its results will be reflected in this disconnect operation.
1822 * If any connect operations are in progress when this function is called,
1823 * they will be cancelled.
1825 * When the operation is finished, @callback will be called. You can
1826 * then call camel_service_disconnect_finish() to get the result of the
1832 camel_service_disconnect (CamelService *service,
1835 GCancellable *cancellable,
1836 GAsyncReadyCallback callback,
1840 CamelServiceClass *class;
1841 GSimpleAsyncResult *simple;
1843 g_return_if_fail (CAMEL_IS_SERVICE (service));
1845 class = CAMEL_SERVICE_GET_CLASS (service);
1846 g_return_if_fail (class->disconnect != NULL);
1848 simple = g_simple_async_result_new (
1849 G_OBJECT (service), callback,
1850 user_data, camel_service_disconnect);
1852 g_simple_async_result_set_check_cancellable (simple, cancellable);
1854 g_mutex_lock (&service->priv->connection_lock);
1856 switch (service->priv->status) {
1858 /* If a connect operation is currently in progress,
1859 * cancel it and make room for the disconnect operation. */
1860 case CAMEL_SERVICE_CONNECTING:
1862 service->priv->connection_op != NULL);
1863 g_cancellable_cancel (
1864 service->priv->connection_op->cancellable);
1865 connection_op_unref (service->priv->connection_op);
1866 service->priv->connection_op = NULL;
1869 /* Start a new disconnect operation. Subsequent disconnect
1870 * operations are queued until this operation completes and
1871 * will share this operation's result. */
1872 case CAMEL_SERVICE_CONNECTED:
1874 service->priv->connection_op == NULL);
1876 op = connection_op_new (simple, cancellable);
1877 service->priv->connection_op = op;
1879 service->priv->status = CAMEL_SERVICE_DISCONNECTING;
1880 service_queue_notify_connection_status (service);
1886 service_shared_disconnect_cb,
1887 connection_op_ref (op));
1890 /* If a disconnect operation is already in progress,
1891 * queue this operation so it completes at the same
1892 * time the first disconnect operation completes. */
1893 case CAMEL_SERVICE_DISCONNECTING:
1894 connection_op_add_pending (
1895 service->priv->connection_op,
1896 simple, cancellable);
1899 /* If we're already disconnected, just report success. */
1900 case CAMEL_SERVICE_DISCONNECTED:
1901 g_simple_async_result_complete_in_idle (simple);
1905 g_warn_if_reached ();
1908 g_mutex_unlock (&service->priv->connection_lock);
1910 g_object_unref (simple);
1914 * camel_service_disconnect_finish:
1915 * @service: a #CamelService
1916 * @result: a #GAsyncResult
1917 * @error: return location for a #GError, or %NULL
1919 * Finishes the operation started with camel_service_disconnect().
1921 * Returns: %TRUE if the connection was severed or %FALSE otherwise
1926 camel_service_disconnect_finish (CamelService *service,
1927 GAsyncResult *result,
1930 GSimpleAsyncResult *simple;
1932 g_return_val_if_fail (
1933 g_simple_async_result_is_valid (
1934 result, G_OBJECT (service), camel_service_disconnect), FALSE);
1936 simple = G_SIMPLE_ASYNC_RESULT (result);
1938 /* Assume success unless a GError is set. */
1939 return !g_simple_async_result_propagate_error (simple, error);
1943 * camel_service_authenticate_sync:
1944 * @service: a #CamelService
1945 * @mechanism: a SASL mechanism name, or %NULL
1946 * @cancellable: optional #GCancellable object, or %NULL
1947 * @error: return location for a #GError, or %NULL
1949 * Attempts to authenticate @service using @mechanism and, if necessary,
1950 * @service's #CamelService:password property. The function makes only
1951 * ONE attempt at authentication and does not loop.
1953 * If the authentication attempt completed and the server accepted the
1954 * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
1956 * If the authentication attempt completed but the server rejected the
1957 * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
1959 * If the authentication attempt failed to complete due to a network
1960 * communication issue or some other mishap, the function sets @error
1961 * and returns #CAMEL_AUTHENTICATION_ERROR.
1963 * Generally this function should only be called from a #CamelSession
1964 * subclass in order to implement its own authentication loop.
1966 * Returns: the authentication result
1970 CamelAuthenticationResult
1971 camel_service_authenticate_sync (CamelService *service,
1972 const gchar *mechanism,
1973 GCancellable *cancellable,
1976 CamelServiceClass *class;
1977 CamelAuthenticationResult result;
1979 g_return_val_if_fail (
1980 CAMEL_IS_SERVICE (service),
1981 CAMEL_AUTHENTICATION_REJECTED);
1983 class = CAMEL_SERVICE_GET_CLASS (service);
1984 g_return_val_if_fail (
1985 class->authenticate_sync != NULL,
1986 CAMEL_AUTHENTICATION_REJECTED);
1988 result = class->authenticate_sync (
1989 service, mechanism, cancellable, error);
1990 CAMEL_CHECK_GERROR (
1991 service, authenticate_sync,
1992 result != CAMEL_AUTHENTICATION_ERROR, error);
1998 * camel_service_authenticate:
1999 * @service: a #CamelService
2000 * @mechanism: a SASL mechanism name, or %NULL
2001 * @io_priority: the I/O priority of the request
2002 * @cancellable: optional #GCancellable object, or %NULL
2003 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2004 * @user_data: data to pass to the callback function
2006 * Asynchronously attempts to authenticate @service using @mechanism and,
2007 * if necessary, @service's #CamelService:password property. The function
2008 * makes only ONE attempt at authentication and does not loop.
2010 * Generally this function should only be called from a #CamelSession
2011 * subclass in order to implement its own authentication loop.
2013 * When the operation is finished, @callback will be called. You can
2014 * then call camel_service_authenticate_finish() to get the result of
2020 camel_service_authenticate (CamelService *service,
2021 const gchar *mechanism,
2023 GCancellable *cancellable,
2024 GAsyncReadyCallback callback,
2027 CamelServiceClass *class;
2029 g_return_if_fail (CAMEL_IS_SERVICE (service));
2031 class = CAMEL_SERVICE_GET_CLASS (service);
2032 g_return_if_fail (class->authenticate != NULL);
2034 class->authenticate (
2035 service, mechanism, io_priority,
2036 cancellable, callback, user_data);
2040 * camel_service_authenticate_finish:
2041 * @service: a #CamelService
2042 * @result: a #GAsyncResult
2043 * @error: return location for a #GError, or %NULL
2045 * Finishes the operation started with camel_service_authenticate().
2047 * If the authentication attempt completed and the server accepted the
2048 * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
2050 * If the authentication attempt completed but the server rejected the
2051 * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
2053 * If the authentication attempt failed to complete due to a network
2054 * communication issue or some other mishap, the function sets @error
2055 * and returns #CAMEL_AUTHENTICATION_ERROR.
2057 * Returns: the authentication result
2061 CamelAuthenticationResult
2062 camel_service_authenticate_finish (CamelService *service,
2063 GAsyncResult *result,
2066 CamelServiceClass *class;
2068 g_return_val_if_fail (
2069 CAMEL_IS_SERVICE (service),
2070 CAMEL_AUTHENTICATION_REJECTED);
2071 g_return_val_if_fail (
2072 G_IS_ASYNC_RESULT (result),
2073 CAMEL_AUTHENTICATION_REJECTED);
2075 class = CAMEL_SERVICE_GET_CLASS (service);
2076 g_return_val_if_fail (
2077 class->authenticate_finish,
2078 CAMEL_AUTHENTICATION_REJECTED);
2080 return class->authenticate_finish (service, result, error);
2084 * camel_service_query_auth_types_sync:
2085 * @service: a #CamelService
2086 * @cancellable: optional #GCancellable object, or %NULL
2087 * @error: return location for a #GError, or %NULL
2089 * Obtains a list of authentication types supported by @service.
2090 * Free the returned list with g_list_free().
2092 * Returns: a list of #CamelServiceAuthType structs
2095 camel_service_query_auth_types_sync (CamelService *service,
2096 GCancellable *cancellable,
2099 CamelServiceClass *class;
2101 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
2103 class = CAMEL_SERVICE_GET_CLASS (service);
2104 g_return_val_if_fail (class->query_auth_types_sync != NULL, NULL);
2106 return class->query_auth_types_sync (service, cancellable, error);
2110 * camel_service_query_auth_types:
2111 * @service: a #CamelService
2112 * @io_priority: the I/O priority of the request
2113 * @cancellable: optional #GCancellable object, or %NULL
2114 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2115 * @user_data: data to pass to the callback function
2117 * Asynchronously obtains a list of authentication types supported by
2120 * When the operation is finished, @callback will be called. You can
2121 * then call camel_service_query_auth_types_finish() to get the result
2127 camel_service_query_auth_types (CamelService *service,
2129 GCancellable *cancellable,
2130 GAsyncReadyCallback callback,
2133 CamelServiceClass *class;
2135 g_return_if_fail (CAMEL_IS_SERVICE (service));
2137 class = CAMEL_SERVICE_GET_CLASS (service);
2138 g_return_if_fail (class->query_auth_types != NULL);
2140 class->query_auth_types (
2141 service, io_priority,
2142 cancellable, callback, user_data);
2146 * camel_service_query_auth_types_finish:
2147 * @service: a #CamelService
2148 * @result: a #GAsyncResult
2149 * @error: return location for a #GError, or %NULL
2151 * Finishes the operation started with camel_service_query_auth_types().
2152 * Free the returned list with g_list_free().
2154 * Returns: a list of #CamelServiceAuthType structs
2159 camel_service_query_auth_types_finish (CamelService *service,
2160 GAsyncResult *result,
2163 CamelServiceClass *class;
2165 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
2166 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
2168 class = CAMEL_SERVICE_GET_CLASS (service);
2169 g_return_val_if_fail (class->query_auth_types_finish != NULL, NULL);
2171 return class->query_auth_types_finish (service, result, error);