Fix nasty typos from recent whitespace cleanup commit
[platform/upstream/evolution-data-server.git] / camel / camel-service.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* camel-service.c : Abstract class for an email service */
3
4 /*
5  *
6  * Author :
7  *  Bertrand Guiheneuf <bertrand@helixcode.com>
8  *
9  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
10  *
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.
14  *
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.
19  *
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
23  * USA
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <ctype.h>
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include <glib/gstdio.h>
36 #include <glib/gi18n-lib.h>
37
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"
44
45 #define d(x)
46 #define w(x)
47
48 #define CAMEL_SERVICE_GET_PRIVATE(obj) \
49         (G_TYPE_INSTANCE_GET_PRIVATE \
50         ((obj), CAMEL_TYPE_SERVICE, CamelServicePrivate))
51
52 typedef struct _AsyncContext AsyncContext;
53
54 struct _CamelServicePrivate {
55         gpointer session;  /* weak pointer */
56
57         CamelSettings *settings;
58         CamelProvider *provider;
59
60         gchar *display_name;
61         gchar *user_data_dir;
62         gchar *user_cache_dir;
63         gchar *uid;
64         gchar *password;
65
66         GCancellable *connect_op;
67         CamelServiceConnectionStatus status;
68
69         GStaticRecMutex connect_lock;   /* for locking connection operations */
70         GStaticMutex connect_op_lock;   /* for locking the connection_op */
71 };
72
73 struct _AsyncContext {
74         GList *auth_types;
75         gchar *auth_mechanism;
76         CamelAuthenticationResult auth_result;
77 };
78
79 enum {
80         PROP_0,
81         PROP_DISPLAY_NAME,
82         PROP_PASSWORD,
83         PROP_PROVIDER,
84         PROP_SESSION,
85         PROP_SETTINGS,
86         PROP_UID
87 };
88
89 /* Forward Declarations */
90 static void camel_service_initable_init (GInitableIface *interface);
91
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))
95
96 static void
97 async_context_free (AsyncContext *async_context)
98 {
99         g_list_free (async_context->auth_types);
100
101         g_free (async_context->auth_mechanism);
102
103         g_slice_free (AsyncContext, async_context);
104 }
105
106 static gchar *
107 service_find_old_data_dir (CamelService *service)
108 {
109         CamelProvider *provider;
110         CamelSession *session;
111         CamelURL *url;
112         GString *path;
113         gboolean allows_host;
114         gboolean allows_user;
115         gboolean needs_host;
116         gboolean needs_path;
117         gboolean needs_user;
118         const gchar *base_dir;
119         gchar *old_data_dir;
120
121         provider = camel_service_get_provider (service);
122         session = camel_service_get_session (service);
123         url = camel_service_new_camel_url (service);
124
125         allows_host = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_HOST);
126         allows_user = CAMEL_PROVIDER_ALLOWS (provider, CAMEL_URL_PART_USER);
127
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);
131
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.
135          *
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. */
139
140         path = g_string_new (provider->protocol);
141
142         if (allows_user) {
143                 g_string_append_c (path, '/');
144                 if (url->user != NULL)
145                         g_string_append (path, url->user);
146                 if (allows_host) {
147                         g_string_append_c (path, '@');
148                         if (url->host != NULL)
149                                 g_string_append (path, url->host);
150                         if (url->port) {
151                                 g_string_append_c (path, ':');
152                                 g_string_append_printf (path, "%d", url->port);
153                         }
154                 } else if (!needs_user) {
155                         g_string_append_c (path, '@');
156                 }
157
158         } else if (allows_host) {
159                 g_string_append_c (path, '/');
160                 if (!needs_host)
161                         g_string_append_c (path, '@');
162                 if (url->host != NULL)
163                         g_string_append (path, url->host);
164                 if (url->port) {
165                         g_string_append_c (path, ':');
166                         g_string_append_printf (path, "%d", url->port);
167                 }
168         }
169
170         if (needs_path && url->path) {
171                 if (*url->path != '/')
172                         g_string_append_c (path, '/');
173                 g_string_append (path, url->path);
174         }
175
176         base_dir = camel_session_get_user_data_dir (session);
177         old_data_dir = g_build_filename (base_dir, path->str, NULL);
178
179         g_string_free (path, TRUE);
180
181         if (!g_file_test (old_data_dir, G_FILE_TEST_IS_DIR)) {
182                 g_free (old_data_dir);
183                 old_data_dir = NULL;
184         }
185
186         camel_url_free (url);
187
188         return old_data_dir;
189 }
190
191 static void
192 service_set_provider (CamelService *service,
193                       CamelProvider *provider)
194 {
195         g_return_if_fail (provider != NULL);
196         g_return_if_fail (service->priv->provider == NULL);
197
198         service->priv->provider = provider;
199 }
200
201 static void
202 service_set_session (CamelService *service,
203                      CamelSession *session)
204 {
205         g_return_if_fail (CAMEL_IS_SESSION (session));
206         g_return_if_fail (service->priv->session == NULL);
207
208         service->priv->session = session;
209
210         g_object_add_weak_pointer (
211                 G_OBJECT (session), &service->priv->session);
212 }
213
214 static void
215 service_set_uid (CamelService *service,
216                  const gchar *uid)
217 {
218         g_return_if_fail (uid != NULL);
219         g_return_if_fail (service->priv->uid == NULL);
220
221         service->priv->uid = g_strdup (uid);
222 }
223
224 static void
225 service_set_property (GObject *object,
226                       guint property_id,
227                       const GValue *value,
228                       GParamSpec *pspec)
229 {
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));
235                         return;
236
237                 case PROP_PASSWORD:
238                         camel_service_set_password (
239                                 CAMEL_SERVICE (object),
240                                 g_value_get_string (value));
241                         return;
242
243                 case PROP_PROVIDER:
244                         service_set_provider (
245                                 CAMEL_SERVICE (object),
246                                 g_value_get_pointer (value));
247                         return;
248
249                 case PROP_SESSION:
250                         service_set_session (
251                                 CAMEL_SERVICE (object),
252                                 g_value_get_object (value));
253                         return;
254
255                 case PROP_SETTINGS:
256                         camel_service_set_settings (
257                                 CAMEL_SERVICE (object),
258                                 g_value_get_object (value));
259                         return;
260
261                 case PROP_UID:
262                         service_set_uid (
263                                 CAMEL_SERVICE (object),
264                                 g_value_get_string (value));
265                         return;
266         }
267
268         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
269 }
270
271 static void
272 service_get_property (GObject *object,
273                       guint property_id,
274                       GValue *value,
275                       GParamSpec *pspec)
276 {
277         switch (property_id) {
278                 case PROP_DISPLAY_NAME:
279                         g_value_set_string (
280                                 value, camel_service_get_display_name (
281                                 CAMEL_SERVICE (object)));
282                         return;
283
284                 case PROP_PASSWORD:
285                         g_value_set_string (
286                                 value, camel_service_get_password (
287                                 CAMEL_SERVICE (object)));
288                         return;
289
290                 case PROP_PROVIDER:
291                         g_value_set_pointer (
292                                 value, camel_service_get_provider (
293                                 CAMEL_SERVICE (object)));
294                         return;
295
296                 case PROP_SESSION:
297                         g_value_set_object (
298                                 value, camel_service_get_session (
299                                 CAMEL_SERVICE (object)));
300                         return;
301
302                 case PROP_SETTINGS:
303                         g_value_set_object (
304                                 value, camel_service_get_settings (
305                                 CAMEL_SERVICE (object)));
306                         return;
307
308                 case PROP_UID:
309                         g_value_set_string (
310                                 value, camel_service_get_uid (
311                                 CAMEL_SERVICE (object)));
312                         return;
313         }
314
315         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
316 }
317
318 static void
319 service_dispose (GObject *object)
320 {
321         CamelServicePrivate *priv;
322
323         priv = CAMEL_SERVICE_GET_PRIVATE (object);
324
325         if (priv->session != NULL) {
326                 g_object_remove_weak_pointer (
327                         G_OBJECT (priv->session), &priv->session);
328                 priv->session = NULL;
329         }
330
331         if (priv->settings != NULL) {
332                 g_object_unref (priv->settings);
333                 priv->settings = NULL;
334         }
335
336         /* Chain up to parent's dispose() method. */
337         G_OBJECT_CLASS (camel_service_parent_class)->dispose (object);
338 }
339
340 static void
341 service_finalize (GObject *object)
342 {
343         CamelServicePrivate *priv;
344
345         priv = CAMEL_SERVICE_GET_PRIVATE (object);
346
347         if (priv->status == CAMEL_SERVICE_CONNECTED)
348                 CAMEL_SERVICE_GET_CLASS (object)->disconnect_sync (
349                         CAMEL_SERVICE (object), TRUE, NULL, NULL);
350
351         g_free (priv->display_name);
352         g_free (priv->user_data_dir);
353         g_free (priv->user_cache_dir);
354         g_free (priv->uid);
355         g_free (priv->password);
356
357         g_static_rec_mutex_free (&priv->connect_lock);
358         g_static_mutex_free (&priv->connect_op_lock);
359
360         /* Chain up to parent's finalize() method. */
361         G_OBJECT_CLASS (camel_service_parent_class)->finalize (object);
362 }
363
364 static void
365 service_constructed (GObject *object)
366 {
367         CamelService *service;
368         CamelSession *session;
369         const gchar *base_dir;
370         const gchar *uid;
371
372         /* Chain up to parent's constructed() method. */
373         G_OBJECT_CLASS (camel_service_parent_class)->constructed (object);
374
375         service = CAMEL_SERVICE (object);
376         session = camel_service_get_session (service);
377
378         uid = camel_service_get_uid (service);
379
380         base_dir = camel_session_get_user_data_dir (session);
381         service->priv->user_data_dir = g_build_filename (base_dir, uid, NULL);
382
383         base_dir = camel_session_get_user_cache_dir (session);
384         service->priv->user_cache_dir = g_build_filename (base_dir, uid, NULL);
385 }
386
387 static gchar *
388 service_get_name (CamelService *service,
389                   gboolean brief)
390 {
391         g_warning (
392                 "%s does not implement CamelServiceClass::get_name()",
393                 G_OBJECT_TYPE_NAME (service));
394
395         return g_strdup (G_OBJECT_TYPE_NAME (service));
396 }
397
398 static void
399 service_cancel_connect (CamelService *service)
400 {
401         g_cancellable_cancel (service->priv->connect_op);
402 }
403
404 static gboolean
405 service_connect_sync (CamelService *service,
406                       GCancellable *cancellable,
407                       GError **error)
408 {
409         /* Things like the CamelMboxStore can validly
410          * not define a connect function. */
411          return TRUE;
412 }
413
414 static gboolean
415 service_disconnect_sync (CamelService *service,
416                          gboolean clean,
417                          GCancellable *cancellable,
418                          GError **error)
419 {
420         /* We let people get away with not having a disconnect
421          * function -- CamelMboxStore, for example. */
422         return TRUE;
423 }
424
425 static GList *
426 service_query_auth_types_sync (CamelService *service,
427                                GCancellable *cancellable,
428                                GError **error)
429 {
430         return NULL;
431 }
432
433 static void
434 service_authenticate_thread (GSimpleAsyncResult *simple,
435                              GObject *object,
436                              GCancellable *cancellable)
437 {
438         AsyncContext *async_context;
439         GError *error = NULL;
440
441         async_context = g_simple_async_result_get_op_res_gpointer (simple);
442
443         async_context->auth_result = camel_service_authenticate_sync (
444                 CAMEL_SERVICE (object), async_context->auth_mechanism,
445                 cancellable, &error);
446
447         if (error != NULL)
448                 g_simple_async_result_take_error (simple, error);
449 }
450
451 static void
452 service_authenticate (CamelService *service,
453                       const gchar *mechanism,
454                       gint io_priority,
455                       GCancellable *cancellable,
456                       GAsyncReadyCallback callback,
457                       gpointer user_data)
458 {
459         GSimpleAsyncResult *simple;
460         AsyncContext *async_context;
461
462         async_context = g_slice_new0 (AsyncContext);
463         async_context->auth_mechanism = g_strdup (mechanism);
464
465         simple = g_simple_async_result_new (
466                 G_OBJECT (service), callback, user_data, service_authenticate);
467
468         g_simple_async_result_set_op_res_gpointer (
469                 simple, async_context, (GDestroyNotify) async_context_free);
470
471         g_simple_async_result_run_in_thread (
472                 simple, service_authenticate_thread, io_priority, cancellable);
473
474         g_object_unref (simple);
475 }
476
477 static CamelAuthenticationResult
478 service_authenticate_finish (CamelService *service,
479                              GAsyncResult *result,
480                              GError **error)
481 {
482         GSimpleAsyncResult *simple;
483         AsyncContext *async_context;
484
485         g_return_val_if_fail (
486                 g_simple_async_result_is_valid (
487                 result, G_OBJECT (service), service_authenticate),
488                 CAMEL_AUTHENTICATION_REJECTED);
489
490         simple = G_SIMPLE_ASYNC_RESULT (result);
491         async_context = g_simple_async_result_get_op_res_gpointer (simple);
492
493         if (g_simple_async_result_propagate_error (simple, error))
494                 return CAMEL_AUTHENTICATION_ERROR;
495
496         return async_context->auth_result;
497 }
498
499 static void
500 service_query_auth_types_thread (GSimpleAsyncResult *simple,
501                                  GObject *object,
502                                  GCancellable *cancellable)
503 {
504         AsyncContext *async_context;
505         GError *error = NULL;
506
507         async_context = g_simple_async_result_get_op_res_gpointer (simple);
508
509         async_context->auth_types = camel_service_query_auth_types_sync (
510                 CAMEL_SERVICE (object), cancellable, &error);
511
512         if (error != NULL)
513                 g_simple_async_result_take_error (simple, error);
514 }
515
516 static void
517 service_query_auth_types (CamelService *service,
518                           gint io_priority,
519                           GCancellable *cancellable,
520                           GAsyncReadyCallback callback,
521                           gpointer user_data)
522 {
523         GSimpleAsyncResult *simple;
524         AsyncContext *async_context;
525
526         async_context = g_slice_new0 (AsyncContext);
527
528         simple = g_simple_async_result_new (
529                 G_OBJECT (service), callback,
530                 user_data, service_query_auth_types);
531
532         g_simple_async_result_set_op_res_gpointer (
533                 simple, async_context, (GDestroyNotify) async_context_free);
534
535         g_simple_async_result_run_in_thread (
536                 simple, service_query_auth_types_thread,
537                 io_priority, cancellable);
538
539         g_object_unref (simple);
540 }
541
542 static GList *
543 service_query_auth_types_finish (CamelService *service,
544                                  GAsyncResult *result,
545                                  GError **error)
546 {
547         GSimpleAsyncResult *simple;
548         AsyncContext *async_context;
549
550         g_return_val_if_fail (
551                 g_simple_async_result_is_valid (
552                 result, G_OBJECT (service),
553                 service_query_auth_types), NULL);
554
555         simple = G_SIMPLE_ASYNC_RESULT (result);
556         async_context = g_simple_async_result_get_op_res_gpointer (simple);
557
558         if (g_simple_async_result_propagate_error (simple, error))
559                 return NULL;
560
561         return g_list_copy (async_context->auth_types);
562 }
563
564 static gboolean
565 service_initable_init (GInitable *initable,
566                        GCancellable *cancellable,
567                        GError **error)
568 {
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. */
571
572         return TRUE;
573 }
574
575 static void
576 camel_service_class_init (CamelServiceClass *class)
577 {
578         GObjectClass *object_class;
579
580         g_type_class_add_private (class, sizeof (CamelServicePrivate));
581
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;
588
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;
595
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;
600
601         g_object_class_install_property (
602                 object_class,
603                 PROP_DISPLAY_NAME,
604                 g_param_spec_string (
605                         "display-name",
606                         "Display Name",
607                         "The display name for the service",
608                         NULL,
609                         G_PARAM_READWRITE |
610                         G_PARAM_CONSTRUCT |
611                         G_PARAM_STATIC_STRINGS));
612
613         g_object_class_install_property (
614                 object_class,
615                 PROP_PASSWORD,
616                 g_param_spec_string (
617                         "password",
618                         "Password",
619                         "The password for the service",
620                         NULL,
621                         G_PARAM_READWRITE |
622                         G_PARAM_CONSTRUCT |
623                         G_PARAM_STATIC_STRINGS));
624
625         g_object_class_install_property (
626                 object_class,
627                 PROP_PROVIDER,
628                 g_param_spec_pointer (
629                         "provider",
630                         "Provider",
631                         "The CamelProvider for the service",
632                         G_PARAM_READWRITE |
633                         G_PARAM_CONSTRUCT_ONLY |
634                         G_PARAM_STATIC_STRINGS));
635
636         g_object_class_install_property (
637                 object_class,
638                 PROP_SESSION,
639                 g_param_spec_object (
640                         "session",
641                         "Session",
642                         "A CamelSession instance",
643                         CAMEL_TYPE_SESSION,
644                         G_PARAM_READWRITE |
645                         G_PARAM_CONSTRUCT_ONLY |
646                         G_PARAM_STATIC_STRINGS));
647
648         g_object_class_install_property (
649                 object_class,
650                 PROP_SETTINGS,
651                 g_param_spec_object (
652                         "settings",
653                         "Settings",
654                         "A CamelSettings instance",
655                         CAMEL_TYPE_SETTINGS,
656                         G_PARAM_READWRITE |
657                         G_PARAM_CONSTRUCT |
658                         G_PARAM_STATIC_STRINGS));
659
660         g_object_class_install_property (
661                 object_class,
662                 PROP_UID,
663                 g_param_spec_string (
664                         "uid",
665                         "UID",
666                         "The unique identity of the service",
667                         NULL,
668                         G_PARAM_READWRITE |
669                         G_PARAM_CONSTRUCT_ONLY |
670                         G_PARAM_STATIC_STRINGS));
671 }
672
673 static void
674 camel_service_initable_init (GInitableIface *interface)
675 {
676         interface->init = service_initable_init;
677 }
678
679 static void
680 camel_service_init (CamelService *service)
681 {
682         service->priv = CAMEL_SERVICE_GET_PRIVATE (service);
683
684         service->priv->status = CAMEL_SERVICE_DISCONNECTED;
685
686         g_static_rec_mutex_init (&service->priv->connect_lock);
687         g_static_mutex_init (&service->priv->connect_op_lock);
688 }
689
690 GQuark
691 camel_service_error_quark (void)
692 {
693         static GQuark quark = 0;
694
695         if (G_UNLIKELY (quark == 0)) {
696                 const gchar *string = "camel-service-error-quark";
697                 quark = g_quark_from_static_string (string);
698         }
699
700         return quark;
701 }
702
703 /**
704  * camel_service_migrate_files:
705  * @service: a #CamelService
706  *
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.
710  *
711  * Since: 3.4
712  **/
713 void
714 camel_service_migrate_files (CamelService *service)
715 {
716         const gchar *new_data_dir;
717         gchar *old_data_dir;
718
719         g_return_if_fail (CAMEL_IS_SERVICE (service));
720
721         new_data_dir = camel_service_get_user_data_dir (service);
722         old_data_dir = service_find_old_data_dir (service);
723
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);
729         }
730 }
731
732 /**
733  * camel_service_new_camel_url:
734  * @service: a #CamelService
735  *
736  * Returns a new #CamelURL representing @service.
737  * Free the returned #CamelURL with camel_url_free().
738  *
739  * Returns: a new #CamelURL
740  *
741  * Since: 3.2
742  **/
743 CamelURL *
744 camel_service_new_camel_url (CamelService *service)
745 {
746         CamelURL *url;
747         CamelProvider *provider;
748         CamelSettings *settings;
749         gchar *host = NULL;
750         gchar *user = NULL;
751         gchar *path = NULL;
752         guint16 port = 0;
753
754         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
755
756         provider = camel_service_get_provider (service);
757         settings = camel_service_get_settings (service);
758
759         g_return_val_if_fail (provider != NULL, NULL);
760
761         /* Allocate as camel_url_new_with_base() does. */
762         url = g_new0 (CamelURL, 1);
763
764         if (CAMEL_IS_NETWORK_SETTINGS (settings)) {
765                 CamelNetworkSettings *network_settings;
766
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);
771         }
772
773         if (CAMEL_IS_LOCAL_SETTINGS (settings)) {
774                 CamelLocalSettings *local_settings;
775
776                 local_settings = CAMEL_LOCAL_SETTINGS (settings);
777                 path = camel_local_settings_dup_path (local_settings);
778         }
779
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);
785
786         g_free (host);
787         g_free (user);
788         g_free (path);
789
790         return url;
791 }
792
793 /**
794  * camel_service_get_display_name:
795  * @service: a #CamelService
796  *
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.
800  *
801  * Compare this with camel_service_get_name(), which returns a built-in
802  * description of the type of service (IMAP, SMTP, etc.).
803  *
804  * Returns: the display name for @service, or %NULL
805  *
806  * Since: 3.2
807  **/
808 const gchar *
809 camel_service_get_display_name (CamelService *service)
810 {
811         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
812
813         return service->priv->display_name;
814 }
815
816 /**
817  * camel_service_set_display_name:
818  * @service: a #CamelService
819  * @display_name: a valid UTF-8 string, or %NULL
820  *
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
823  * name.
824  *
825  * Compare this with camel_service_get_name(), which returns a built-in
826  * description of the type of service (IMAP, SMTP, etc.).
827  *
828  * Since: 3.2
829  **/
830 void
831 camel_service_set_display_name (CamelService *service,
832                                 const gchar *display_name)
833 {
834         g_return_if_fail (CAMEL_IS_SERVICE (service));
835
836         if (display_name != NULL)
837                 g_return_if_fail (g_utf8_validate (display_name, -1, NULL));
838
839         g_free (service->priv->display_name);
840         service->priv->display_name = g_strdup (display_name);
841
842         g_object_notify (G_OBJECT (service), "display-name");
843 }
844
845 /**
846  * camel_service_get_password:
847  * @service: a #CamelService
848  *
849  * Returns the password for @service.  Some SASL mechanisms use this
850  * when attempting to authenticate.
851  *
852  * Returns: the password for @service
853  *
854  * Since: 3.4
855  **/
856 const gchar *
857 camel_service_get_password (CamelService *service)
858 {
859         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
860
861         return service->priv->password;
862 }
863
864 /**
865  * camel_service_set_password:
866  * @service: a #CamelService
867  * @password: the password for @service
868  *
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.
872  *
873  * Since: 3.4
874  **/
875 void
876 camel_service_set_password (CamelService *service,
877                             const gchar *password)
878 {
879         g_return_if_fail (CAMEL_IS_SERVICE (service));
880
881         g_free (service->priv->password);
882         service->priv->password = g_strdup (password);
883
884         g_object_notify (G_OBJECT (service), "password");
885 }
886
887 /**
888  * camel_service_get_user_data_dir:
889  * @service: a #CamelService
890  *
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.
895  *
896  * Returns: the base directory for @service
897  *
898  * Since: 3.2
899  **/
900 const gchar *
901 camel_service_get_user_data_dir (CamelService *service)
902 {
903         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
904
905         return service->priv->user_data_dir;
906 }
907
908 /**
909  * camel_service_get_user_cache_dir:
910  * @service: a #CamelService
911  *
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.
916  *
917  * Returns: the base cache directory for @service
918  *
919  * Since: 3.4
920  **/
921 const gchar *
922 camel_service_get_user_cache_dir (CamelService *service)
923 {
924         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
925
926         return service->priv->user_cache_dir;
927 }
928
929 /**
930  * camel_service_get_name:
931  * @service: a #CamelService
932  * @brief: whether or not to use a briefer form
933  *
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.
938  *
939  * Returns: a description of the service which the caller must free
940  **/
941 gchar *
942 camel_service_get_name (CamelService *service,
943                         gboolean brief)
944 {
945         CamelServiceClass *class;
946
947         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
948
949         class = CAMEL_SERVICE_GET_CLASS (service);
950         g_return_val_if_fail (class->get_name != NULL, NULL);
951
952         return class->get_name (service, brief);
953 }
954
955 /**
956  * camel_service_get_provider:
957  * @service: a #CamelService
958  *
959  * Gets the #CamelProvider associated with the service.
960  *
961  * Returns: the #CamelProvider
962  **/
963 CamelProvider *
964 camel_service_get_provider (CamelService *service)
965 {
966         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
967
968         return service->priv->provider;
969 }
970
971 /**
972  * camel_service_get_session:
973  * @service: a #CamelService
974  *
975  * Gets the #CamelSession associated with the service.
976  *
977  * Returns: the #CamelSession
978  **/
979 CamelSession *
980 camel_service_get_session (CamelService *service)
981 {
982         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
983
984         return CAMEL_SESSION (service->priv->session);
985 }
986
987 /**
988  * camel_service_get_settings:
989  * @service: a #CamelService
990  *
991  * Returns the #CamelSettings instance associated with the service.
992  *
993  * Returns: the #CamelSettings
994  *
995  * Since: 3.2
996  **/
997 CamelSettings *
998 camel_service_get_settings (CamelService *service)
999 {
1000         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1001
1002         /* Every service should have a settings object. */
1003         g_warn_if_fail (service->priv->settings != NULL);
1004
1005         return service->priv->settings;
1006 }
1007
1008 /**
1009  * camel_service_set_settings:
1010  * @service: a #CamelService
1011  * @settings: an instance derviced from #CamelSettings, or %NULL
1012  *
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
1017  * set to defaults.
1018  *
1019  * Since: 3.2
1020  **/
1021 void
1022 camel_service_set_settings (CamelService *service,
1023                             CamelSettings *settings)
1024 {
1025         CamelServiceClass *class;
1026
1027         g_return_if_fail (CAMEL_IS_SERVICE (service));
1028
1029         class = CAMEL_SERVICE_GET_CLASS (service);
1030
1031         if (settings != NULL) {
1032                 g_return_if_fail (
1033                         g_type_is_a (
1034                                 G_OBJECT_TYPE (settings),
1035                                 class->settings_type));
1036                 g_object_ref (settings);
1037
1038         } else {
1039                 g_return_if_fail (
1040                         g_type_is_a (
1041                                 class->settings_type,
1042                                 CAMEL_TYPE_SETTINGS));
1043                 settings = g_object_new (class->settings_type, NULL);
1044         }
1045
1046         if (service->priv->settings != NULL)
1047                 g_object_unref (service->priv->settings);
1048
1049         service->priv->settings = settings;
1050
1051         g_object_notify (G_OBJECT (service), "settings");
1052 }
1053
1054 /**
1055  * camel_service_get_uid:
1056  * @service: a #CamelService
1057  *
1058  * Gets the unique identifier string associated with the service.
1059  *
1060  * Returns: the UID string
1061  *
1062  * Since: 3.2
1063  **/
1064 const gchar *
1065 camel_service_get_uid (CamelService *service)
1066 {
1067         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1068
1069         return service->priv->uid;
1070 }
1071
1072 /**
1073  * camel_service_cancel_connect:
1074  * @service: a #CamelService
1075  *
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
1078  * no-op.
1079  **/
1080 void
1081 camel_service_cancel_connect (CamelService *service)
1082 {
1083         CamelServiceClass *class;
1084
1085         g_return_if_fail (CAMEL_IS_SERVICE (service));
1086
1087         class = CAMEL_SERVICE_GET_CLASS (service);
1088         g_return_if_fail (class->cancel_connect != NULL);
1089
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);
1094 }
1095
1096 /**
1097  * camel_service_connect_sync:
1098  * @service: a #CamelService
1099  * @error: return location for a #GError, or %NULL
1100  *
1101  * Connect to the service using the parameters it was initialized
1102  * with.
1103  *
1104  * Returns: %TRUE if the connection is made or %FALSE otherwise
1105  **/
1106 gboolean
1107 camel_service_connect_sync (CamelService *service,
1108                             GError **error)
1109 {
1110         CamelServiceClass *class;
1111         GCancellable *op;
1112         gboolean ret = FALSE;
1113
1114         g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1115         g_return_val_if_fail (service->priv->session != NULL, FALSE);
1116
1117         class = CAMEL_SERVICE_GET_CLASS (service);
1118         g_return_val_if_fail (class->connect_sync != NULL, FALSE);
1119
1120         camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1121
1122         if (service->priv->status == CAMEL_SERVICE_CONNECTED) {
1123                 camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1124                 return TRUE;
1125         }
1126
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);
1133
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;
1139
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);
1145
1146         camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1147
1148         return ret;
1149 }
1150
1151 /**
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
1156  *
1157  * Disconnect from the service. If @clean is %FALSE, it should not
1158  * try to do any synchronizing or other cleanup of the connection.
1159  *
1160  * Returns: %TRUE if the disconnect was successful or %FALSE otherwise
1161  **/
1162 gboolean
1163 camel_service_disconnect_sync (CamelService *service,
1164                                gboolean clean,
1165                                GError **error)
1166 {
1167         CamelServiceClass *class;
1168         gboolean res = TRUE;
1169
1170         g_return_val_if_fail (CAMEL_IS_SERVICE (service), FALSE);
1171
1172         class = CAMEL_SERVICE_GET_CLASS (service);
1173         g_return_val_if_fail (class->disconnect_sync != NULL, FALSE);
1174
1175         camel_service_lock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1176
1177         if (service->priv->status != CAMEL_SERVICE_DISCONNECTED
1178             && service->priv->status != CAMEL_SERVICE_DISCONNECTING) {
1179                 GCancellable *op;
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);
1184
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;
1190
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);
1196         }
1197
1198         camel_service_unlock (service, CAMEL_SERVICE_REC_CONNECT_LOCK);
1199
1200         service->priv->status = CAMEL_SERVICE_DISCONNECTED;
1201
1202         return res;
1203 }
1204
1205 /**
1206  * camel_service_get_connection_status:
1207  * @service: a #CamelService
1208  *
1209  * Returns the connection status for @service.
1210  *
1211  * Returns: the connection status
1212  *
1213  * Since: 3.2
1214  **/
1215 CamelServiceConnectionStatus
1216 camel_service_get_connection_status (CamelService *service)
1217 {
1218         g_return_val_if_fail (
1219                 CAMEL_IS_SERVICE (service), CAMEL_SERVICE_DISCONNECTED);
1220
1221         return service->priv->status;
1222 }
1223
1224 /**
1225  * camel_service_lock:
1226  * @service: a #CamelService
1227  * @lock: lock type to lock
1228  *
1229  * Locks @service's @lock. Unlock it with camel_service_unlock().
1230  *
1231  * Since: 2.32
1232  **/
1233 void
1234 camel_service_lock (CamelService *service,
1235                     CamelServiceLock lock)
1236 {
1237         g_return_if_fail (CAMEL_IS_SERVICE (service));
1238
1239         switch (lock) {
1240                 case CAMEL_SERVICE_REC_CONNECT_LOCK:
1241                         g_static_rec_mutex_lock (&service->priv->connect_lock);
1242                         break;
1243                 case CAMEL_SERVICE_CONNECT_OP_LOCK:
1244                         g_static_mutex_lock (&service->priv->connect_op_lock);
1245                         break;
1246                 default:
1247                         g_return_if_reached ();
1248         }
1249 }
1250
1251 /**
1252  * camel_service_unlock:
1253  * @service: a #CamelService
1254  * @lock: lock type to unlock
1255  *
1256  * Unlocks @service's @lock, previously locked with camel_service_lock().
1257  *
1258  * Since: 2.32
1259  **/
1260 void
1261 camel_service_unlock (CamelService *service,
1262                       CamelServiceLock lock)
1263 {
1264         g_return_if_fail (CAMEL_IS_SERVICE (service));
1265
1266         switch (lock) {
1267                 case CAMEL_SERVICE_REC_CONNECT_LOCK:
1268                         g_static_rec_mutex_unlock (&service->priv->connect_lock);
1269                         break;
1270                 case CAMEL_SERVICE_CONNECT_OP_LOCK:
1271                         g_static_mutex_unlock (&service->priv->connect_op_lock);
1272                         break;
1273                 default:
1274                         g_return_if_reached ();
1275         }
1276 }
1277
1278 /**
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
1284  *
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.
1288  *
1289  * If the authentication attempt completed and the server accepted the
1290  * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
1291  *
1292  * If the authentication attempt completed but the server rejected the
1293  * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
1294  *
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.
1298  *
1299  * Generally this function should only be called from a #CamelSession
1300  * subclass in order to implement its own authentication loop.
1301  *
1302  * Returns: the authentication result
1303  *
1304  * Since: 3.4
1305  **/
1306 CamelAuthenticationResult
1307 camel_service_authenticate_sync (CamelService *service,
1308                                  const gchar *mechanism,
1309                                  GCancellable *cancellable,
1310                                  GError **error)
1311 {
1312         CamelServiceClass *class;
1313         CamelAuthenticationResult result;
1314
1315         g_return_val_if_fail (
1316                 CAMEL_IS_SERVICE (service),
1317                 CAMEL_AUTHENTICATION_REJECTED);
1318
1319         class = CAMEL_SERVICE_GET_CLASS (service);
1320         g_return_val_if_fail (
1321                 class->authenticate_sync != NULL,
1322                 CAMEL_AUTHENTICATION_REJECTED);
1323
1324         result = class->authenticate_sync (
1325                 service, mechanism, cancellable, error);
1326         CAMEL_CHECK_GERROR (
1327                 service, authenticate_sync,
1328                 result != CAMEL_AUTHENTICATION_ERROR, error);
1329
1330         return result;
1331 }
1332
1333 /**
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
1341  *
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.
1345  *
1346  * Generally this function should only be called from a #CamelSession
1347  * subclass in order to implement its own authentication loop.
1348  *
1349  * When the operation is finished, @callback will be called.  You can
1350  * then call camel_service_authenticate_finish() to get the result of
1351  * the operation.
1352  *
1353  * Since: 3.4
1354  **/
1355 void
1356 camel_service_authenticate (CamelService *service,
1357                             const gchar *mechanism,
1358                             gint io_priority,
1359                             GCancellable *cancellable,
1360                             GAsyncReadyCallback callback,
1361                             gpointer user_data)
1362 {
1363         CamelServiceClass *class;
1364
1365         g_return_if_fail (CAMEL_IS_SERVICE (service));
1366
1367         class = CAMEL_SERVICE_GET_CLASS (service);
1368         g_return_if_fail (class->authenticate != NULL);
1369
1370         class->authenticate (
1371                 service, mechanism, io_priority,
1372                 cancellable, callback, user_data);
1373 }
1374
1375 /**
1376  * camel_service_authenticate_finish:
1377  * @service: a #CamelService
1378  * @result: a #GAsyncResult
1379  * @error: return location for a #GError, or %NULL
1380  *
1381  * Finishes the operation started with camel_service_authenticate().
1382  *
1383  * If the authentication attempt completed and the server accepted the
1384  * credentials, the function returns #CAMEL_AUTHENTICATION_ACCEPTED.
1385  *
1386  * If the authentication attempt completed but the server rejected the
1387  * credentials, the function returns #CAMEL_AUTHENTICATION_REJECTED.
1388  *
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.
1392  *
1393  * Returns: the authentication result
1394  *
1395  * Since: 3.4
1396  **/
1397 CamelAuthenticationResult
1398 camel_service_authenticate_finish (CamelService *service,
1399                                    GAsyncResult *result,
1400                                    GError **error)
1401 {
1402         CamelServiceClass *class;
1403
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);
1410
1411         class = CAMEL_SERVICE_GET_CLASS (service);
1412         g_return_val_if_fail (
1413                 class->authenticate_finish,
1414                 CAMEL_AUTHENTICATION_REJECTED);
1415
1416         return class->authenticate_finish (service, result, error);
1417 }
1418
1419 /**
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
1424  *
1425  * Obtains a list of authentication types supported by @service.
1426  * Free the returned list with g_list_free().
1427  *
1428  * Returns: a list of #CamelServiceAuthType structs
1429  **/
1430 GList *
1431 camel_service_query_auth_types_sync (CamelService *service,
1432                                      GCancellable *cancellable,
1433                                      GError **error)
1434 {
1435         CamelServiceClass *class;
1436         GList *list;
1437
1438         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1439
1440         class = CAMEL_SERVICE_GET_CLASS (service);
1441         g_return_val_if_fail (class->query_auth_types_sync != NULL, NULL);
1442
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);
1448
1449         return list;
1450 }
1451
1452 /**
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
1459  *
1460  * Asynchronously obtains a list of authentication types supported by
1461  * @service.
1462  *
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
1465  * of the operation.
1466  *
1467  * Since: 3.2
1468  **/
1469 void
1470 camel_service_query_auth_types (CamelService *service,
1471                                 gint io_priority,
1472                                 GCancellable *cancellable,
1473                                 GAsyncReadyCallback callback,
1474                                 gpointer user_data)
1475 {
1476         CamelServiceClass *class;
1477
1478         g_return_if_fail (CAMEL_IS_SERVICE (service));
1479
1480         class = CAMEL_SERVICE_GET_CLASS (service);
1481         g_return_if_fail (class->query_auth_types != NULL);
1482
1483         class->query_auth_types (
1484                 service, io_priority,
1485                 cancellable, callback, user_data);
1486 }
1487
1488 /**
1489  * camel_service_query_auth_types_finish:
1490  * @service: a #CamelService
1491  * @result: a #GAsyncResult
1492  * @error: return location for a #GError, or %NULL
1493  *
1494  * Finishes the operation started with camel_service_query_auth_types().
1495  * Free the returned list with g_list_free().
1496  *
1497  * Returns: a list of #CamelServiceAuthType structs
1498  *
1499  * Since: 3.2
1500  **/
1501 GList *
1502 camel_service_query_auth_types_finish (CamelService *service,
1503                                        GAsyncResult *result,
1504                                        GError **error)
1505 {
1506         CamelServiceClass *class;
1507
1508         g_return_val_if_fail (CAMEL_IS_SERVICE (service), NULL);
1509         g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
1510
1511         class = CAMEL_SERVICE_GET_CLASS (service);
1512         g_return_val_if_fail (class->query_auth_types_finish != NULL, NULL);
1513
1514         return class->query_auth_types_finish (service, result, error);
1515 }
1516