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-local-settings.h"
40 #include "camel-network-settings.h"
41 #include "camel-operation.h"
42 #include "camel-service.h"
43 #include "camel-session.h"
48 #define CAMEL_SERVICE_GET_PRIVATE(obj) \
49 (G_TYPE_INSTANCE_GET_PRIVATE \
50 ((obj), CAMEL_TYPE_SERVICE, CamelServicePrivate))
52 typedef struct _AsyncContext AsyncContext;
54 struct _CamelServicePrivate {
55 gpointer session; /* weak pointer */
57 CamelSettings *settings;
58 CamelProvider *provider;
62 gchar *user_cache_dir;
66 GCancellable *connect_op;
67 CamelServiceConnectionStatus status;
69 GStaticRecMutex connect_lock; /* for locking connection operations */
70 GStaticMutex connect_op_lock; /* for locking the connection_op */
73 struct _AsyncContext {
75 gchar *auth_mechanism;
76 CamelAuthenticationResult auth_result;
89 /* Forward Declarations */
90 static void camel_service_initable_init (GInitableIface *interface);
92 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
93 CamelService, camel_service, CAMEL_TYPE_OBJECT,
94 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, camel_service_initable_init))
97 async_context_free (AsyncContext *async_context)
99 g_list_free (async_context->auth_types);
101 g_free (async_context->auth_mechanism);
103 g_slice_free (AsyncContext, async_context);
107 service_find_old_data_dir (CamelService *service)
109 CamelProvider *provider;
110 CamelSession *session;
113 gboolean allows_host;
114 gboolean allows_user;
118 const gchar *base_dir;
121 provider = camel_service_get_provider (service);
122 session = camel_service_get_session (service);
123 url = camel_service_new_camel_url (service);
125 allows_host = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST);
126 allows_user = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_USER);
128 needs_host = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST);
129 needs_path = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH);
130 needs_user = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER);
132 /* This function reproduces the way service data directories used
133 * to be determined before we moved to just using the UID. If the
134 * old data directory exists, try renaming it to the new form.
136 * A virtual class method was used to determine the directory path,
137 * but no known CamelProviders ever overrode the default algorithm
138 * below. So this should work for everyone. */
140 path = g_string_new (provider->protocol);
143 g_string_append_c (path, '/');
144 if (url->user != NULL)
145 g_string_append (path, url->user);
147 g_string_append_c (path, '@');
148 if (url->host != NULL)
149 g_string_append (path, url->host);
151 g_string_append_c (path, ':');
152 g_string_append_printf (path, "%d", url->port);
154 } else if (!needs_user) {
155 g_string_append_c (path, '@');
158 } else if (allows_host) {
159 g_string_append_c (path, '/');
161 g_string_append_c (path, '@');
162 if (url->host != NULL)
163 g_string_append (path, url->host);
165 g_string_append_c (path, ':');
166 g_string_append_printf (path, "%d", url->port);
170 if (needs_path && url->path) {
171 if (*url->path != '/')
172 g_string_append_c (path, '/');
173 g_string_append (path, url->path);
176 base_dir = camel_session_get_user_data_dir (session);
177 old_data_dir = g_build_filename (base_dir, path->str, NULL);
179 g_string_free (path, TRUE);
181 if (!g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) {
182 g_free (old_data_dir);
186 camel_url_free (url);
192 service_set_provider (CamelService *service,
193 CamelProvider *provider)
195 g_return_if_fail (provider != NULL);
196 g_return_if_fail (service->priv->provider == NULL);
198 service->priv->provider = provider;
202 service_set_session (CamelService *service,
203 CamelSession *session)
205 g_return_if_fail (CAMEL_IS_SESSION (session));
206 g_return_if_fail (service->priv->session == NULL);
208 service->priv->session = session;
210 g_object_add_weak_pointer (
211 G_OBJECT (session), &service->priv->session);
215 service_set_uid (CamelService *service,
218 g_return_if_fail (uid != NULL);
219 g_return_if_fail (service->priv->uid == NULL);
221 service->priv->uid = g_strdup (uid);
225 service_set_property (GObject *object,
230 switch (property_id) {
231 case PROP_DISPLAY_NAME:
232 camel_service_set_display_name (
233 CAMEL_SERVICE (object),
234 g_value_get_string (value));
238 camel_service_set_password (
239 CAMEL_SERVICE (object),
240 g_value_get_string (value));
244 service_set_provider (
245 CAMEL_SERVICE (object),
246 g_value_get_pointer (value));
250 service_set_session (
251 CAMEL_SERVICE (object),
252 g_value_get_object (value));
256 camel_service_set_settings (
257 CAMEL_SERVICE (object),
258 g_value_get_object (value));
263 CAMEL_SERVICE (object),
264 g_value_get_string (value));
268 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
272 service_get_property (GObject *object,
277 switch (property_id) {
278 case PROP_DISPLAY_NAME:
280 value, camel_service_get_display_name (
281 CAMEL_SERVICE (object)));
286 value, camel_service_get_password (
287 CAMEL_SERVICE (object)));
291 g_value_set_pointer (
292 value, camel_service_get_provider (
293 CAMEL_SERVICE (object)));
298 value, camel_service_get_session (
299 CAMEL_SERVICE (object)));
304 value, camel_service_get_settings (
305 CAMEL_SERVICE (object)));
310 value, camel_service_get_uid (
311 CAMEL_SERVICE (object)));
315 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
319 service_dispose (GObject *object)
321 CamelServicePrivate *priv;
323 priv = CAMEL_SERVICE_GET_PRIVATE (object);
325 if (priv->session != NULL) {
326 g_object_remove_weak_pointer (
327 G_OBJECT (priv->session), &priv->session);
328 priv->session = NULL;
331 if (priv->settings != NULL) {
332 g_object_unref (priv->settings);
333 priv->settings = NULL;
336 /* Chain up to parent's dispose() method. */
337 G_OBJECT_CLASS (camel_service_parent_class)->dispose (object);
341 service_finalize (GObject *object)
343 CamelServicePrivate *priv;
345 priv = CAMEL_SERVICE_GET_PRIVATE (object);
347 if (priv->status == CAMEL_SERVICE_CONNECTED)
348 CAMEL_SERVICE_GET_CLASS (object)->disconnect_sync (
349 CAMEL_SERVICE (object), TRUE, NULL, NULL);
351 g_free (priv->display_name);
352 g_free (priv->user_data_dir);
353 g_free (priv->user_cache_dir);
355 g_free (priv->password);
357 g_static_rec_mutex_free (&priv->connect_lock);
358 g_static_mutex_free (&priv->connect_op_lock);
360 /* Chain up to parent's finalize() method. */
361 G_OBJECT_CLASS (camel_service_parent_class)->finalize (object);
365 service_constructed (GObject *object)
367 CamelService *service;
368 CamelSession *session;
369 const gchar *base_dir;
372 /* Chain up to parent's constructed() method. */
373 G_OBJECT_CLASS (camel_service_parent_class)->constructed (object);
375 service = CAMEL_SERVICE (object);
376 session = camel_service_get_session (service);
378 uid = camel_service_get_uid (service);
380 base_dir = camel_session_get_user_data_dir (session);
381 service->priv->user_data_dir = g_build_filename (base_dir, uid, NULL);
383 base_dir = camel_session_get_user_cache_dir (session);
384 service->priv->user_cache_dir = g_build_filename (base_dir, uid, NULL);
388 service_get_name (CamelService *service,
392 "%s does not implement CamelServiceClass::get_name()",
393 G_OBJECT_TYPE_NAME (service));
395 return g_strdup (G_OBJECT_TYPE_NAME (service));
399 service_cancel_connect (CamelService *service)
401 g_cancellable_cancel (service->priv->connect_op);
405 service_connect_sync (CamelService *service,
406 GCancellable *cancellable,
409 /* Things like the CamelMboxStore can validly
410 * not define a connect function. */
415 service_disconnect_sync (CamelService *service,
417 GCancellable *cancellable,
420 /* We let people get away with not having a disconnect
421 * function -- CamelMboxStore, for example. */
426 service_query_auth_types_sync (CamelService *service,
427 GCancellable *cancellable,
434 service_authenticate_thread (GSimpleAsyncResult *simple,
436 GCancellable *cancellable)
438 AsyncContext *async_context;
439 GError *error = NULL;
441 async_context = g_simple_async_result_get_op_res_gpointer (simple);
443 async_context->auth_result = camel_service_authenticate_sync (
444 CAMEL_SERVICE (object), async_context->auth_mechanism,
445 cancellable, &error);
448 g_simple_async_result_take_error (simple, error);
452 service_authenticate (CamelService *service,
453 const gchar *mechanism,
455 GCancellable *cancellable,
456 GAsyncReadyCallback callback,
459 GSimpleAsyncResult *simple;
460 AsyncContext *async_context;
462 async_context = g_slice_new0 (AsyncContext);
463 async_context->auth_mechanism = g_strdup (mechanism);
465 simple = g_simple_async_result_new (
466 G_OBJECT (service), callback, user_data, service_authenticate);
468 g_simple_async_result_set_op_res_gpointer (
469 simple, async_context, (GDestroyNotify) async_context_free);
471 g_simple_async_result_run_in_thread (
472 simple, service_authenticate_thread, io_priority, cancellable);
474 g_object_unref (simple);
477 static CamelAuthenticationResult
478 service_authenticate_finish (CamelService *service,
479 GAsyncResult *result,
482 GSimpleAsyncResult *simple;
483 AsyncContext *async_context;
485 g_return_val_if_fail (
486 g_simple_async_result_is_valid (
487 result, G_OBJECT (service), service_authenticate),
488 CAMEL_AUTHENTICATION_REJECTED);
490 simple = G_SIMPLE_ASYNC_RESULT (result);
491 async_context = g_simple_async_result_get_op_res_gpointer (simple);
493 if (g_simple_async_result_propagate_error (simple, error))
494 return CAMEL_AUTHENTICATION_ERROR;
496 return async_context->auth_result;
500 service_query_auth_types_thread (GSimpleAsyncResult *simple,
502 GCancellable *cancellable)
504 AsyncContext *async_context;
505 GError *error = NULL;
507 async_context = g_simple_async_result_get_op_res_gpointer (simple);
509 async_context->auth_types = camel_service_query_auth_types_sync (
510 CAMEL_SERVICE (object), cancellable, &error);
513 g_simple_async_result_take_error (simple, error);
517 service_query_auth_types (CamelService *service,
519 GCancellable *cancellable,
520 GAsyncReadyCallback callback,
523 GSimpleAsyncResult *simple;
524 AsyncContext *async_context;
526 async_context = g_slice_new0 (AsyncContext);
528 simple = g_simple_async_result_new (
529 G_OBJECT (service), callback,
530 user_data, service_query_auth_types);
532 g_simple_async_result_set_op_res_gpointer (
533 simple, async_context, (GDestroyNotify) async_context_free);
535 g_simple_async_result_run_in_thread (
536 simple, service_query_auth_types_thread,
537 io_priority, cancellable);
539 g_object_unref (simple);
543 service_query_auth_types_finish (CamelService *service,
544 GAsyncResult *result,
547 GSimpleAsyncResult *simple;
548 AsyncContext *async_context;
550 g_return_val_if_fail (
551 g_simple_async_result_is_valid (
552 result, G_OBJECT (service),
553 service_query_auth_types), NULL);
555 simple = G_SIMPLE_ASYNC_RESULT (result);
556 async_context = g_simple_async_result_get_op_res_gpointer (simple);
558 if (g_simple_async_result_propagate_error (simple, error))
561 return g_list_copy (async_context->auth_types);
565 service_initable_init (GInitable *initable,
566 GCancellable *cancellable,
569 /* Nothing to do here, but we may need add something in the future.
570 * For now this is a placeholder so subclasses can safely chain up. */
576 camel_service_class_init (CamelServiceClass *class)
578 GObjectClass *object_class;
580 g_type_class_add_private (class, sizeof (CamelServicePrivate));
582 object_class = G_OBJECT_CLASS (class);
583 object_class->set_property = service_set_property;
584 object_class->get_property = service_get_property;
585 object_class->dispose = service_dispose;
586 object_class->finalize = service_finalize;
587 object_class->constructed = service_constructed;
589 class->settings_type = CAMEL_TYPE_SETTINGS;
590 class->get_name = service_get_name;
591 class->cancel_connect = service_cancel_connect;
592 class->connect_sync = service_connect_sync;
593 class->disconnect_sync = service_disconnect_sync;
594 class->query_auth_types_sync = service_query_auth_types_sync;
596 class->authenticate = service_authenticate;
597 class->authenticate_finish = service_authenticate_finish;
598 class->query_auth_types = service_query_auth_types;
599 class->query_auth_types_finish = service_query_auth_types_finish;
601 g_object_class_install_property (
604 g_param_spec_string (
607 "The display name for the service",
611 G_PARAM_STATIC_STRINGS));
613 g_object_class_install_property (
616 g_param_spec_string (
619 "The password for the service",
623 G_PARAM_STATIC_STRINGS));
625 g_object_class_install_property (
628 g_param_spec_pointer (
631 "The CamelProvider for the service",
633 G_PARAM_CONSTRUCT_ONLY |
634 G_PARAM_STATIC_STRINGS));
636 g_object_class_install_property (
639 g_param_spec_object (
642 "A CamelSession instance",
645 G_PARAM_CONSTRUCT_ONLY |
646 G_PARAM_STATIC_STRINGS));
648 g_object_class_install_property (
651 g_param_spec_object (
654 "A CamelSettings instance",
658 G_PARAM_STATIC_STRINGS));
660 g_object_class_install_property (
663 g_param_spec_string (
666 "The unique identity of the service",
669 G_PARAM_CONSTRUCT_ONLY |
670 G_PARAM_STATIC_STRINGS));
674 camel_service_initable_init (GInitableIface *interface)
676 interface->init = service_initable_init;
680 camel_service_init (CamelService *service)
682 service->priv = CAMEL_SERVICE_GET_PRIVATE (service);
684 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
686 g_static_rec_mutex_init (&service->priv->connect_lock);
687 g_static_mutex_init (&service->priv->connect_op_lock);
691 camel_service_error_quark (void)
693 static GQuark quark = 0;
695 if (G_UNLIKELY (quark == 0)) {
696 const gchar *string = "camel-service-error-quark";
697 quark = g_quark_from_static_string (string);
704 * camel_service_migrate_files:
705 * @service: a #CamelService
707 * Performs any necessary file migrations for @service. This should be
708 * called after installing or configuring the @service's #CamelSettings,
709 * since it requires building a URL string for @service.
714 camel_service_migrate_files (CamelService *service)
716 const gchar *new_data_dir;
719 g_return_if_fail (CAMEL_IS_SERVICE (service));
721 new_data_dir = camel_service_get_user_data_dir (service);
722 old_data_dir = service_find_old_data_dir (service);
724 /* If the old data directory name exists, try renaming
725 * it to the new data directory. Failure is non-fatal. */
726 if (old_data_dir != NULL) {
727 g_rename (old_data_dir, new_data_dir);
728 g_free (old_data_dir);
733 * camel_service_new_camel_url:
734 * @service: a #CamelService
736 * Returns a new #CamelURL representing @service.
737 * Free the returned #CamelURL with camel_url_free().
739 * Returns: a new #CamelURL
744 camel_service_new_camel_url (CamelService *service)
747 CamelProvider *provider;
748 CamelSettings *settings;
754 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
756 provider = camel_service_get_provider (service);
757 settings = camel_service_get_settings (service);
759 g_return_val_if_fail (provider != NULL, NULL);
761 /* Allocate as camel_url_new_with_base() does. */
762 url = g_new0 (CamelURL, 1);
764 if (CAMEL_IS_NETWORK_SETTINGS (settings)) {
765 CamelNetworkSettings *network_settings;
767 network_settings = CAMEL_NETWORK_SETTINGS (settings);
768 host = camel_network_settings_dup_host (network_settings);
769 port = camel_network_settings_get_port (network_settings);
770 user = camel_network_settings_dup_user (network_settings);
773 if (CAMEL_IS_LOCAL_SETTINGS (settings)) {
774 CamelLocalSettings *local_settings;
776 local_settings = CAMEL_LOCAL_SETTINGS (settings);
777 path = camel_local_settings_dup_path (local_settings);
780 camel_url_set_protocol (url, provider->protocol);
781 camel_url_set_host (url, host);
782 camel_url_set_port (url, port);
783 camel_url_set_user (url, user);
784 camel_url_set_path (url, path);
794 * camel_service_get_display_name:
795 * @service: a #CamelService
797 * Returns the display name for @service, or %NULL if @service has not
798 * been given a display name. The display name is intended for use in
799 * a user interface and should generally be given a user-defined name.
801 * Compare this with camel_service_get_name(), which returns a built-in
802 * description of the type of service (IMAP, SMTP, etc.).
804 * Returns: the display name for @service, or %NULL
809 camel_service_get_display_name (CamelService *service)
811 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
813 return service->priv->display_name;
817 * camel_service_set_display_name:
818 * @service: a #CamelService
819 * @display_name: a valid UTF-8 string, or %NULL
821 * Assigns a UTF-8 display name to @service. The display name is intended
822 * for use in a user interface and should generally be given a user-defined
825 * Compare this with camel_service_get_name(), which returns a built-in
826 * description of the type of service (IMAP, SMTP, etc.).
831 camel_service_set_display_name (CamelService *service,
832 const gchar *display_name)
834 g_return_if_fail (CAMEL_IS_SERVICE (service));
836 if (display_name != NULL)
837 g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
839 g_free (service->priv->display_name);
840 service->priv->display_name = g_strdup (display_name);
842 g_object_notify (G_OBJECT (service), "display-name");
846 * camel_service_get_password:
847 * @service: a #CamelService
849 * Returns the password for @service. Some SASL mechanisms use this
850 * when attempting to authenticate.
852 * Returns: the password for @service
857 camel_service_get_password (CamelService *service)
859 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
861 return service->priv->password;
865 * camel_service_set_password:
866 * @service: a #CamelService
867 * @password: the password for @service
869 * Sets the password for @service. Use this function to cache the password
870 * in memory after obtaining it through camel_session_get_password(). Some
871 * SASL mechanisms use this when attempting to authenticate.
876 camel_service_set_password (CamelService *service,
877 const gchar *password)
879 g_return_if_fail (CAMEL_IS_SERVICE (service));
881 g_free (service->priv->password);
882 service->priv->password = g_strdup (password);
884 g_object_notify (G_OBJECT (service), "password");
888 * camel_service_get_user_data_dir:
889 * @service: a #CamelService
891 * Returns the base directory under which to store user-specific data
892 * for @service. The directory is formed by appending the directory
893 * returned by camel_session_get_user_data_dir() with the service's
894 * #CamelService:uid value.
896 * Returns: the base directory for @service
901 camel_service_get_user_data_dir (CamelService *service)
903 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
905 return service->priv->user_data_dir;
909 * camel_service_get_user_cache_dir:
910 * @service: a #CamelService
912 * Returns the base directory under which to store cache data
913 * for @service. The directory is formed by appending the directory
914 * returned by camel_session_get_user_cache_dir() with the service's
915 * #CamelService:uid value.
917 * Returns: the base cache directory for @service
922 camel_service_get_user_cache_dir (CamelService *service)
924 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
926 return service->priv->user_cache_dir;
930 * camel_service_get_name:
931 * @service: a #CamelService
932 * @brief: whether or not to use a briefer form
934 * This gets the name of the service in a "friendly" (suitable for
935 * humans) form. If @brief is %TRUE, this should be a brief description
936 * such as for use in the folder tree. If @brief is %FALSE, it should
937 * be a more complete and mostly unambiguous description.
939 * Returns: a description of the service which the caller must free
942 camel_service_get_name (CamelService *service,
945 CamelServiceClass *class;
947 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
949 class = CAMEL_SERVICE_GET_CLASS (service);
950 g_return_val_if_fail (class->get_name != NULL, NULL);
952 return class->get_name (service, brief);
956 * camel_service_get_provider:
957 * @service: a #CamelService
959 * Gets the #CamelProvider associated with the service.
961 * Returns: the #CamelProvider
964 camel_service_get_provider (CamelService *service)
966 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
968 return service->priv->provider;
972 * camel_service_get_session:
973 * @service: a #CamelService
975 * Gets the #CamelSession associated with the service.
977 * Returns: the #CamelSession
980 camel_service_get_session (CamelService *service)
982 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
984 return CAMEL_SESSION (service->priv->session);
988 * camel_service_get_settings:
989 * @service: a #CamelService
991 * Returns the #CamelSettings instance associated with the service.
993 * Returns: the #CamelSettings
998 camel_service_get_settings (CamelService *service)
1000 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1002 /* Every service should have a settings object. */
1003 g_warn_if_fail (service->priv->settings != NULL);
1005 return service->priv->settings;
1009 * camel_service_set_settings:
1010 * @service: a #CamelService
1011 * @settings: an instance derviced from #CamelSettings, or %NULL
1013 * Associates a new #CamelSettings instance with the service.
1014 * The @settings instance must match the settings type defined in
1015 * #CamelServiceClass. If @settings is %NULL, a new #CamelSettings
1016 * instance of the appropriate type is created with all properties
1022 camel_service_set_settings (CamelService *service,
1023 CamelSettings *settings)
1025 CamelServiceClass *class;
1027 g_return_if_fail (CAMEL_IS_SERVICE (service));
1029 class = CAMEL_SERVICE_GET_CLASS (service);
1031 if (settings != NULL) {
1034 G_OBJECT_TYPE (settings),
1035 class->settings_type));
1036 g_object_ref (settings);
1041 class->settings_type,
1042 CAMEL_TYPE_SETTINGS));
1043 settings = g_object_new (class->settings_type, NULL);
1046 if (service->priv->settings != NULL)
1047 g_object_unref (service->priv->settings);
1049 service->priv->settings = settings;
1051 g_object_notify (G_OBJECT (service), "settings");
1055 * camel_service_get_uid:
1056 * @service: a #CamelService
1058 * Gets the unique identifier string associated with the service.
1060 * Returns: the UID string
1065 camel_service_get_uid (CamelService *service)
1067 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1069 return service->priv->uid;
1073 * camel_service_cancel_connect:
1074 * @service: a #CamelService
1076 * If @service is currently attempting to connect to or disconnect
1077 * from a server, this causes it to stop and fail. Otherwise it is a
1081 camel_service_cancel_connect (CamelService *service)
1083 CamelServiceClass *class;
1085 g_return_if_fail (CAMEL_IS_SERVICE (service));
1087 class = CAMEL_SERVICE_GET_CLASS (service);
1088 g_return_if_fail (class->cancel_connect != NULL);
1090 camel_service_lock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1091 if (service->priv->connect_op)
1092 class->cancel_connect (service);
1093 camel_service_unlock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1097 * camel_service_connect_sync:
1098 * @service: a #CamelService
1099 * @error: return location for a #GError, or %NULL
1101 * Connect to the service using the parameters it was initialized
1104 * Returns: %TRUE if the connection is made or %FALSE otherwise
1107 camel_service_connect_sync (CamelService *service,
1110 CamelServiceClass *class;
1112 gboolean ret = FALSE;
1114 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1115 g_return_val_if_fail (service->priv->session != NULL, FALSE);
1117 class = CAMEL_SERVICE_GET_CLASS (service);
1118 g_return_val_if_fail (class->connect_sync != NULL, FALSE);
1120 camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1122 if (service->priv->status == CAMEL_SERVICE_CONNECTED) {
1123 camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1127 /* Register a separate operation for connecting, so that
1128 * the offline code can cancel it. */
1129 camel_service_lock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1130 service->priv->connect_op = camel_operation_new ();
1131 op = service->priv->connect_op;
1132 camel_service_unlock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1134 service->priv->status = CAMEL_SERVICE_CONNECTING;
1135 ret = class->connect_sync (service, service->priv->connect_op, error);
1136 CAMEL_CHECK_GERROR (service, connect_sync, ret, error);
1137 service->priv->status =
1138 ret ? CAMEL_SERVICE_CONNECTED : CAMEL_SERVICE_DISCONNECTED;
1140 camel_service_lock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1141 g_object_unref (op);
1142 if (op == service->priv->connect_op)
1143 service->priv->connect_op = NULL;
1144 camel_service_unlock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1146 camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1152 * camel_service_disconnect_sync:
1153 * @service: a #CamelService
1154 * @clean: whether or not to try to disconnect cleanly
1155 * @error: return location for a #GError, or %NULL
1157 * Disconnect from the service. If @clean is %FALSE, it should not
1158 * try to do any synchronizing or other cleanup of the connection.
1160 * Returns: %TRUE if the disconnect was successful or %FALSE otherwise
1163 camel_service_disconnect_sync (CamelService *service,
1167 CamelServiceClass *class;
1168 gboolean res = TRUE;
1170 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1172 class = CAMEL_SERVICE_GET_CLASS (service);
1173 g_return_val_if_fail (class->disconnect_sync != NULL, FALSE);
1175 camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1177 if (service->priv->status != CAMEL_SERVICE_DISCONNECTED
1178 && service->priv->status != CAMEL_SERVICE_DISCONNECTING) {
1180 camel_service_lock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1181 service->priv->connect_op = camel_operation_new ();
1182 op = service->priv->connect_op;
1183 camel_service_unlock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1185 service->priv->status = CAMEL_SERVICE_DISCONNECTING;
1186 res = class->disconnect_sync (
1187 service, clean, service->priv->connect_op, error);
1188 CAMEL_CHECK_GERROR (service, disconnect_sync, res, error);
1189 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
1191 camel_service_lock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1192 g_object_unref (op);
1193 if (op == service->priv->connect_op)
1194 service->priv->connect_op = NULL;
1195 camel_service_unlock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1198 camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1200 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
1206 * camel_service_get_connection_status:
1207 * @service: a #CamelService
1209 * Returns the connection status for @service.
1211 * Returns: the connection status
1215 CamelServiceConnectionStatus
1216 camel_service_get_connection_status (CamelService *service)
1218 g_return_val_if_fail (
1219 CAMEL_IS_SERVICE (service), CAMEL_SERVICE_DISCONNECTED);
1221 return service->priv->status;
1225 * camel_service_lock:
1226 * @service: a #CamelService
1227 * @lock: lock type to lock
1229 * Locks @service's @lock. Unlock it with camel_service_unlock().
1234 camel_service_lock (CamelService *service,
1235 CamelServiceLock lock)
1237 g_return_if_fail (CAMEL_IS_SERVICE (service));
1240 case CAMEL_SERVICE_REC_CONNECT_LOCK:
1241 g_static_rec_mutex_lock (&service->priv->connect_lock);
1243 case CAMEL_SERVICE_CONNECT_OP_LOCK:
1244 g_static_mutex_lock (&service->priv->connect_op_lock);
1247 g_return_if_reached ();
1252 * camel_service_unlock:
1253 * @service: a #CamelService
1254 * @lock: lock type to unlock
1256 * Unlocks @service's @lock, previously locked with camel_service_lock().
1261 camel_service_unlock (CamelService *service,
1262 CamelServiceLock lock)
1264 g_return_if_fail (CAMEL_IS_SERVICE (service));
1267 case CAMEL_SERVICE_REC_CONNECT_LOCK:
1268 g_static_rec_mutex_unlock (&service->priv->connect_lock);
1270 case CAMEL_SERVICE_CONNECT_OP_LOCK:
1271 g_static_mutex_unlock (&service->priv->connect_op_lock);
1274 g_return_if_reached ();
1279 * camel_service_authenticate_sync:
1280 * @service: a #CamelService
1281 * @mechanism: a SASL mechanism name, or %NULL
1282 * @cancellable: optional #GCancellable object, or %NULL
1283 * @error: return location for a #GError, or %NULL
1285 * Attempts to authenticate @service using @mechanism and, if necessary,
1286 * @service's #CamelService:password property. The function makes only
1287 * ONE attempt at authentication and does not loop.
1289 * If the authentication attempt completed and the server accepted the
1290 * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
1292 * If the authentication attempt completed but the server rejected the
1293 * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
1295 * If the authentication attempt failed to complete due to a network
1296 * communication issue or some other mishap, the function sets @error
1297 * and returns #CAMEL_AUTHENTICATION_ERROR.
1299 * Generally this function should only be called from a #CamelSession
1300 * subclass in order to implement its own authentication loop.
1302 * Returns: the authentication result
1306 CamelAuthenticationResult
1307 camel_service_authenticate_sync (CamelService *service,
1308 const gchar *mechanism,
1309 GCancellable *cancellable,
1312 CamelServiceClass *class;
1313 CamelAuthenticationResult result;
1315 g_return_val_if_fail (
1316 CAMEL_IS_SERVICE (service),
1317 CAMEL_AUTHENTICATION_REJECTED);
1319 class = CAMEL_SERVICE_GET_CLASS (service);
1320 g_return_val_if_fail (
1321 class->authenticate_sync != NULL,
1322 CAMEL_AUTHENTICATION_REJECTED);
1324 result = class->authenticate_sync (
1325 service, mechanism, cancellable, error);
1326 CAMEL_CHECK_GERROR (
1327 service, authenticate_sync,
1328 result != CAMEL_AUTHENTICATION_ERROR, error);
1334 * camel_service_authenticate:
1335 * @service: a #CamelService
1336 * @mechanism: a SASL mechanism name, or %NULL
1337 * @io_priority: the I/O priority of the request
1338 * @cancellable: optional #GCancellable object, or %NULL
1339 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1340 * @user_data: data to pass to the callback function
1342 * Asynchronously attempts to authenticate @service using @mechanism and,
1343 * if necessary, @service's #CamelService:password property. The function
1344 * makes only ONE attempt at authentication and does not loop.
1346 * Generally this function should only be called from a #CamelSession
1347 * subclass in order to implement its own authentication loop.
1349 * When the operation is finished, @callback will be called. You can
1350 * then call camel_service_authenticate_finish() to get the result of
1356 camel_service_authenticate (CamelService *service,
1357 const gchar *mechanism,
1359 GCancellable *cancellable,
1360 GAsyncReadyCallback callback,
1363 CamelServiceClass *class;
1365 g_return_if_fail (CAMEL_IS_SERVICE (service));
1367 class = CAMEL_SERVICE_GET_CLASS (service);
1368 g_return_if_fail (class->authenticate != NULL);
1370 class->authenticate (
1371 service, mechanism, io_priority,
1372 cancellable, callback, user_data);
1376 * camel_service_authenticate_finish:
1377 * @service: a #CamelService
1378 * @result: a #GAsyncResult
1379 * @error: return location for a #GError, or %NULL
1381 * Finishes the operation started with camel_service_authenticate().
1383 * If the authentication attempt completed and the server accepted the
1384 * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
1386 * If the authentication attempt completed but the server rejected the
1387 * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
1389 * If the authentication attempt failed to complete due to a network
1390 * communication issue or some other mishap, the function sets @error
1391 * and returns #CAMEL_AUTHENTICATION_ERROR.
1393 * Returns: the authentication result
1397 CamelAuthenticationResult
1398 camel_service_authenticate_finish (CamelService *service,
1399 GAsyncResult *result,
1402 CamelServiceClass *class;
1404 g_return_val_if_fail (
1405 CAMEL_IS_SERVICE (service),
1406 CAMEL_AUTHENTICATION_REJECTED);
1407 g_return_val_if_fail (
1408 G_IS_ASYNC_RESULT (result),
1409 CAMEL_AUTHENTICATION_REJECTED);
1411 class = CAMEL_SERVICE_GET_CLASS (service);
1412 g_return_val_if_fail (
1413 class->authenticate_finish,
1414 CAMEL_AUTHENTICATION_REJECTED);
1416 return class->authenticate_finish (service, result, error);
1420 * camel_service_query_auth_types_sync:
1421 * @service: a #CamelService
1422 * @cancellable: optional #GCancellable object, or %NULL
1423 * @error: return location for a #GError, or %NULL
1425 * Obtains a list of authentication types supported by @service.
1426 * Free the returned list with g_list_free().
1428 * Returns: a list of #CamelServiceAuthType structs
1431 camel_service_query_auth_types_sync (CamelService *service,
1432 GCancellable *cancellable,
1435 CamelServiceClass *class;
1438 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1440 class = CAMEL_SERVICE_GET_CLASS (service);
1441 g_return_val_if_fail (class->query_auth_types_sync != NULL, NULL);
1443 /* Note that we get the connect lock here, which means the
1444 * callee must not call the connect functions itself. */
1445 camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1446 list = class->query_auth_types_sync (service, cancellable, error);
1447 camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1453 * camel_service_query_auth_types:
1454 * @service: a #CamelService
1455 * @io_priority: the I/O priority of the request
1456 * @cancellable: optional #GCancellable object, or %NULL
1457 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1458 * @user_data: data to pass to the callback function
1460 * Asynchronously obtains a list of authentication types supported by
1463 * When the operation is finished, @callback will be called. You can
1464 * then call camel_service_query_auth_types_finish() to get the result
1470 camel_service_query_auth_types (CamelService *service,
1472 GCancellable *cancellable,
1473 GAsyncReadyCallback callback,
1476 CamelServiceClass *class;
1478 g_return_if_fail (CAMEL_IS_SERVICE (service));
1480 class = CAMEL_SERVICE_GET_CLASS (service);
1481 g_return_if_fail (class->query_auth_types != NULL);
1483 class->query_auth_types (
1484 service, io_priority,
1485 cancellable, callback, user_data);
1489 * camel_service_query_auth_types_finish:
1490 * @service: a #CamelService
1491 * @result: a #GAsyncResult
1492 * @error: return location for a #GError, or %NULL
1494 * Finishes the operation started with camel_service_query_auth_types().
1495 * Free the returned list with g_list_free().
1497 * Returns: a list of #CamelServiceAuthType structs
1502 camel_service_query_auth_types_finish (CamelService *service,
1503 GAsyncResult *result,
1506 CamelServiceClass *class;
1508 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1509 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1511 class = CAMEL_SERVICE_GET_CLASS (service);
1512 g_return_val_if_fail (class->query_auth_types_finish != NULL, NULL);
1514 return class->query_auth_types_finish (service, result, error);