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 <libedataserver/e-data-server-util.h>
40 #include "camel-debug.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;
65 GCancellable *connect_op;
66 CamelServiceConnectionStatus status;
68 GStaticRecMutex connect_lock; /* for locking connection operations */
69 GStaticMutex connect_op_lock; /* for locking the connection_op */
72 struct _AsyncContext {
86 /* Forward Declarations */
87 static void camel_service_initable_init (GInitableIface *interface);
89 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (
90 CamelService, camel_service, CAMEL_TYPE_OBJECT,
91 G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, camel_service_initable_init))
94 async_context_free (AsyncContext *async_context)
96 g_list_free (async_context->auth_types);
98 g_slice_free (AsyncContext, async_context);
102 service_find_old_data_dir (CamelService *service)
104 CamelProvider *provider;
105 CamelSession *session;
108 gboolean allows_host;
109 gboolean allows_user;
113 const gchar *base_dir;
116 provider = camel_service_get_provider (service);
117 session = camel_service_get_session (service);
118 url = camel_service_get_camel_url (service);
120 allows_host = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST);
121 allows_user = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_USER);
123 needs_host = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST);
124 needs_path = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH);
125 needs_user = CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER);
127 /* This function reproduces the way service data directories used
128 * to be determined before we moved to just using the UID. If the
129 * old data directory exists, try renaming it to the new form.
131 * A virtual class method was used to determine the directory path,
132 * but no known CamelProviders ever overrode the default algorithm
133 * below. So this should work for everyone. */
135 path = g_string_new (provider->protocol);
138 g_string_append_c (path, '/');
139 if (url->user != NULL)
140 g_string_append (path, url->user);
142 g_string_append_c (path, '@');
143 if (url->host != NULL)
144 g_string_append (path, url->host);
146 g_string_append_c (path, ':');
147 g_string_append_printf (path, "%d", url->port);
149 } else if (!needs_user) {
150 g_string_append_c (path, '@');
153 } else if (allows_host) {
154 g_string_append_c (path, '/');
156 g_string_append_c (path, '@');
157 if (url->host != NULL)
158 g_string_append (path, url->host);
160 g_string_append_c (path, ':');
161 g_string_append_printf (path, "%d", url->port);
166 if (*url->path != '/')
167 g_string_append_c (path, '/');
168 g_string_append (path, url->path);
171 base_dir = camel_session_get_user_data_dir (session);
172 old_data_dir = g_build_filename (base_dir, path->str, NULL);
174 g_string_free (path, TRUE);
176 if (!g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) {
177 g_free (old_data_dir);
185 service_set_provider (CamelService *service,
186 CamelProvider *provider)
188 g_return_if_fail (provider != NULL);
189 g_return_if_fail (service->priv->provider == NULL);
191 service->priv->provider = provider;
195 service_set_session (CamelService *service,
196 CamelSession *session)
198 g_return_if_fail (CAMEL_IS_SESSION (session));
199 g_return_if_fail (service->priv->session == NULL);
201 service->priv->session = session;
203 g_object_add_weak_pointer (
204 G_OBJECT (session), &service->priv->session);
208 service_set_uid (CamelService *service,
211 g_return_if_fail (uid != NULL);
212 g_return_if_fail (service->priv->uid == NULL);
214 service->priv->uid = g_strdup (uid);
218 service_set_url (CamelService *service,
221 g_return_if_fail (url != NULL);
222 g_return_if_fail (service->priv->url == NULL);
224 service->priv->url = camel_url_copy (url);
228 service_set_property (GObject *object,
233 switch (property_id) {
234 case PROP_DISPLAY_NAME:
235 camel_service_set_display_name (
236 CAMEL_SERVICE (object),
237 g_value_get_string (value));
241 service_set_provider (
242 CAMEL_SERVICE (object),
243 g_value_get_pointer (value));
247 service_set_session (
248 CAMEL_SERVICE (object),
249 g_value_get_object (value));
253 camel_service_set_settings (
254 CAMEL_SERVICE (object),
255 g_value_get_object (value));
260 CAMEL_SERVICE (object),
261 g_value_get_string (value));
266 CAMEL_SERVICE (object),
267 g_value_get_boxed (value));
271 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
275 service_get_property (GObject *object,
280 switch (property_id) {
281 case PROP_DISPLAY_NAME:
283 value, camel_service_get_display_name (
284 CAMEL_SERVICE (object)));
288 g_value_set_pointer (
289 value, camel_service_get_provider (
290 CAMEL_SERVICE (object)));
295 value, camel_service_get_session (
296 CAMEL_SERVICE (object)));
301 value, camel_service_get_settings (
302 CAMEL_SERVICE (object)));
307 value, camel_service_get_uid (
308 CAMEL_SERVICE (object)));
313 value, camel_service_get_url (
314 CAMEL_SERVICE (object)));
318 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
322 service_dispose (GObject *object)
324 CamelServicePrivate *priv;
326 priv = CAMEL_SERVICE_GET_PRIVATE (object);
328 if (priv->session != NULL) {
329 g_object_remove_weak_pointer (
330 G_OBJECT (priv->session), &priv->session);
331 priv->session = NULL;
334 if (priv->settings != NULL) {
335 g_object_unref (priv->settings);
336 priv->settings = NULL;
339 /* Chain up to parent's dispose() method. */
340 G_OBJECT_CLASS (camel_service_parent_class)->dispose (object);
344 service_finalize (GObject *object)
346 CamelServicePrivate *priv;
348 priv = CAMEL_SERVICE_GET_PRIVATE (object);
350 if (priv->status == CAMEL_SERVICE_CONNECTED)
351 CAMEL_SERVICE_GET_CLASS (object)->disconnect_sync (
352 CAMEL_SERVICE (object), TRUE, NULL, NULL);
354 if (priv->url != NULL)
355 camel_url_free (priv->url);
357 g_free (priv->display_name);
358 g_free (priv->user_data_dir);
361 g_static_rec_mutex_free (&priv->connect_lock);
362 g_static_mutex_free (&priv->connect_op_lock);
364 /* Chain up to parent's finalize() method. */
365 G_OBJECT_CLASS (camel_service_parent_class)->finalize (object);
369 service_constructed (GObject *object)
371 CamelService *service;
372 CamelSession *session;
373 const gchar *base_data_dir;
376 /* Chain up to parent's constructed() method. */
377 G_OBJECT_CLASS (camel_service_parent_class)->constructed (object);
379 service = CAMEL_SERVICE (object);
380 session = camel_service_get_session (service);
382 uid = camel_service_get_uid (service);
383 base_data_dir = camel_session_get_user_data_dir (session);
385 service->priv->user_data_dir =
386 g_build_filename (base_data_dir, uid, NULL);
390 service_get_name (CamelService *service,
394 "%s does not implement CamelServiceClass::get_name()",
395 G_OBJECT_TYPE_NAME (service));
397 return g_strdup (G_OBJECT_TYPE_NAME (service));
401 service_cancel_connect (CamelService *service)
403 g_cancellable_cancel (service->priv->connect_op);
407 service_connect_sync (CamelService *service,
408 GCancellable *cancellable,
411 /* Things like the CamelMboxStore can validly
412 * not define a connect function. */
417 service_disconnect_sync (CamelService *service,
419 GCancellable *cancellable,
422 /* We let people get away with not having a disconnect
423 * function -- CamelMboxStore, for example. */
428 service_query_auth_types_sync (CamelService *service,
429 GCancellable *cancellable,
436 service_query_auth_types_thread (GSimpleAsyncResult *simple,
438 GCancellable *cancellable)
440 AsyncContext *async_context;
441 GError *error = NULL;
443 async_context = g_simple_async_result_get_op_res_gpointer (simple);
445 async_context->auth_types = camel_service_query_auth_types_sync (
446 CAMEL_SERVICE (object), cancellable, &error);
449 g_simple_async_result_set_from_error (simple, error);
450 g_error_free (error);
455 service_query_auth_types (CamelService *service,
457 GCancellable *cancellable,
458 GAsyncReadyCallback callback,
461 GSimpleAsyncResult *simple;
462 AsyncContext *async_context;
464 async_context = g_slice_new0 (AsyncContext);
466 simple = g_simple_async_result_new (
467 G_OBJECT (service), callback,
468 user_data, service_query_auth_types);
470 g_simple_async_result_set_op_res_gpointer (
471 simple, async_context, (GDestroyNotify) async_context_free);
473 g_simple_async_result_run_in_thread (
474 simple, service_query_auth_types_thread,
475 io_priority, cancellable);
477 g_object_unref (simple);
481 service_query_auth_types_finish (CamelService *service,
482 GAsyncResult *result,
485 GSimpleAsyncResult *simple;
486 AsyncContext *async_context;
488 g_return_val_if_fail (
489 g_simple_async_result_is_valid (
490 result, G_OBJECT (service),
491 service_query_auth_types), NULL);
493 simple = G_SIMPLE_ASYNC_RESULT (result);
494 async_context = g_simple_async_result_get_op_res_gpointer (simple);
496 if (g_simple_async_result_propagate_error (simple, error))
499 return g_list_copy (async_context->auth_types);
503 service_initable_init (GInitable *initable,
504 GCancellable *cancellable,
507 CamelProvider *provider;
508 CamelService *service;
510 gboolean success = FALSE;
511 const gchar *new_data_dir;
515 service = CAMEL_SERVICE (initable);
516 url = camel_service_get_camel_url (service);
517 provider = camel_service_get_provider (service);
519 url_string = camel_url_to_string (url, CAMEL_URL_HIDE_PASSWORD);
521 if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_USER)) {
522 if (url->user == NULL || *url->user == '\0') {
524 error, CAMEL_SERVICE_ERROR,
525 CAMEL_SERVICE_ERROR_URL_INVALID,
526 _("URL '%s' needs a user component"),
532 if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_HOST)) {
533 if (url->host == NULL || *url->host == '\0') {
535 error, CAMEL_SERVICE_ERROR,
536 CAMEL_SERVICE_ERROR_URL_INVALID,
537 _("URL '%s' needs a host component"),
543 if (CAMEL_PROVIDER_NEEDS (provider, CAMEL_URL_PART_PATH)) {
544 if (url->path == NULL || *url->path == '\0') {
546 error, CAMEL_SERVICE_ERROR,
547 CAMEL_SERVICE_ERROR_URL_INVALID,
548 _("URL '%s' needs a path component"),
554 new_data_dir = camel_service_get_user_data_dir (service);
555 old_data_dir = service_find_old_data_dir (service);
557 /* If the old data directory name exists, try renaming
558 * it to the new data directory. Failure is non-fatal. */
559 if (old_data_dir != NULL) {
560 g_rename (old_data_dir, new_data_dir);
561 g_free (old_data_dir);
573 camel_service_class_init (CamelServiceClass *class)
575 GObjectClass *object_class;
577 g_type_class_add_private (class, sizeof (CamelServicePrivate));
579 object_class = G_OBJECT_CLASS (class);
580 object_class->set_property = service_set_property;
581 object_class->get_property = service_get_property;
582 object_class->dispose = service_dispose;
583 object_class->finalize = service_finalize;
584 object_class->constructed = service_constructed;
586 class->settings_type = CAMEL_TYPE_SETTINGS;
587 class->get_name = service_get_name;
588 class->cancel_connect = service_cancel_connect;
589 class->connect_sync = service_connect_sync;
590 class->disconnect_sync = service_disconnect_sync;
591 class->query_auth_types_sync = service_query_auth_types_sync;
593 class->query_auth_types = service_query_auth_types;
594 class->query_auth_types_finish = service_query_auth_types_finish;
596 g_object_class_install_property (
599 g_param_spec_string (
602 "The display name for the service",
606 G_PARAM_STATIC_STRINGS));
608 g_object_class_install_property (
611 g_param_spec_pointer (
614 "The CamelProvider for the service",
616 G_PARAM_CONSTRUCT_ONLY |
617 G_PARAM_STATIC_STRINGS));
619 g_object_class_install_property (
622 g_param_spec_object (
625 "A CamelSession instance",
628 G_PARAM_CONSTRUCT_ONLY |
629 G_PARAM_STATIC_STRINGS));
631 g_object_class_install_property (
634 g_param_spec_object (
637 "A CamelSettings instance",
641 G_PARAM_STATIC_STRINGS));
643 g_object_class_install_property (
646 g_param_spec_string (
649 "The unique identity of the service",
652 G_PARAM_CONSTRUCT_ONLY |
653 G_PARAM_STATIC_STRINGS));
655 g_object_class_install_property (
661 "The CamelURL for the service",
664 G_PARAM_CONSTRUCT_ONLY |
665 G_PARAM_STATIC_STRINGS));
669 camel_service_initable_init (GInitableIface *interface)
671 interface->init = service_initable_init;
675 camel_service_init (CamelService *service)
677 service->priv = CAMEL_SERVICE_GET_PRIVATE (service);
679 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
681 g_static_rec_mutex_init (&service->priv->connect_lock);
682 g_static_mutex_init (&service->priv->connect_op_lock);
686 camel_service_error_quark (void)
688 static GQuark quark = 0;
690 if (G_UNLIKELY (quark == 0)) {
691 const gchar *string = "camel-service-error-quark";
692 quark = g_quark_from_static_string (string);
699 * camel_service_cancel_connect:
700 * @service: a #CamelService
702 * If @service is currently attempting to connect to or disconnect
703 * from a server, this causes it to stop and fail. Otherwise it is a
707 camel_service_cancel_connect (CamelService *service)
709 CamelServiceClass *class;
711 g_return_if_fail (CAMEL_IS_SERVICE (service));
713 class = CAMEL_SERVICE_GET_CLASS (service);
714 g_return_if_fail (class->cancel_connect != NULL);
716 camel_service_lock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
717 if (service->priv->connect_op)
718 class->cancel_connect (service);
719 camel_service_unlock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
723 * camel_service_get_display_name:
724 * @service: a #CamelService
726 * Returns the display name for @service, or %NULL if @service has not
727 * been given a display name. The display name is intended for use in
728 * a user interface and should generally be given a user-defined name.
730 * Compare this with camel_service_get_name(), which returns a built-in
731 * description of the type of service (IMAP, SMTP, etc.).
733 * Returns: the display name for @service, or %NULL
738 camel_service_get_display_name (CamelService *service)
740 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
742 return service->priv->display_name;
746 * camel_service_set_display_name:
747 * @service: a #CamelService
748 * @display_name: a valid UTF-8 string, or %NULL
750 * Assigns a UTF-8 display name to @service. The display name is intended
751 * for use in a user interface and should generally be given a user-defined
754 * Compare this with camel_service_get_name(), which returns a built-in
755 * description of the type of service (IMAP, SMTP, etc.).
760 camel_service_set_display_name (CamelService *service,
761 const gchar *display_name)
763 g_return_if_fail (CAMEL_IS_SERVICE (service));
765 if (display_name != NULL)
766 g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
768 g_free (service->priv->display_name);
769 service->priv->display_name = g_strdup (display_name);
771 g_object_notify (G_OBJECT (service), "display-name");
775 * camel_service_get_user_data_dir:
776 * @service: a #CamelService
778 * Returns the base directory under which to store user-specific data
779 * for @service. The directory is formed by appending the directory
780 * returned by camel_session_get_user_data_dir() with the service's
781 * #CamelService:uid value.
783 * Returns: the base directory for @service
788 camel_service_get_user_data_dir (CamelService *service)
790 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
792 return service->priv->user_data_dir;
796 * camel_service_get_name:
797 * @service: a #CamelService
798 * @brief: whether or not to use a briefer form
800 * This gets the name of the service in a "friendly" (suitable for
801 * humans) form. If @brief is %TRUE, this should be a brief description
802 * such as for use in the folder tree. If @brief is %FALSE, it should
803 * be a more complete and mostly unambiguous description.
805 * Returns: a description of the service which the caller must free
808 camel_service_get_name (CamelService *service,
811 CamelServiceClass *class;
813 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
814 g_return_val_if_fail (service->priv->url, NULL);
816 class = CAMEL_SERVICE_GET_CLASS (service);
817 g_return_val_if_fail (class->get_name != NULL, NULL);
819 return class->get_name (service, brief);
823 * camel_service_get_provider:
824 * @service: a #CamelService
826 * Gets the #CamelProvider associated with the service.
828 * Returns: the #CamelProvider
831 camel_service_get_provider (CamelService *service)
833 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
835 return service->priv->provider;
839 * camel_service_get_session:
840 * @service: a #CamelService
842 * Gets the #CamelSession associated with the service.
844 * Returns: the #CamelSession
847 camel_service_get_session (CamelService *service)
849 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
851 return CAMEL_SESSION (service->priv->session);
855 * camel_service_get_settings:
856 * @service: a #CamelService
858 * Returns the #CamelSettings instance associated with the service.
860 * Returns: the #CamelSettings
865 camel_service_get_settings (CamelService *service)
867 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
869 /* Every service should have a settings object. */
870 g_warn_if_fail (service->priv->settings != NULL);
872 return service->priv->settings;
876 * camel_service_set_settings:
877 * @service: a #CamelService
878 * @settings: an instance derviced from #CamelSettings, or %NULL
880 * Associates a new #CamelSettings instance with the service.
881 * The @settings instance must match the settings type defined in
882 * #CamelServiceClass. If @settings is %NULL, a new #CamelSettings
883 * instance of the appropriate type is created with all properties
889 camel_service_set_settings (CamelService *service,
890 CamelSettings *settings)
892 CamelServiceClass *class;
894 g_return_if_fail (CAMEL_IS_SERVICE (service));
896 class = CAMEL_SERVICE_GET_CLASS (service);
898 if (settings != NULL) {
901 G_OBJECT_TYPE (settings),
902 class->settings_type));
903 g_object_ref (settings);
908 class->settings_type,
909 CAMEL_TYPE_SETTINGS));
910 settings = g_object_new (class->settings_type, NULL);
911 camel_settings_load_from_url (settings, camel_service_get_camel_url (service));
914 if (service->priv->settings != NULL)
915 g_object_unref (service->priv->settings);
917 service->priv->settings = settings;
919 g_object_notify (G_OBJECT (service), "settings");
923 * camel_service_get_uid:
924 * @service: a #CamelService
926 * Gets the unique identifier string associated with the service.
928 * Returns: the UID string
933 camel_service_get_uid (CamelService *service)
935 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
937 return service->priv->uid;
941 * camel_service_get_camel_url:
942 * @service: a #CamelService
944 * Returns the #CamelURL representing @service.
946 * Returns: the #CamelURL representing @service
951 camel_service_get_camel_url (CamelService *service)
953 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
955 return service->priv->url;
959 * camel_service_get_url:
960 * @service: a #CamelService
962 * Gets the URL representing @service. The returned URL must be
963 * freed when it is no longer needed. For security reasons, this
964 * routine does not return the password.
966 * Returns: the URL representing @service
969 camel_service_get_url (CamelService *service)
973 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
975 url = camel_service_get_camel_url (service);
977 return camel_url_to_string (url, CAMEL_URL_HIDE_PASSWORD);
981 * camel_service_connect_sync:
982 * @service: a #CamelService
983 * @error: return location for a #GError, or %NULL
985 * Connect to the service using the parameters it was initialized
988 * Returns: %TRUE if the connection is made or %FALSE otherwise
991 camel_service_connect_sync (CamelService *service,
994 CamelServiceClass *class;
996 gboolean ret = FALSE;
998 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
999 g_return_val_if_fail (service->priv->session != NULL, FALSE);
1000 g_return_val_if_fail (service->priv->url != NULL, FALSE);
1002 class = CAMEL_SERVICE_GET_CLASS (service);
1003 g_return_val_if_fail (class->connect_sync != NULL, FALSE);
1005 camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1007 if (service->priv->status == CAMEL_SERVICE_CONNECTED) {
1008 camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1012 /* Register a separate operation for connecting, so that
1013 * the offline code can cancel it. */
1014 camel_service_lock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1015 service->priv->connect_op = camel_operation_new ();
1016 op = service->priv->connect_op;
1017 camel_service_unlock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1019 service->priv->status = CAMEL_SERVICE_CONNECTING;
1020 ret = class->connect_sync (service, service->priv->connect_op, error);
1021 CAMEL_CHECK_GERROR (service, connect_sync, ret, error);
1022 service->priv->status =
1023 ret ? CAMEL_SERVICE_CONNECTED : CAMEL_SERVICE_DISCONNECTED;
1025 camel_service_lock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1026 g_object_unref (op);
1027 if (op == service->priv->connect_op)
1028 service->priv->connect_op = NULL;
1029 camel_service_unlock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1031 camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1037 * camel_service_disconnect_sync:
1038 * @service: a #CamelService
1039 * @clean: whether or not to try to disconnect cleanly
1040 * @error: return location for a #GError, or %NULL
1042 * Disconnect from the service. If @clean is %FALSE, it should not
1043 * try to do any synchronizing or other cleanup of the connection.
1045 * Returns: %TRUE if the disconnect was successful or %FALSE otherwise
1048 camel_service_disconnect_sync (CamelService *service,
1052 CamelServiceClass *class;
1053 gboolean res = TRUE;
1055 g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1057 class = CAMEL_SERVICE_GET_CLASS (service);
1058 g_return_val_if_fail (class->disconnect_sync != NULL, FALSE);
1060 camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1062 if (service->priv->status != CAMEL_SERVICE_DISCONNECTED
1063 && service->priv->status != CAMEL_SERVICE_DISCONNECTING) {
1065 camel_service_lock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1066 service->priv->connect_op = camel_operation_new ();
1067 op = service->priv->connect_op;
1068 camel_service_unlock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1070 service->priv->status = CAMEL_SERVICE_DISCONNECTING;
1071 res = class->disconnect_sync (
1072 service, clean, service->priv->connect_op, error);
1073 CAMEL_CHECK_GERROR (service, disconnect_sync, res, error);
1074 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
1076 camel_service_lock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1077 g_object_unref (op);
1078 if (op == service->priv->connect_op)
1079 service->priv->connect_op = NULL;
1080 camel_service_unlock (service, CAMEL_SERVICE_CONNECT_OP_LOCK);
1083 camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1085 service->priv->status = CAMEL_SERVICE_DISCONNECTED;
1091 * camel_service_get_connection_status:
1092 * @service: a #CamelService
1094 * Returns the connection status for @service.
1096 * Returns: the connection status
1100 CamelServiceConnectionStatus
1101 camel_service_get_connection_status (CamelService *service)
1103 g_return_val_if_fail (
1104 CAMEL_IS_SERVICE (service), CAMEL_SERVICE_DISCONNECTED);
1106 return service->priv->status;
1110 * camel_service_lock:
1111 * @service: a #CamelService
1112 * @lock: lock type to lock
1114 * Locks @service's @lock. Unlock it with camel_service_unlock().
1119 camel_service_lock (CamelService *service,
1120 CamelServiceLock lock)
1122 g_return_if_fail (CAMEL_IS_SERVICE (service));
1125 case CAMEL_SERVICE_REC_CONNECT_LOCK:
1126 g_static_rec_mutex_lock (&service->priv->connect_lock);
1128 case CAMEL_SERVICE_CONNECT_OP_LOCK:
1129 g_static_mutex_lock (&service->priv->connect_op_lock);
1132 g_return_if_reached ();
1137 * camel_service_unlock:
1138 * @service: a #CamelService
1139 * @lock: lock type to unlock
1141 * Unlocks @service's @lock, previously locked with camel_service_lock().
1146 camel_service_unlock (CamelService *service,
1147 CamelServiceLock lock)
1149 g_return_if_fail (CAMEL_IS_SERVICE (service));
1152 case CAMEL_SERVICE_REC_CONNECT_LOCK:
1153 g_static_rec_mutex_unlock (&service->priv->connect_lock);
1155 case CAMEL_SERVICE_CONNECT_OP_LOCK:
1156 g_static_mutex_unlock (&service->priv->connect_op_lock);
1159 g_return_if_reached ();
1164 * camel_service_query_auth_types_sync:
1165 * @service: a #CamelService
1166 * @cancellable: optional #GCancellable object, or %NULL
1167 * @error: return location for a #GError, or %NULL
1169 * Obtains a list of authentication types supported by @service.
1170 * Free the returned list with g_list_free().
1172 * Returns: a list of #CamelServiceAuthType structs
1175 camel_service_query_auth_types_sync (CamelService *service,
1176 GCancellable *cancellable,
1179 CamelServiceClass *class;
1182 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1184 class = CAMEL_SERVICE_GET_CLASS (service);
1185 g_return_val_if_fail (class->query_auth_types_sync != NULL, NULL);
1187 /* Note that we get the connect lock here, which means the
1188 * callee must not call the connect functions itself. */
1189 camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1190 list = class->query_auth_types_sync (service, cancellable, error);
1191 camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1197 * camel_service_query_auth_types:
1198 * @service: a #CamelService
1199 * @io_priority: the I/O priority of the request
1200 * @cancellable: optional #GCancellable object, or %NULL
1201 * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1202 * @user_data: data to pass to the callback function
1204 * Asynchronously obtains a list of authentication types supported by
1207 * When the operation is finished, @callback will be called. You can
1208 * then call camel_service_query_auth_types_finish() to get the result
1214 camel_service_query_auth_types (CamelService *service,
1216 GCancellable *cancellable,
1217 GAsyncReadyCallback callback,
1220 CamelServiceClass *class;
1222 g_return_if_fail (CAMEL_IS_SERVICE (service));
1224 class = CAMEL_SERVICE_GET_CLASS (service);
1225 g_return_if_fail (class->query_auth_types != NULL);
1227 class->query_auth_types (
1228 service, io_priority,
1229 cancellable, callback, user_data);
1233 * camel_service_query_auth_types_finish:
1234 * @service: a #CamelService
1235 * @result: a #GAsyncResult
1236 * @error: return location for a #GError, or %NULL
1238 * Finishes the operation started with camel_service_query_auth_types().
1239 * Free the returned list with g_list_free().
1241 * Returns: a list of #CamelServiceAuthType structs
1246 camel_service_query_auth_types_finish (CamelService *service,
1247 GAsyncResult *result,
1250 CamelServiceClass *class;
1252 g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1253 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1255 class = CAMEL_SERVICE_GET_CLASS (service);
1256 g_return_val_if_fail (class->query_auth_types_finish != NULL, NULL);
1258 return class->query_auth_types_finish (service, result, error);