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-service.h"
42 #include "camel-network-settings.h"
43 #include "camel-operation.h"
44 #include "camel-service.h"
45 #include "camel-session.h"
50 #define CAMEL_SERVICE_GET_PRIVATE(obj) \
51 (G_TYPE_INSTANCE_GET_PRIVATE \
52 ((obj), CAMEL_TYPE_SERVICE, CamelServicePrivate))
54 typedef struct _AsyncClosure AsyncClosure;
55 typedef struct _AsyncContext AsyncContext;
56 typedef struct _ConnectionOp ConnectionOp;
58 struct _CamelServicePrivate {
61 CamelSettings *settings;
64 CamelProvider *provider;
68 gchar *user_cache_dir;
72 GMutex connection_lock;
73 ConnectionOp *connection_op;
74 CamelServiceConnectionStatus status;
76 gboolean network_service_inited;
79 /* This is copied from EAsyncClosure in libedataserver.
80 * If this proves useful elsewhere in Camel we may want
81 * to split this out and make it part of the public API. */
82 struct _AsyncClosure {
84 GMainContext *context;
88 struct _AsyncContext {
90 gchar *auth_mechanism;
91 CamelAuthenticationResult auth_result;
94 /* The GQueue is only modified while CamelService's
95 * connection_lock is held, so it does not need its
97 struct _ConnectionOp {
98 volatile gint ref_count;
101 GSimpleAsyncResult *simple;
102 GCancellable *cancellable;
108 PROP_CONNECTION_STATUS,
117 /* Forward Declarations */
118 void camel_network_service_init (CamelNetworkService *service);
119 static void camel_service_initable_init (GInitableIface *interface);
121 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
122 CamelService, camel_service, CAMEL_TYPE_OBJECT,
123 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, camel_service_initable_init))
125 static AsyncClosure *
126 async_closure_new (void)
128 AsyncClosure *closure;
130 closure = g_slice_new0 (AsyncClosure);
131 closure->context = g_main_context_new ();
132 closure->loop = g_main_loop_new (closure->context, FALSE);
134 g_main_context_push_thread_default (closure->context);
139 static GAsyncResult *
140 async_closure_wait (AsyncClosure *closure)
142 g_return_val_if_fail (closure != NULL, NULL);
144 g_main_loop_run (closure->loop);
146 return closure->result;
150 async_closure_free (AsyncClosure *closure)
152 g_return_if_fail (closure != NULL);
154 g_main_context_pop_thread_default (closure->context);
156 g_main_loop_unref (closure->loop);
157 g_main_context_unref (closure->context);
159 if (closure->result != NULL)
160 g_object_unref (closure->result);
162 g_slice_free (AsyncClosure, closure);
166 async_closure_callback (GObject *object,
167 GAsyncResult *result,
170 AsyncClosure *real_closure;
172 g_return_if_fail (G_IS_OBJECT (object));
173 g_return_if_fail (G_IS_ASYNC_RESULT (result));
174 g_return_if_fail (closure != NULL);
176 real_closure = closure;
178 /* Replace any previous result. */
179 if (real_closure->result != NULL)
180 g_object_unref (real_closure->result);
181 real_closure->result = g_object_ref (result);
183 g_main_loop_quit (real_closure->loop);
187 async_context_free (AsyncContext *async_context)
189 g_list_free (async_context->auth_types);
191 g_free (async_context->auth_mechanism);
193 g_slice_free (AsyncContext, async_context);
196 static ConnectionOp *
197 connection_op_new (GSimpleAsyncResult *simple,
198 GCancellable *cancellable)
202 op = g_slice_new0 (ConnectionOp);
204 g_mutex_init (&op->simple_lock);
205 op->simple = g_object_ref (simple);
207 if (G_IS_CANCELLABLE (cancellable))
208 op->cancellable = g_object_ref (cancellable);
213 static ConnectionOp *
214 connection_op_ref (ConnectionOp *op)
216 g_return_val_if_fail (op != NULL, NULL);
217 g_return_val_if_fail (op->ref_count > 0, NULL);
219 g_atomic_int_inc (&op->ref_count);
225 connection_op_unref (ConnectionOp *op)
227 g_return_if_fail (op != NULL);
228 g_return_if_fail (op->ref_count > 0);
230 if (g_atomic_int_dec_and_test (&op->ref_count)) {
232 /* The pending queue should be empty. */
233 g_warn_if_fail (g_queue_is_empty (&op->pending));
235 g_mutex_clear (&op->simple_lock);
237 if (op->simple != NULL)
238 g_object_unref (op->simple);
240 if (op->cancel_id > 0)
241 g_cancellable_disconnect (
242 op->cancellable, op->cancel_id);
244 if (op->cancellable != NULL)
245 g_object_unref (op->cancellable);
247 g_slice_free (ConnectionOp, op);
252 connection_op_complete (ConnectionOp *op,
255 g_mutex_lock (&op->simple_lock);
257 if (op->simple != NULL && error != NULL)
258 g_simple_async_result_set_from_error (op->simple, error);
260 if (op->simple != NULL) {
261 g_simple_async_result_complete_in_idle (op->simple);
262 g_object_unref (op->simple);
266 g_mutex_unlock (&op->simple_lock);
270 connection_op_cancelled (GCancellable *cancellable,
273 /* Because we called g_simple_async_result_set_check_cancellable()
274 * we don't need to explicitly set a G_IO_ERROR_CANCELLED here. */
275 connection_op_complete (op, NULL);
279 connection_op_add_pending (ConnectionOp *op,
280 GSimpleAsyncResult *simple,
281 GCancellable *cancellable)
283 ConnectionOp *pending_op;
285 g_return_if_fail (op != NULL);
287 pending_op = connection_op_new (simple, cancellable);
289 if (pending_op->cancellable != NULL)
290 pending_op->cancel_id = g_cancellable_connect (
291 pending_op->cancellable,
292 G_CALLBACK (connection_op_cancelled),
293 pending_op, (GDestroyNotify) NULL);
295 g_queue_push_tail (&op->pending, pending_op);
299 connection_op_complete_pending (ConnectionOp *op,
302 ConnectionOp *pending_op;
304 g_return_if_fail (op != NULL);
306 while (!g_queue_is_empty (&op->pending)) {
307 pending_op = g_queue_pop_head (&op->pending);
308 connection_op_complete (pending_op, error);
309 connection_op_unref (pending_op);
314 service_find_old_data_dir (CamelService *service)
316 CamelProvider *provider;
317 CamelSession *session;
320 gboolean allows_host;
321 gboolean allows_user;
325 const gchar *base_dir;
328 provider = camel_service_get_provider (service);
329 url = camel_service_new_camel_url (service);
331 allows_host = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST);
332 allows_user = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_USER);
334 needs_host = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST);
335 needs_path = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH);
336 needs_user = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER);
338 /* This function reproduces the way service data directories used
339 * to be determined before we moved to just using the UID. If the
340 * old data directory exists, try renaming it to the new form.
342 * A virtual class method was used to determine the directory path,
343 * but no known CamelProviders ever overrode the default algorithm
344 * below. So this should work for everyone. */
346 path = g_string_new (provider->protocol);
349 g_string_append_c (path, '/');
350 if (url->user != NULL)
351 g_string_append (path, url->user);
353 g_string_append_c (path, '@');
354 if (url->host != NULL)
355 g_string_append (path, url->host);
357 g_string_append_c (path, ':');
358 g_string_append_printf (path, "%d", url->port);
360 } else if (!needs_user) {
361 g_string_append_c (path, '@');
364 } else if (allows_host) {
365 g_string_append_c (path, '/');
367 g_string_append_c (path, '@');
368 if (url->host != NULL)
369 g_string_append (path, url->host);
371 g_string_append_c (path, ':');
372 g_string_append_printf (path, "%d", url->port);
376 if (needs_path && url->path) {
377 if (*url->path != '/')
378 g_string_append_c (path, '/');
379 g_string_append (path, url->path);
382 session = camel_service_ref_session (service);
384 base_dir = camel_session_get_user_data_dir (session);
385 old_data_dir = g_build_filename (base_dir, path->str, NULL);
387 g_object_unref (session);
389 g_string_free (path, TRUE);
391 if (!g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) {
392 g_free (old_data_dir);
396 camel_url_free (url);
402 service_notify_connection_status_cb (gpointer user_data)
404 CamelService *service = CAMEL_SERVICE (user_data);
406 g_object_notify (G_OBJECT (service), "connection-status");
412 service_queue_notify_connection_status (CamelService *service)
414 CamelSession *session;
416 session = camel_service_ref_session (service);
418 /* Prioritize ahead of GTK+ redraws. */
419 camel_session_idle_add (
420 session, G_PRIORITY_HIGH_IDLE,
421 service_notify_connection_status_cb,
422 g_object_ref (service),
423 (GDestroyNotify) g_object_unref);
425 g_object_unref (session);
429 service_shared_connect_cb (GObject *source_object,
430 GAsyncResult *result,
433 CamelService *service;
434 CamelServiceClass *class;
435 ConnectionOp *op = user_data;
437 GError *error = NULL;
439 /* This avoids a compiler warning
440 * in the CAMEL_CHECK_GERROR macro. */
441 GError **p_error = &error;
443 service = CAMEL_SERVICE (source_object);
444 class = CAMEL_SERVICE_GET_CLASS (service);
445 g_return_if_fail (class->connect_finish != NULL);
447 success = class->connect_finish (service, result, &error);
448 CAMEL_CHECK_GERROR (service, connect_sync, success, p_error);
450 g_mutex_lock (&service->priv->connection_lock);
452 if (service->priv->connection_op == op) {
453 connection_op_unref (service->priv->connection_op);
454 service->priv->connection_op = NULL;
456 service->priv->status = CAMEL_SERVICE_CONNECTED;
458 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
459 service_queue_notify_connection_status (service);
462 connection_op_complete (op, error);
463 connection_op_complete_pending (op, error);
465 g_mutex_unlock (&service->priv->connection_lock);
467 connection_op_unref (op);
468 g_clear_error (&error);
472 service_shared_disconnect_cb (GObject *source_object,
473 GAsyncResult *result,
476 CamelService *service;
477 CamelServiceClass *class;
478 ConnectionOp *op = user_data;
480 GError *error = NULL;
482 /* This avoids a compiler warning
483 * in the CAMEL_CHECK_GERROR macro. */
484 GError **p_error = &error;
486 service = CAMEL_SERVICE (source_object);
487 class = CAMEL_SERVICE_GET_CLASS (service);
488 g_return_if_fail (class->disconnect_finish != NULL);
490 success = class->disconnect_finish (service, result, &error);
491 CAMEL_CHECK_GERROR (service, disconnect_sync, success, p_error);
493 g_mutex_lock (&service->priv->connection_lock);
495 if (service->priv->connection_op == op) {
496 connection_op_unref (service->priv->connection_op);
497 service->priv->connection_op = NULL;
499 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
501 service->priv->status = CAMEL_SERVICE_CONNECTED;
502 service_queue_notify_connection_status (service);
505 connection_op_complete (op, error);
506 connection_op_complete_pending (op, error);
508 g_mutex_unlock (&service->priv->connection_lock);
510 connection_op_unref (op);
511 g_clear_error (&error);
515 service_set_provider (CamelService *service,
516 CamelProvider *provider)
518 g_return_if_fail (provider != NULL);
519 g_return_if_fail (service->priv->provider == NULL);
521 service->priv->provider = provider;
525 service_set_session (CamelService *service,
526 CamelSession *session)
528 g_return_if_fail (CAMEL_IS_SESSION (session));
530 g_weak_ref_set (&service->priv->session, session);
534 service_set_uid (CamelService *service,
537 g_return_if_fail (uid != NULL);
538 g_return_if_fail (service->priv->uid == NULL);
540 service->priv->uid = g_strdup (uid);
544 service_set_property (GObject *object,
549 switch (property_id) {
550 case PROP_DISPLAY_NAME:
551 camel_service_set_display_name (
552 CAMEL_SERVICE (object),
553 g_value_get_string (value));
557 camel_service_set_password (
558 CAMEL_SERVICE (object),
559 g_value_get_string (value));
563 service_set_provider (
564 CAMEL_SERVICE (object),
565 g_value_get_pointer (value));
569 service_set_session (
570 CAMEL_SERVICE (object),
571 g_value_get_object (value));
575 camel_service_set_settings (
576 CAMEL_SERVICE (object),
577 g_value_get_object (value));
582 CAMEL_SERVICE (object),
583 g_value_get_string (value));
587 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
591 service_get_property (GObject *object,
596 switch (property_id) {
597 case PROP_CONNECTION_STATUS:
599 value, camel_service_get_connection_status (
600 CAMEL_SERVICE (object)));
603 case PROP_DISPLAY_NAME:
605 value, camel_service_get_display_name (
606 CAMEL_SERVICE (object)));
611 value, camel_service_get_password (
612 CAMEL_SERVICE (object)));
616 g_value_set_pointer (
617 value, camel_service_get_provider (
618 CAMEL_SERVICE (object)));
622 g_value_take_object (
623 value, camel_service_ref_session (
624 CAMEL_SERVICE (object)));
628 g_value_take_object (
629 value, camel_service_ref_settings (
630 CAMEL_SERVICE (object)));
635 value, camel_service_get_uid (
636 CAMEL_SERVICE (object)));
640 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
644 service_dispose (GObject *object)
646 CamelServicePrivate *priv;
648 priv = CAMEL_SERVICE_GET_PRIVATE (object);
650 g_weak_ref_set (&priv->session, NULL);
652 if (priv->settings != NULL) {
653 g_object_unref (priv->settings);
654 priv->settings = NULL;
657 /* Chain up to parent's dispose() method. */
658 G_OBJECT_CLASS (camel_service_parent_class)->dispose (object);
662 service_finalize (GObject *object)
664 CamelServicePrivate *priv;
666 priv = CAMEL_SERVICE_GET_PRIVATE (object);
668 if (priv->status == CAMEL_SERVICE_CONNECTED)
669 CAMEL_SERVICE_GET_CLASS (object)->disconnect_sync (
670 CAMEL_SERVICE (object), TRUE, NULL, NULL);
672 g_mutex_clear (&priv->settings_lock);
674 g_free (priv->display_name);
675 g_free (priv->user_data_dir);
676 g_free (priv->user_cache_dir);
678 g_free (priv->password);
680 /* There should be no outstanding connection operations. */
681 g_warn_if_fail (priv->connection_op == NULL);
682 g_mutex_clear (&priv->connection_lock);
684 /* Chain up to parent's finalize() method. */
685 G_OBJECT_CLASS (camel_service_parent_class)->finalize (object);
689 service_constructed (GObject *object)
691 CamelService *service;
692 CamelSession *session;
693 const gchar *base_dir;
696 /* Chain up to parent's constructed() method. */
697 G_OBJECT_CLASS (camel_service_parent_class)->constructed (object);
699 service = CAMEL_SERVICE (object);
700 session = camel_service_ref_session (service);
702 uid = camel_service_get_uid (service);
704 base_dir = camel_session_get_user_data_dir (session);
705 service->priv->user_data_dir = g_build_filename (base_dir, uid, NULL);
707 base_dir = camel_session_get_user_cache_dir (session);
708 service->priv->user_cache_dir = g_build_filename (base_dir, uid, NULL);
710 g_object_unref (session);
712 /* The CamelNetworkService interface needs initialization. */
713 if (CAMEL_IS_NETWORK_SERVICE (service)) {
714 camel_network_service_init (CAMEL_NETWORK_SERVICE (service));
715 service->priv->network_service_inited = TRUE;
720 service_get_name (CamelService *service,
724 "%s does not implement CamelServiceClass::get_name()",
725 G_OBJECT_TYPE_NAME (service));
727 return g_strdup (G_OBJECT_TYPE_NAME (service));
731 service_connect_sync (CamelService *service,
732 GCancellable *cancellable,
735 /* Default behavior for local storage providers. */
740 service_disconnect_sync (CamelService *service,
742 GCancellable *cancellable,
745 /* Default behavior for local storage providers. */
750 service_query_auth_types_sync (CamelService *service,
751 GCancellable *cancellable,
758 service_connect_thread (GSimpleAsyncResult *simple,
760 GCancellable *cancellable)
762 CamelService *service;
763 CamelServiceClass *class;
764 GError *error = NULL;
766 /* Note we call the class method directly here. */
768 service = CAMEL_SERVICE (object);
770 class = CAMEL_SERVICE_GET_CLASS (service);
771 g_return_if_fail (class->connect_sync != NULL);
773 class->connect_sync (service, cancellable, &error);
776 g_simple_async_result_take_error (simple, error);
780 service_connect (CamelService *service,
782 GCancellable *cancellable,
783 GAsyncReadyCallback callback,
786 GSimpleAsyncResult *simple;
788 simple = g_simple_async_result_new (
789 G_OBJECT (service), callback, user_data, service_connect);
791 g_simple_async_result_set_check_cancellable (simple, cancellable);
793 g_simple_async_result_run_in_thread (
794 simple, service_connect_thread, io_priority, cancellable);
796 g_object_unref (simple);
800 service_connect_finish (CamelService *service,
801 GAsyncResult *result,
804 GSimpleAsyncResult *simple;
806 g_return_val_if_fail (
807 g_simple_async_result_is_valid (
808 result, G_OBJECT (service), service_connect), FALSE);
810 simple = G_SIMPLE_ASYNC_RESULT (result);
812 /* Assume success unless a GError is set. */
813 return !g_simple_async_result_propagate_error (simple, error);
817 service_disconnect_thread (GSimpleAsyncResult *simple,
819 GCancellable *cancellable)
821 CamelService *service;
822 CamelServiceClass *class;
824 GError *error = NULL;
826 /* Note we call the class method directly here. */
828 service = CAMEL_SERVICE (object);
829 clean = g_simple_async_result_get_op_res_gboolean (simple);
831 class = CAMEL_SERVICE_GET_CLASS (service);
832 g_return_if_fail (class->disconnect_sync != NULL);
834 class->disconnect_sync (service, clean, cancellable, &error);
837 g_simple_async_result_take_error (simple, error);
841 service_disconnect (CamelService *service,
844 GCancellable *cancellable,
845 GAsyncReadyCallback callback,
848 GSimpleAsyncResult *simple;
850 simple = g_simple_async_result_new (
851 G_OBJECT (service), callback, user_data, service_disconnect);
853 g_simple_async_result_set_check_cancellable (simple, cancellable);
855 g_simple_async_result_set_op_res_gboolean (simple, clean);
857 g_simple_async_result_run_in_thread (
858 simple, service_disconnect_thread, io_priority, cancellable);
860 g_object_unref (simple);
864 service_disconnect_finish (CamelService *service,
865 GAsyncResult *result,
868 GSimpleAsyncResult *simple;
870 g_return_val_if_fail (
871 g_simple_async_result_is_valid (
872 result, G_OBJECT (service), service_disconnect), FALSE);
874 simple = G_SIMPLE_ASYNC_RESULT (result);
876 /* Assume success unless a GError is set. */
877 return !g_simple_async_result_propagate_error (simple, error);
881 service_authenticate_thread (GSimpleAsyncResult *simple,
883 GCancellable *cancellable)
885 AsyncContext *async_context;
886 GError *error = NULL;
888 async_context = g_simple_async_result_get_op_res_gpointer (simple);
890 async_context->auth_result = camel_service_authenticate_sync (
891 CAMEL_SERVICE (object), async_context->auth_mechanism,
892 cancellable, &error);
895 g_simple_async_result_take_error (simple, error);
899 service_authenticate (CamelService *service,
900 const gchar *mechanism,
902 GCancellable *cancellable,
903 GAsyncReadyCallback callback,
906 GSimpleAsyncResult *simple;
907 AsyncContext *async_context;
909 async_context = g_slice_new0 (AsyncContext);
910 async_context->auth_mechanism = g_strdup (mechanism);
912 simple = g_simple_async_result_new (
913 G_OBJECT (service), callback, user_data, service_authenticate);
915 g_simple_async_result_set_check_cancellable (simple, cancellable);
917 g_simple_async_result_set_op_res_gpointer (
918 simple, async_context, (GDestroyNotify) async_context_free);
920 g_simple_async_result_run_in_thread (
921 simple, service_authenticate_thread, io_priority, cancellable);
923 g_object_unref (simple);
926 static CamelAuthenticationResult
927 service_authenticate_finish (CamelService *service,
928 GAsyncResult *result,
931 GSimpleAsyncResult *simple;
932 AsyncContext *async_context;
934 g_return_val_if_fail (
935 g_simple_async_result_is_valid (
936 result, G_OBJECT (service), service_authenticate),
937 CAMEL_AUTHENTICATION_REJECTED);
939 simple = G_SIMPLE_ASYNC_RESULT (result);
940 async_context = g_simple_async_result_get_op_res_gpointer (simple);
942 if (g_simple_async_result_propagate_error (simple, error))
943 return CAMEL_AUTHENTICATION_ERROR;
945 return async_context->auth_result;
949 service_query_auth_types_thread (GSimpleAsyncResult *simple,
951 GCancellable *cancellable)
953 AsyncContext *async_context;
954 GError *error = NULL;
956 async_context = g_simple_async_result_get_op_res_gpointer (simple);
958 async_context->auth_types = camel_service_query_auth_types_sync (
959 CAMEL_SERVICE (object), cancellable, &error);
962 g_simple_async_result_take_error (simple, error);
966 service_query_auth_types (CamelService *service,
968 GCancellable *cancellable,
969 GAsyncReadyCallback callback,
972 GSimpleAsyncResult *simple;
973 AsyncContext *async_context;
975 async_context = g_slice_new0 (AsyncContext);
977 simple = g_simple_async_result_new (
978 G_OBJECT (service), callback,
979 user_data, service_query_auth_types);
981 g_simple_async_result_set_check_cancellable (simple, cancellable);
983 g_simple_async_result_set_op_res_gpointer (
984 simple, async_context, (GDestroyNotify) async_context_free);
986 g_simple_async_result_run_in_thread (
987 simple, service_query_auth_types_thread,
988 io_priority, cancellable);
990 g_object_unref (simple);
994 service_query_auth_types_finish (CamelService *service,
995 GAsyncResult *result,
998 GSimpleAsyncResult *simple;
999 AsyncContext *async_context;
1001 g_return_val_if_fail (
1002 g_simple_async_result_is_valid (
1003 result, G_OBJECT (service),
1004 service_query_auth_types), NULL);
1006 simple = G_SIMPLE_ASYNC_RESULT (result);
1007 async_context = g_simple_async_result_get_op_res_gpointer (simple);
1009 if (g_simple_async_result_propagate_error (simple, error))
1012 return g_list_copy (async_context->auth_types);
1016 service_initable_init (GInitable *initable,
1017 GCancellable *cancellable,
1020 /* Nothing to do here, but we may need add something in the future.
1021 * For now this is a placeholder so subclasses can safely chain up. */
1027 camel_service_class_init (CamelServiceClass *class)
1029 GObjectClass *object_class;
1031 g_type_class_add_private (class, sizeof (CamelServicePrivate));
1033 object_class = G_OBJECT_CLASS (class);
1034 object_class->set_property = service_set_property;
1035 object_class->get_property = service_get_property;
1036 object_class->dispose = service_dispose;
1037 object_class->finalize = service_finalize;
1038 object_class->constructed = service_constructed;
1040 class->settings_type = CAMEL_TYPE_SETTINGS;
1041 class->get_name = service_get_name;
1042 class->connect_sync = service_connect_sync;
1043 class->disconnect_sync = service_disconnect_sync;
1044 class->query_auth_types_sync = service_query_auth_types_sync;
1046 class->connect = service_connect;
1047 class->connect_finish = service_connect_finish;
1048 class->disconnect = service_disconnect;
1049 class->disconnect_finish = service_disconnect_finish;
1050 class->authenticate = service_authenticate;
1051 class->authenticate_finish = service_authenticate_finish;
1052 class->query_auth_types = service_query_auth_types;
1053 class->query_auth_types_finish = service_query_auth_types_finish;
1055 g_object_class_install_property (
1057 PROP_CONNECTION_STATUS,
1059 "connection-status",
1060 "Connection Status",
1061 "The connection status for the service",
1062 CAMEL_TYPE_SERVICE_CONNECTION_STATUS,
1063 CAMEL_SERVICE_DISCONNECTED,
1065 G_PARAM_STATIC_STRINGS));
1067 g_object_class_install_property (
1070 g_param_spec_string (
1073 "The display name for the service",
1077 G_PARAM_STATIC_STRINGS));
1079 g_object_class_install_property (
1082 g_param_spec_string (
1085 "The password for the service",
1089 G_PARAM_STATIC_STRINGS));
1091 g_object_class_install_property (
1094 g_param_spec_pointer (
1097 "The CamelProvider for the service",
1099 G_PARAM_CONSTRUCT_ONLY |
1100 G_PARAM_STATIC_STRINGS));
1102 g_object_class_install_property (
1105 g_param_spec_object (
1108 "A CamelSession instance",
1111 G_PARAM_CONSTRUCT_ONLY |
1112 G_PARAM_STATIC_STRINGS));
1114 g_object_class_install_property (
1117 g_param_spec_object (
1120 "A CamelSettings instance",
1121 CAMEL_TYPE_SETTINGS,
1124 G_PARAM_STATIC_STRINGS));
1126 g_object_class_install_property (
1129 g_param_spec_string (
1132 "The unique identity of the service",
1135 G_PARAM_CONSTRUCT_ONLY |
1136 G_PARAM_STATIC_STRINGS));
1140 camel_service_initable_init (GInitableIface *interface)
1142 interface->init = service_initable_init;
1146 camel_service_init (CamelService *service)
1148 service->priv = CAMEL_SERVICE_GET_PRIVATE (service);
1150 g_mutex_init (&service->priv->settings_lock);
1151 g_mutex_init (&service->priv->connection_lock);
1152 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
1155 G_DEFINE_QUARK (camel-service-error-quark, camel_service_error)
1158 * camel_service_migrate_files:
1159 * @service: a #CamelService
1161 * Performs any necessary file migrations for @service. This should be
1162 * called after installing or configuring the @service's #CamelSettings,
1163 * since it requires building a URL string for @service.
1168 camel_service_migrate_files (CamelService *service)
1170 const gchar *new_data_dir;
1171 gchar *old_data_dir;
1173 g_return_if_fail (CAMEL_IS_SERVICE (service));
1175 new_data_dir = camel_service_get_user_data_dir (service);
1176 old_data_dir = service_find_old_data_dir (service);
1178 /* If the old data directory name exists, try renaming
1179 * it to the new data directory. Failure is non-fatal. */
1180 if (old_data_dir != NULL) {
1181 g_rename (old_data_dir, new_data_dir);
1182 g_free (old_data_dir);
1187 * camel_service_new_camel_url:
1188 * @service: a #CamelService
1190 * Returns a new #CamelURL representing @service.
1191 * Free the returned #CamelURL with camel_url_free().
1193 * Returns: a new #CamelURL
1198 camel_service_new_camel_url (CamelService *service)
1201 CamelProvider *provider;
1202 CamelSettings *settings;
1208 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1210 provider = camel_service_get_provider (service);
1211 g_return_val_if_fail (provider != NULL, NULL);
1213 settings = camel_service_ref_settings (service);
1215 /* Allocate as camel_url_new_with_base() does. */
1216 url = g_new0 (CamelURL, 1);
1218 if (CAMEL_IS_NETWORK_SETTINGS (settings)) {
1219 CamelNetworkSettings *network_settings;
1221 network_settings = CAMEL_NETWORK_SETTINGS (settings);
1222 host = camel_network_settings_dup_host (network_settings);
1223 port = camel_network_settings_get_port (network_settings);
1224 user = camel_network_settings_dup_user (network_settings);
1227 if (CAMEL_IS_LOCAL_SETTINGS (settings)) {
1228 CamelLocalSettings *local_settings;
1230 local_settings = CAMEL_LOCAL_SETTINGS (settings);
1231 path = camel_local_settings_dup_path (local_settings);
1234 camel_url_set_protocol (url, provider->protocol);
1235 camel_url_set_host (url, host);
1236 camel_url_set_port (url, port);
1237 camel_url_set_user (url, user);
1238 camel_url_set_path (url, path);
1244 g_object_unref (settings);
1250 * camel_service_get_connection_status:
1251 * @service: a #CamelService
1253 * Returns the connection status for @service.
1255 * Returns: the connection status
1259 CamelServiceConnectionStatus
1260 camel_service_get_connection_status (CamelService *service)
1262 g_return_val_if_fail (
1263 CAMEL_IS_SERVICE (service),
1264 CAMEL_SERVICE_DISCONNECTED);
1266 return service->priv->status;
1270 * camel_service_get_display_name:
1271 * @service: a #CamelService
1273 * Returns the display name for @service, or %NULL if @service has not
1274 * been given a display name. The display name is intended for use in
1275 * a user interface and should generally be given a user-defined name.
1277 * Compare this with camel_service_get_name(), which returns a built-in
1278 * description of the type of service (IMAP, SMTP, etc.).
1280 * Returns: the display name for @service, or %NULL
1285 camel_service_get_display_name (CamelService *service)
1287 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1289 return service->priv->display_name;
1293 * camel_service_set_display_name:
1294 * @service: a #CamelService
1295 * @display_name: a valid UTF-8 string, or %NULL
1297 * Assigns a UTF-8 display name to @service. The display name is intended
1298 * for use in a user interface and should generally be given a user-defined
1301 * Compare this with camel_service_get_name(), which returns a built-in
1302 * description of the type of service (IMAP, SMTP, etc.).
1307 camel_service_set_display_name (CamelService *service,
1308 const gchar *display_name)
1310 g_return_if_fail (CAMEL_IS_SERVICE (service));
1312 if (g_strcmp0 (service->priv->display_name, display_name) == 0)
1315 if (display_name != NULL)
1316 g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
1318 g_free (service->priv->display_name);
1319 service->priv->display_name = g_strdup (display_name);
1321 g_object_notify (G_OBJECT (service), "display-name");
1325 * camel_service_get_password:
1326 * @service: a #CamelService
1328 * Returns the password for @service. Some SASL mechanisms use this
1329 * when attempting to authenticate.
1331 * Returns: the password for @service
1336 camel_service_get_password (CamelService *service)
1338 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1340 return service->priv->password;
1344 * camel_service_set_password:
1345 * @service: a #CamelService
1346 * @password: the password for @service
1348 * Sets the password for @service. Use this function to cache the password
1349 * in memory after obtaining it through camel_session_get_password(). Some
1350 * SASL mechanisms use this when attempting to authenticate.
1355 camel_service_set_password (CamelService *service,
1356 const gchar *password)
1358 g_return_if_fail (CAMEL_IS_SERVICE (service));
1360 if (g_strcmp0 (service->priv->password, password) == 0)
1363 g_free (service->priv->password);
1364 service->priv->password = g_strdup (password);
1366 g_object_notify (G_OBJECT (service), "password");
1370 * camel_service_get_user_data_dir:
1371 * @service: a #CamelService
1373 * Returns the base directory under which to store user-specific data
1374 * for @service. The directory is formed by appending the directory
1375 * returned by camel_session_get_user_data_dir() with the service's
1376 * #CamelService:uid value.
1378 * Returns: the base directory for @service
1383 camel_service_get_user_data_dir (CamelService *service)
1385 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1387 return service->priv->user_data_dir;
1391 * camel_service_get_user_cache_dir:
1392 * @service: a #CamelService
1394 * Returns the base directory under which to store cache data
1395 * for @service. The directory is formed by appending the directory
1396 * returned by camel_session_get_user_cache_dir() with the service's
1397 * #CamelService:uid value.
1399 * Returns: the base cache directory for @service
1404 camel_service_get_user_cache_dir (CamelService *service)
1406 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1408 return service->priv->user_cache_dir;
1412 * camel_service_get_name:
1413 * @service: a #CamelService
1414 * @brief: whether or not to use a briefer form
1416 * This gets the name of the service in a "friendly" (suitable for
1417 * humans) form. If @brief is %TRUE, this should be a brief description
1418 * such as for use in the folder tree. If @brief is %FALSE, it should
1419 * be a more complete and mostly unambiguous description.
1421 * Returns: a description of the service which the caller must free
1424 camel_service_get_name (CamelService *service,
1427 CamelServiceClass *class;
1429 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1431 class = CAMEL_SERVICE_GET_CLASS (service);
1432 g_return_val_if_fail (class->get_name != NULL, NULL);
1434 return class->get_name (service, brief);
1438 * camel_service_get_provider:
1439 * @service: a #CamelService
1441 * Gets the #CamelProvider associated with the service.
1443 * Returns: the #CamelProvider
1446 camel_service_get_provider (CamelService *service)
1448 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1450 return service->priv->provider;
1454 * camel_service_ref_session:
1455 * @service: a #CamelService
1457 * Returns the #CamelSession associated with the service.
1459 * The returned #CamelSession is referenced for thread-safety. Unreference
1460 * the #CamelSession with g_object_unref() when finished with it.
1462 * Returns: the #CamelSession
1467 camel_service_ref_session (CamelService *service)
1469 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1471 return g_weak_ref_get (&service->priv->session);
1475 * camel_service_get_session:
1476 * @service: a #CamelService
1478 * Returns the #CamelSession associated with the service.
1480 * Note this function is not thread-safe. The returned #CamelSession could
1481 * be finalized by another thread while the caller is still using it.
1483 * Returns: the #CamelSession
1485 * Deprecated: 3.8: Use camel_service_ref_session() instead.
1488 camel_service_get_session (CamelService *service)
1490 CamelSession *session;
1492 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1494 session = camel_service_ref_session (service);
1496 /* XXX Drop the CamelSession reference for backward-compatibility.
1497 * This is risky. Without a reference, the CamelSession could
1498 * be finalized while the caller is still using it. */
1499 if (session != NULL)
1500 g_object_unref (session);
1506 * camel_service_ref_settings:
1507 * @service: a #CamelService
1509 * Returns the #CamelSettings instance associated with the service.
1511 * The returned #CamelSettings is referenced for thread-safety and must
1512 * be unreferenced with g_object_unref() when finished with it.
1514 * Returns: the #CamelSettings
1519 camel_service_ref_settings (CamelService *service)
1521 CamelSettings *settings;
1523 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1525 /* Every service should have a settings object. */
1526 g_return_val_if_fail (service->priv->settings != NULL, NULL);
1528 g_mutex_lock (&service->priv->settings_lock);
1530 settings = g_object_ref (service->priv->settings);
1532 g_mutex_unlock (&service->priv->settings_lock);
1538 * camel_service_set_settings:
1539 * @service: a #CamelService
1540 * @settings: an instance derviced from #CamelSettings, or %NULL
1542 * Associates a new #CamelSettings instance with the service.
1543 * The @settings instance must match the settings type defined in
1544 * #CamelServiceClass. If @settings is %NULL, a new #CamelSettings
1545 * instance of the appropriate type is created with all properties
1551 camel_service_set_settings (CamelService *service,
1552 CamelSettings *settings)
1554 CamelServiceClass *class;
1556 g_return_if_fail (CAMEL_IS_SERVICE (service));
1558 class = CAMEL_SERVICE_GET_CLASS (service);
1560 if (settings != NULL) {
1563 G_OBJECT_TYPE (settings),
1564 class->settings_type));
1565 g_object_ref (settings);
1570 class->settings_type,
1571 CAMEL_TYPE_SETTINGS));
1572 settings = g_object_new (class->settings_type, NULL);
1575 g_mutex_lock (&service->priv->settings_lock);
1577 if (service->priv->settings != NULL)
1578 g_object_unref (service->priv->settings);
1580 service->priv->settings = settings; /* takes ownership */
1582 g_mutex_unlock (&service->priv->settings_lock);
1584 /* If the service is a CamelNetworkService, it needs to
1585 * replace its GSocketConnectable for the new settings. */
1586 if (service->priv->network_service_inited)
1587 camel_network_service_set_connectable (
1588 CAMEL_NETWORK_SERVICE (service), NULL);
1590 g_object_notify (G_OBJECT (service), "settings");
1594 * camel_service_get_uid:
1595 * @service: a #CamelService
1597 * Gets the unique identifier string associated with the service.
1599 * Returns: the UID string
1604 camel_service_get_uid (CamelService *service)
1606 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1608 return service->priv->uid;
1612 * camel_service_connect_sync:
1613 * @service: a #CamelService
1614 * @cancellable: optional #GCancellable object, or %NULL
1615 * @error: return location for a #GError, or %NULL
1617 * Connects @service to a remote server using the information in its
1618 * #CamelService:settings instance.
1620 * If a connect operation is already in progress when this function is
1621 * called, its results will be reflected in this connect operation.
1623 * Returns: %TRUE if the connection is made or %FALSE otherwise
1628 camel_service_connect_sync (CamelService *service,
1629 GCancellable *cancellable,
1632 AsyncClosure *closure;
1633 GAsyncResult *result;
1636 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1638 closure = async_closure_new ();
1640 camel_service_connect (
1641 service, G_PRIORITY_DEFAULT, cancellable,
1642 async_closure_callback, closure);
1644 result = async_closure_wait (closure);
1646 success = camel_service_connect_finish (service, result, error);
1648 async_closure_free (closure);
1654 * camel_service_connect:
1655 * @service: a #CamelService
1656 * @io_priority: the I/O priority of the request
1657 * @cancellable: optional #GCancellable object, or %NULL
1658 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1659 * @user_data: data to pass to the callback function
1661 * Asynchronously connects @service to a remote server using the information
1662 * in its #CamelService:settings instance.
1664 * If a connect operation is already in progress when this function is
1665 * called, its results will be reflected in this connect operation.
1667 * If any disconnect operations are in progress when this function is
1668 * called, they will be cancelled.
1670 * When the operation is finished, @callback will be called. You can
1671 * then call camel_service_connect_finish() to get the result of the
1677 camel_service_connect (CamelService *service,
1679 GCancellable *cancellable,
1680 GAsyncReadyCallback callback,
1684 CamelServiceClass *class;
1685 GSimpleAsyncResult *simple;
1687 g_return_if_fail (CAMEL_IS_SERVICE (service));
1689 class = CAMEL_SERVICE_GET_CLASS (service);
1690 g_return_if_fail (class->connect != NULL);
1692 simple = g_simple_async_result_new (
1693 G_OBJECT (service), callback,
1694 user_data, camel_service_connect);
1696 g_simple_async_result_set_check_cancellable (simple, cancellable);
1698 g_mutex_lock (&service->priv->connection_lock);
1700 switch (service->priv->status) {
1702 /* If a connect operation is already in progress,
1703 * queue this operation so it completes at the same
1704 * time the first connect operation completes. */
1705 case CAMEL_SERVICE_CONNECTING:
1706 connection_op_add_pending (
1707 service->priv->connection_op,
1708 simple, cancellable);
1711 /* If we're already connected, just report success. */
1712 case CAMEL_SERVICE_CONNECTED:
1713 g_simple_async_result_complete_in_idle (simple);
1716 /* If a disconnect operation is currently in progress,
1717 * cancel it and make room for the connect operation. */
1718 case CAMEL_SERVICE_DISCONNECTING:
1720 service->priv->connection_op != NULL);
1721 g_cancellable_cancel (
1722 service->priv->connection_op->cancellable);
1723 connection_op_unref (service->priv->connection_op);
1724 service->priv->connection_op = NULL;
1727 /* Start a new connect operation. Subsequent connect
1728 * operations are queued until this operation completes
1729 * and will share this operation's result. */
1730 case CAMEL_SERVICE_DISCONNECTED:
1732 service->priv->connection_op == NULL);
1734 op = connection_op_new (simple, cancellable);
1735 service->priv->connection_op = op;
1737 service->priv->status = CAMEL_SERVICE_CONNECTING;
1738 service_queue_notify_connection_status (service);
1744 service_shared_connect_cb,
1745 connection_op_ref (op));
1749 g_warn_if_reached ();
1752 g_mutex_unlock (&service->priv->connection_lock);
1754 g_object_unref (simple);
1758 * camel_service_connect_finish:
1759 * @service: a #CamelService
1760 * @result: a #GAsyncResult
1761 * @error: return location for a #GError, or %NULL
1763 * Finishes the operation started with camel_service_connect().
1765 * Returns: %TRUE if the connection was made or %FALSE otherwise
1770 camel_service_connect_finish (CamelService *service,
1771 GAsyncResult *result,
1774 GSimpleAsyncResult *simple;
1776 g_return_val_if_fail (
1777 g_simple_async_result_is_valid (
1778 result, G_OBJECT (service), camel_service_connect), FALSE);
1780 simple = G_SIMPLE_ASYNC_RESULT (result);
1782 /* Assume success unless a GError is set. */
1783 return !g_simple_async_result_propagate_error (simple, error);
1787 * camel_service_disconnect_sync:
1788 * @service: a #CamelService
1789 * @clean: whether or not to try to disconnect cleanly
1790 * @cancellable: optional #GCancellable object, or %NULL
1791 * @error: return location for a #GError, or %NULL
1793 * Disconnect from the service. If @clean is %FALSE, it should not
1794 * try to do any synchronizing or other cleanup of the connection.
1796 * If a disconnect operation is already in progress when this function is
1797 * called, its results will be reflected in this disconnect operation.
1799 * If any connect operations are in progress when this function is called,
1800 * they will be cancelled.
1802 * Returns: %TRUE if the connection was severed or %FALSE otherwise
1807 camel_service_disconnect_sync (CamelService *service,
1809 GCancellable *cancellable,
1812 AsyncClosure *closure;
1813 GAsyncResult *result;
1816 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1818 closure = async_closure_new ();
1820 camel_service_disconnect (
1821 service, clean, G_PRIORITY_DEFAULT,
1822 cancellable, async_closure_callback, closure);
1824 result = async_closure_wait (closure);
1826 success = camel_service_disconnect_finish (service, result, error);
1828 async_closure_free (closure);
1834 * camel_service_disconnect:
1835 * @service: a #CamelService
1836 * @clean: whether or not to try to disconnect cleanly
1837 * @io_priority: the I/O priority of the request
1838 * @cancellable: optional #GCancellable object, or %NULL
1839 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1840 * @user_data: data to pass to the callback function
1842 * If a disconnect operation is already in progress when this function is
1843 * called, its results will be reflected in this disconnect operation.
1845 * If any connect operations are in progress when this function is called,
1846 * they will be cancelled.
1848 * When the operation is finished, @callback will be called. You can
1849 * then call camel_service_disconnect_finish() to get the result of the
1855 camel_service_disconnect (CamelService *service,
1858 GCancellable *cancellable,
1859 GAsyncReadyCallback callback,
1863 CamelServiceClass *class;
1864 GSimpleAsyncResult *simple;
1866 g_return_if_fail (CAMEL_IS_SERVICE (service));
1868 class = CAMEL_SERVICE_GET_CLASS (service);
1869 g_return_if_fail (class->disconnect != NULL);
1871 simple = g_simple_async_result_new (
1872 G_OBJECT (service), callback,
1873 user_data, camel_service_disconnect);
1875 g_simple_async_result_set_check_cancellable (simple, cancellable);
1877 g_mutex_lock (&service->priv->connection_lock);
1879 switch (service->priv->status) {
1881 /* If a connect operation is currently in progress,
1882 * cancel it and make room for the disconnect operation. */
1883 case CAMEL_SERVICE_CONNECTING:
1885 service->priv->connection_op != NULL);
1886 g_cancellable_cancel (
1887 service->priv->connection_op->cancellable);
1888 connection_op_unref (service->priv->connection_op);
1889 service->priv->connection_op = NULL;
1892 /* Start a new disconnect operation. Subsequent disconnect
1893 * operations are queued until this operation completes and
1894 * will share this operation's result. */
1895 case CAMEL_SERVICE_CONNECTED:
1897 service->priv->connection_op == NULL);
1899 op = connection_op_new (simple, cancellable);
1900 service->priv->connection_op = op;
1902 service->priv->status = CAMEL_SERVICE_DISCONNECTING;
1903 service_queue_notify_connection_status (service);
1909 service_shared_disconnect_cb,
1910 connection_op_ref (op));
1913 /* If a disconnect operation is already in progress,
1914 * queue this operation so it completes at the same
1915 * time the first disconnect operation completes. */
1916 case CAMEL_SERVICE_DISCONNECTING:
1917 connection_op_add_pending (
1918 service->priv->connection_op,
1919 simple, cancellable);
1922 /* If we're already disconnected, just report success. */
1923 case CAMEL_SERVICE_DISCONNECTED:
1924 g_simple_async_result_complete_in_idle (simple);
1928 g_warn_if_reached ();
1931 g_mutex_unlock (&service->priv->connection_lock);
1933 g_object_unref (simple);
1937 * camel_service_disconnect_finish:
1938 * @service: a #CamelService
1939 * @result: a #GAsyncResult
1940 * @error: return location for a #GError, or %NULL
1942 * Finishes the operation started with camel_service_disconnect().
1944 * Returns: %TRUE if the connection was severed or %FALSE otherwise
1949 camel_service_disconnect_finish (CamelService *service,
1950 GAsyncResult *result,
1953 GSimpleAsyncResult *simple;
1955 g_return_val_if_fail (
1956 g_simple_async_result_is_valid (
1957 result, G_OBJECT (service), camel_service_disconnect), FALSE);
1959 simple = G_SIMPLE_ASYNC_RESULT (result);
1961 /* Assume success unless a GError is set. */
1962 return !g_simple_async_result_propagate_error (simple, error);
1966 * camel_service_authenticate_sync:
1967 * @service: a #CamelService
1968 * @mechanism: a SASL mechanism name, or %NULL
1969 * @cancellable: optional #GCancellable object, or %NULL
1970 * @error: return location for a #GError, or %NULL
1972 * Attempts to authenticate @service using @mechanism and, if necessary,
1973 * @service's #CamelService:password property. The function makes only
1974 * ONE attempt at authentication and does not loop.
1976 * If the authentication attempt completed and the server accepted the
1977 * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
1979 * If the authentication attempt completed but the server rejected the
1980 * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
1982 * If the authentication attempt failed to complete due to a network
1983 * communication issue or some other mishap, the function sets @error
1984 * and returns #CAMEL_AUTHENTICATION_ERROR.
1986 * Generally this function should only be called from a #CamelSession
1987 * subclass in order to implement its own authentication loop.
1989 * Returns: the authentication result
1993 CamelAuthenticationResult
1994 camel_service_authenticate_sync (CamelService *service,
1995 const gchar *mechanism,
1996 GCancellable *cancellable,
1999 CamelServiceClass *class;
2000 CamelAuthenticationResult result;
2002 g_return_val_if_fail (
2003 CAMEL_IS_SERVICE (service),
2004 CAMEL_AUTHENTICATION_REJECTED);
2006 class = CAMEL_SERVICE_GET_CLASS (service);
2007 g_return_val_if_fail (
2008 class->authenticate_sync != NULL,
2009 CAMEL_AUTHENTICATION_REJECTED);
2011 result = class->authenticate_sync (
2012 service, mechanism, cancellable, error);
2013 CAMEL_CHECK_GERROR (
2014 service, authenticate_sync,
2015 result != CAMEL_AUTHENTICATION_ERROR, error);
2021 * camel_service_authenticate:
2022 * @service: a #CamelService
2023 * @mechanism: a SASL mechanism name, or %NULL
2024 * @io_priority: the I/O priority of the request
2025 * @cancellable: optional #GCancellable object, or %NULL
2026 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2027 * @user_data: data to pass to the callback function
2029 * Asynchronously attempts to authenticate @service using @mechanism and,
2030 * if necessary, @service's #CamelService:password property. The function
2031 * makes only ONE attempt at authentication and does not loop.
2033 * Generally this function should only be called from a #CamelSession
2034 * subclass in order to implement its own authentication loop.
2036 * When the operation is finished, @callback will be called. You can
2037 * then call camel_service_authenticate_finish() to get the result of
2043 camel_service_authenticate (CamelService *service,
2044 const gchar *mechanism,
2046 GCancellable *cancellable,
2047 GAsyncReadyCallback callback,
2050 CamelServiceClass *class;
2052 g_return_if_fail (CAMEL_IS_SERVICE (service));
2054 class = CAMEL_SERVICE_GET_CLASS (service);
2055 g_return_if_fail (class->authenticate != NULL);
2057 class->authenticate (
2058 service, mechanism, io_priority,
2059 cancellable, callback, user_data);
2063 * camel_service_authenticate_finish:
2064 * @service: a #CamelService
2065 * @result: a #GAsyncResult
2066 * @error: return location for a #GError, or %NULL
2068 * Finishes the operation started with camel_service_authenticate().
2070 * If the authentication attempt completed and the server accepted the
2071 * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
2073 * If the authentication attempt completed but the server rejected the
2074 * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
2076 * If the authentication attempt failed to complete due to a network
2077 * communication issue or some other mishap, the function sets @error
2078 * and returns #CAMEL_AUTHENTICATION_ERROR.
2080 * Returns: the authentication result
2084 CamelAuthenticationResult
2085 camel_service_authenticate_finish (CamelService *service,
2086 GAsyncResult *result,
2089 CamelServiceClass *class;
2091 g_return_val_if_fail (
2092 CAMEL_IS_SERVICE (service),
2093 CAMEL_AUTHENTICATION_REJECTED);
2094 g_return_val_if_fail (
2095 G_IS_ASYNC_RESULT (result),
2096 CAMEL_AUTHENTICATION_REJECTED);
2098 class = CAMEL_SERVICE_GET_CLASS (service);
2099 g_return_val_if_fail (
2100 class->authenticate_finish,
2101 CAMEL_AUTHENTICATION_REJECTED);
2103 return class->authenticate_finish (service, result, error);
2107 * camel_service_query_auth_types_sync:
2108 * @service: a #CamelService
2109 * @cancellable: optional #GCancellable object, or %NULL
2110 * @error: return location for a #GError, or %NULL
2112 * Obtains a list of authentication types supported by @service.
2113 * Free the returned list with g_list_free().
2115 * Returns: a list of #CamelServiceAuthType structs
2118 camel_service_query_auth_types_sync (CamelService *service,
2119 GCancellable *cancellable,
2122 CamelServiceClass *class;
2124 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
2126 class = CAMEL_SERVICE_GET_CLASS (service);
2127 g_return_val_if_fail (class->query_auth_types_sync != NULL, NULL);
2129 return class->query_auth_types_sync (service, cancellable, error);
2133 * camel_service_query_auth_types:
2134 * @service: a #CamelService
2135 * @io_priority: the I/O priority of the request
2136 * @cancellable: optional #GCancellable object, or %NULL
2137 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
2138 * @user_data: data to pass to the callback function
2140 * Asynchronously obtains a list of authentication types supported by
2143 * When the operation is finished, @callback will be called. You can
2144 * then call camel_service_query_auth_types_finish() to get the result
2150 camel_service_query_auth_types (CamelService *service,
2152 GCancellable *cancellable,
2153 GAsyncReadyCallback callback,
2156 CamelServiceClass *class;
2158 g_return_if_fail (CAMEL_IS_SERVICE (service));
2160 class = CAMEL_SERVICE_GET_CLASS (service);
2161 g_return_if_fail (class->query_auth_types != NULL);
2163 class->query_auth_types (
2164 service, io_priority,
2165 cancellable, callback, user_data);
2169 * camel_service_query_auth_types_finish:
2170 * @service: a #CamelService
2171 * @result: a #GAsyncResult
2172 * @error: return location for a #GError, or %NULL
2174 * Finishes the operation started with camel_service_query_auth_types().
2175 * Free the returned list with g_list_free().
2177 * Returns: a list of #CamelServiceAuthType structs
2182 camel_service_query_auth_types_finish (CamelService *service,
2183 GAsyncResult *result,
2186 CamelServiceClass *class;
2188 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
2189 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
2191 class = CAMEL_SERVICE_GET_CLASS (service);
2192 g_return_val_if_fail (class->query_auth_types_finish != NULL, NULL);
2194 return class->query_auth_types_finish (service, result, error);