Make use of G_DEFINE_QUARK()
[platform/upstream/evolution-data-server.git] / addressbook / libebook / e-book.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
4  * Copyright (C) 2006 OpenedHand Ltd
5  * Copyright (C) 2009 Intel Corporation
6  *
7  * This library is free software; you can redistribute it and/or modify it under
8  * the terms of version 2.1 of the GNU Lesser General Public License as
9  * published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  * Author: Ross Burton <ross@linux.intel.com>
21  */
22
23 /* e-book deprecated since 3.2, use e-book-client instead */
24
25 /**
26  * SECTION:e-book
27  *
28  * The old asynchronous API was deprecated since 3.0 and is replaced with
29  * their an equivalent version which has a detailed #GError
30  * structure in the asynchronous callback, instead of a status code only.
31  *
32  * As an example, e_book_async_open() is replaced by e_book_open_async().
33  *
34  * Deprecated: 3.2: Use #EBookClient instead.
35  */
36
37 #include <config.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <glib/gi18n-lib.h>
41 #include "e-book.h"
42 #include "e-error.h"
43 #include "e-contact.h"
44 #include "e-name-western.h"
45 #include "e-book-view-private.h"
46 #include "e-book-marshal.h"
47
48 #define E_BOOK_GET_PRIVATE(obj) \
49         (G_TYPE_INSTANCE_GET_PRIVATE \
50         ((obj), E_TYPE_BOOK, EBookPrivate))
51
52 #define CLIENT_BACKEND_PROPERTY_CAPABILITIES            "capabilities"
53 #define BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS           "required-fields"
54 #define BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS          "supported-fields"
55
56 struct _EBookPrivate {
57         EBookClient *client;
58         gulong backend_died_handler_id;
59         gulong notify_online_handler_id;
60         gulong notify_readonly_handler_id;
61
62         ESource *source;
63         gchar *cap;
64 };
65
66 typedef struct {
67         EBook *book;
68         gpointer callback; /* TODO union */
69         gpointer excallback;
70         gpointer closure;
71         gpointer data;
72 } AsyncData;
73
74 enum {
75         PROP_0,
76         PROP_SOURCE
77 };
78
79 enum {
80         WRITABLE_STATUS,
81         CONNECTION_STATUS,
82         AUTH_REQUIRED,
83         BACKEND_DIED,
84         LAST_SIGNAL
85 };
86
87 static guint signals[LAST_SIGNAL];
88
89 static void     e_book_initable_init            (GInitableIface *interface);
90
91 G_DEFINE_TYPE_WITH_CODE (
92         EBook, e_book, G_TYPE_OBJECT,
93         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, e_book_initable_init))
94
95 G_DEFINE_QUARK (e-book-error-quark, e_book_error)
96
97 static void
98 book_backend_died_cb (EClient *client,
99                       EBook *book)
100 {
101         /* Echo the signal emission from the EBookClient. */
102         g_signal_emit (book, signals[BACKEND_DIED], 0);
103 }
104
105 static void
106 book_notify_online_cb (EClient *client,
107                        GParamSpec *pspec,
108                        EBook *book)
109 {
110         gboolean online = e_client_is_online (client);
111
112         g_signal_emit (book, signals[CONNECTION_STATUS], 0, online);
113 }
114
115 static void
116 book_notify_readonly_cb (EClient *client,
117                          GParamSpec *pspec,
118                          EBook *book)
119 {
120         gboolean writable = !e_client_is_readonly (client);
121
122         g_signal_emit (book, signals[WRITABLE_STATUS], 0, writable);
123 }
124
125 static void
126 book_set_source (EBook *book,
127                  ESource *source)
128 {
129         g_return_if_fail (E_IS_SOURCE (source));
130         g_return_if_fail (book->priv->source == NULL);
131
132         book->priv->source = g_object_ref (source);
133 }
134
135 static void
136 book_set_property (GObject *object,
137                    guint property_id,
138                    const GValue *value,
139                    GParamSpec *pspec)
140 {
141         switch (property_id) {
142                 case PROP_SOURCE:
143                         book_set_source (
144                                 E_BOOK (object),
145                                 g_value_get_object (value));
146                         return;
147         }
148
149         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
150 }
151
152 static void
153 book_get_property (GObject *object,
154                    guint property_id,
155                    GValue *value,
156                    GParamSpec *pspec)
157 {
158         switch (property_id) {
159                 case PROP_SOURCE:
160                         g_value_set_object (
161                                 value, e_book_get_source (
162                                 E_BOOK (object)));
163                         return;
164         }
165
166         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
167 }
168
169 static void
170 book_dispose (GObject *object)
171 {
172         EBookPrivate *priv;
173
174         priv = E_BOOK_GET_PRIVATE (object);
175
176         if (priv->client != NULL) {
177                 g_signal_handler_disconnect (
178                         priv->client,
179                         priv->backend_died_handler_id);
180                 g_signal_handler_disconnect (
181                         priv->client,
182                         priv->notify_online_handler_id);
183                 g_signal_handler_disconnect (
184                         priv->client,
185                         priv->notify_readonly_handler_id);
186                 g_object_unref (priv->client);
187                 priv->client = NULL;
188         }
189
190         if (priv->source != NULL) {
191                 g_object_unref (priv->source);
192                 priv->source = NULL;
193         }
194
195         /* Chain up to parent's dispose() method. */
196         G_OBJECT_CLASS (e_book_parent_class)->dispose (object);
197 }
198
199 static void
200 book_finalize (GObject *object)
201 {
202         EBookPrivate *priv;
203
204         priv = E_BOOK_GET_PRIVATE (object);
205
206         g_free (priv->cap);
207
208         /* Chain up to parent's finalize() method. */
209         G_OBJECT_CLASS (e_book_parent_class)->finalize (object);
210 }
211
212 static gboolean
213 book_initable_init (GInitable *initable,
214                     GCancellable *cancellable,
215                     GError **error)
216 {
217         EBook *book = E_BOOK (initable);
218         ESource *source;
219
220         source = e_book_get_source (book);
221
222         book->priv->client = e_book_client_new (source, error);
223
224         if (book->priv->client == NULL)
225                 return FALSE;
226
227         book->priv->backend_died_handler_id = g_signal_connect (
228                 book->priv->client, "backend-died",
229                 G_CALLBACK (book_backend_died_cb), book);
230
231         book->priv->notify_online_handler_id = g_signal_connect (
232                 book->priv->client, "notify::online",
233                 G_CALLBACK (book_notify_online_cb), book);
234
235         book->priv->notify_readonly_handler_id = g_signal_connect (
236                 book->priv->client, "notify::readonly",
237                 G_CALLBACK (book_notify_readonly_cb), book);
238
239         return TRUE;
240 }
241
242 static void
243 e_book_class_init (EBookClass *class)
244 {
245         GObjectClass *object_class;
246
247         g_type_class_add_private (class, sizeof (EBookPrivate));
248
249         object_class = G_OBJECT_CLASS (class);
250         object_class->set_property = book_set_property;
251         object_class->get_property = book_get_property;
252         object_class->dispose = book_dispose;
253         object_class->finalize = book_finalize;
254
255         g_object_class_install_property (
256                 object_class,
257                 PROP_SOURCE,
258                 g_param_spec_object (
259                         "source",
260                         "Source",
261                         "The data source for this EBook",
262                         E_TYPE_SOURCE,
263                         G_PARAM_READWRITE |
264                         G_PARAM_CONSTRUCT_ONLY |
265                         G_PARAM_STATIC_STRINGS));
266
267         signals[WRITABLE_STATUS] = g_signal_new (
268                 "writable_status",
269                 G_OBJECT_CLASS_TYPE (object_class),
270                 G_SIGNAL_RUN_LAST,
271                 G_STRUCT_OFFSET (EBookClass, writable_status),
272                 NULL, NULL,
273                 e_book_marshal_NONE__BOOL,
274                 G_TYPE_NONE, 1,
275                 G_TYPE_BOOLEAN);
276
277         signals[CONNECTION_STATUS] = g_signal_new (
278                 "connection_status",
279                 G_OBJECT_CLASS_TYPE (object_class),
280                 G_SIGNAL_RUN_LAST,
281                 G_STRUCT_OFFSET (EBookClass, connection_status),
282                 NULL, NULL,
283                 e_book_marshal_NONE__BOOL,
284                 G_TYPE_NONE, 1,
285                 G_TYPE_BOOLEAN);
286
287         signals[BACKEND_DIED] = g_signal_new (
288                 "backend_died",
289                 G_OBJECT_CLASS_TYPE (object_class),
290                 G_SIGNAL_RUN_LAST,
291                 G_STRUCT_OFFSET (EBookClass, backend_died),
292                 NULL, NULL,
293                 e_book_marshal_NONE__NONE,
294                 G_TYPE_NONE, 0);
295 }
296
297 static void
298 e_book_initable_init (GInitableIface *interface)
299 {
300         interface->init = book_initable_init;
301 }
302
303 static void
304 e_book_init (EBook *book)
305 {
306         book->priv = E_BOOK_GET_PRIVATE (book);
307 }
308
309 /**
310  * e_book_add_contact:
311  * @book: an #EBook
312  * @contact: an #EContact
313  * @error: a #GError to set on failure
314  *
315  * Adds @contact to @book.
316  *
317  * Returns: %TRUE if successful, %FALSE otherwise.
318  *
319  * Deprecated: 3.2: Use e_book_client_add_contact_sync() instead.
320  **/
321 gboolean
322 e_book_add_contact (EBook *book,
323                     EContact *contact,
324                     GError **error)
325 {
326         gchar *added_uid = NULL;
327         gboolean success;
328
329         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
330         g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
331
332         success = e_book_client_add_contact_sync (
333                 book->priv->client, contact, &added_uid, NULL, error);
334
335         if (added_uid != NULL) {
336                 e_contact_set (contact, E_CONTACT_UID, added_uid);
337                 g_free (added_uid);
338         }
339
340         return success;
341 }
342
343 static void
344 add_contact_reply (GObject *source_object,
345                    GAsyncResult *result,
346                    gpointer user_data)
347 {
348         AsyncData *data = user_data;
349         EBookIdCallback cb = data->callback;
350         EBookIdAsyncCallback excb = data->excallback;
351         gchar *added_uid = NULL;
352         GError *error = NULL;
353
354         e_book_client_add_contact_finish (
355                 E_BOOK_CLIENT (source_object), result, &added_uid, &error);
356
357         if (cb != NULL && error == NULL)
358                 cb (data->book, E_BOOK_ERROR_OK, added_uid, data->closure);
359         if (cb != NULL && error != NULL)
360                 cb (data->book, error->code, NULL, data->closure);
361         if (excb != NULL)
362                 excb (data->book, error, added_uid, data->closure);
363
364         if (error != NULL)
365                 g_error_free (error);
366
367         g_free (added_uid);
368
369         g_object_unref (data->book);
370         g_slice_free (AsyncData, data);
371 }
372
373 /**
374  * e_book_async_add_contact:
375  * @book: an #EBook
376  * @contact: an #EContact
377  * @cb: (scope async): function to call when the operation finishes
378  * @closure: data to pass to callback function
379  *
380  * Adds @contact to @book without blocking.
381  *
382  * Returns: %TRUE if the operation was started, %FALSE otherwise.
383  *
384  * Deprecated: 3.0: Use e_book_add_contact_async() instead.
385  **/
386 gboolean
387 e_book_async_add_contact (EBook *book,
388                           EContact *contact,
389                           EBookIdCallback cb,
390                           gpointer closure)
391 {
392         AsyncData *data;
393
394         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
395         g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
396
397         data = g_slice_new0 (AsyncData);
398         data->book = g_object_ref (book);
399         data->callback = cb;
400         data->closure = closure;
401
402         e_book_client_add_contact (
403                 book->priv->client, contact, NULL,
404                 add_contact_reply, data);
405
406         return TRUE;
407 }
408
409 /**
410  * e_book_add_contact_async:
411  * @book: an #EBook
412  * @contact: an #EContact
413  * @cb: (scope async): function to call when the operation finishes
414  * @closure: data to pass to callback function
415  *
416  * Adds @contact to @book without blocking.
417  *
418  * Returns: %TRUE if the operation was started, %FALSE otherwise.
419  *
420  * Since: 2.32
421  *
422  * Deprecated: 3.2: Use e_book_client_add_contact() and e_book_client_add_contact_finish() instead.
423  **/
424 gboolean
425 e_book_add_contact_async (EBook *book,
426                           EContact *contact,
427                           EBookIdAsyncCallback cb,
428                           gpointer closure)
429 {
430         AsyncData *data;
431
432         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
433         g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
434
435         data = g_slice_new0 (AsyncData);
436         data->book = g_object_ref (book);
437         data->excallback = cb;
438         data->closure = closure;
439
440         e_book_client_add_contact (
441                 book->priv->client, contact, NULL,
442                 add_contact_reply, data);
443
444         return TRUE;
445 }
446
447 /**
448  * e_book_commit_contact:
449  * @book: an #EBook
450  * @contact: an #EContact
451  * @error: a #GError to set on failure
452  *
453  * Applies the changes made to @contact to the stored version in
454  * @book.
455  *
456  * Returns: %TRUE if successful, %FALSE otherwise
457  *
458  * Deprecated: 3.2: Use e_book_client_modify_contact_sync() instead.
459  **/
460 gboolean
461 e_book_commit_contact (EBook *book,
462                        EContact *contact,
463                        GError **error)
464 {
465         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
466         g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
467
468         return e_book_client_modify_contact_sync (
469                 book->priv->client, contact, NULL, error);
470 }
471
472 static void
473 modify_contacts_reply (GObject *source_object,
474                        GAsyncResult *result,
475                        gpointer user_data)
476 {
477         AsyncData *data = user_data;
478         EBookCallback cb = data->callback;
479         EBookAsyncCallback excb = data->excallback;
480         GError *error = NULL;
481
482         e_book_client_modify_contact_finish (
483                 E_BOOK_CLIENT (source_object), result, &error);
484
485         if (cb != NULL && error == NULL)
486                 cb (data->book, E_BOOK_ERROR_OK, data->closure);
487         if (cb != NULL && error != NULL)
488                 cb (data->book, error->code, data->closure);
489         if (excb != NULL)
490                 excb (data->book, error, data->closure);
491
492         if (error != NULL)
493                 g_error_free (error);
494
495         g_object_unref (data->book);
496         g_slice_free (AsyncData, data);
497 }
498
499 /**
500  * e_book_async_commit_contact:
501  * @book: an #EBook
502  * @contact: an #EContact
503  * @cb: (scope async): function to call when the operation finishes
504  * @closure: data to pass to callback function
505  *
506  * Applies the changes made to @contact to the stored version in
507  * @book without blocking.
508  *
509  * Returns: %TRUE if the operation was started, %FALSE otherwise.
510  *
511  * Deprecated: 3.0: Use e_book_commit_contact_async() instead.
512  **/
513 gboolean
514 e_book_async_commit_contact (EBook *book,
515                              EContact *contact,
516                              EBookCallback cb,
517                              gpointer closure)
518 {
519         AsyncData *data;
520
521         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
522         g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
523
524         data = g_slice_new0 (AsyncData);
525         data->book = g_object_ref (book);
526         data->callback = cb;
527         data->closure = closure;
528
529         e_book_client_modify_contact (
530                 book->priv->client, contact, NULL,
531                 modify_contacts_reply, data);
532
533         return TRUE;
534 }
535
536 /**
537  * e_book_commit_contact_async:
538  * @book: an #EBook
539  * @contact: an #EContact
540  * @cb: (scope async): function to call when the operation finishes
541  * @closure: data to pass to callback function
542  *
543  * Applies the changes made to @contact to the stored version in
544  * @book without blocking.
545  *
546  * Returns: %TRUE if the operation was started, %FALSE otherwise.
547  *
548  * Since: 2.32
549  *
550  * Deprecated: 3.2: Use e_book_client_modify_contact() and e_book_client_modify_contact_finish() instead.
551  **/
552 gboolean
553 e_book_commit_contact_async (EBook *book,
554                              EContact *contact,
555                              EBookAsyncCallback cb,
556                              gpointer closure)
557 {
558         AsyncData *data;
559
560         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
561         g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
562
563         data = g_slice_new0 (AsyncData);
564         data->book = g_object_ref (book);
565         data->excallback = cb;
566         data->closure = closure;
567
568         e_book_client_modify_contact (
569                 book->priv->client, contact, NULL,
570                 modify_contacts_reply, data);
571
572         return TRUE;
573 }
574
575 /**
576  * e_book_get_required_fields:
577  * @book: an #EBook
578  * @fields: (out) (transfer full) (element-type utf8): a #GList of fields to set on success
579  * @error: a #GError to set on failure
580  *
581  * Gets a list of fields that are required to be filled in for
582  * all contacts in this @book. The list will contain pointers
583  * to allocated strings, and both the #GList and the strings
584  * must be freed by the caller.
585  *
586  * Returns: %TRUE if successful, %FALSE otherwise.
587  *
588  * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
589  * an #EBookClient object with #BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
590  **/
591 gboolean
592 e_book_get_required_fields (EBook *book,
593                             GList **fields,
594                             GError **error)
595 {
596         gchar *prop_value = NULL;
597         gboolean success;
598
599         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
600
601         if (fields != NULL)
602                 *fields = NULL;
603
604         success = e_client_get_backend_property_sync (
605                 E_CLIENT (book->priv->client),
606                 BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
607                 &prop_value, NULL, error);
608
609         if (success && fields != NULL) {
610                 GQueue queue = G_QUEUE_INIT;
611                 gchar **strv;
612                 gint ii;
613
614                 strv = g_strsplit (prop_value, ",", -1);
615
616                 for (ii = 0; strv != NULL && strv[ii] != NULL; ii++)
617                         g_queue_push_tail (&queue, strv[ii]);
618
619                 /* The GQueue now owns the strings in the string array,
620                  * so use g_free() instead of g_strfreev() to free just
621                  * the array itself. */
622                 g_free (strv);
623
624                 /* Transfer ownership of the GQueue content. */
625                 *fields = g_queue_peek_head_link (&queue);
626         }
627
628         g_free (prop_value);
629
630         return success;
631 }
632
633 static void
634 get_required_fields_reply (GObject *source_object,
635                            GAsyncResult *result,
636                            gpointer user_data)
637 {
638         AsyncData *data = user_data;
639         EBookEListCallback cb = data->callback;
640         EBookEListAsyncCallback excb = data->excallback;
641         EList *elist;
642         gchar *prop_value = NULL;
643         GError *error = NULL;
644
645         e_client_get_backend_property_finish (
646                 E_CLIENT (source_object), result, &prop_value, &error);
647
648         /* Sanity check. */
649         g_return_if_fail (
650                 ((prop_value != NULL) && (error == NULL)) ||
651                 ((prop_value == NULL) && (error != NULL)));
652
653         /* In the event of an error, we pass an empty EList. */
654         elist = e_list_new (NULL, (EListFreeFunc) g_free, NULL);
655
656         if (prop_value != NULL) {
657                 gchar **strv;
658                 gint ii;
659
660                 strv = g_strsplit (prop_value, ",", -1);
661                 for (ii = 0; strv != NULL && strv[ii] != NULL; ii++) {
662                         gchar *utf8 = e_util_utf8_make_valid (strv[ii]);
663                         e_list_append (elist, utf8);
664                 }
665                 g_strfreev (strv);
666         }
667
668         if (cb != NULL && error == NULL)
669                 cb (data->book, E_BOOK_ERROR_OK, elist, data->closure);
670         if (cb != NULL && error != NULL)
671                 cb (data->book, error->code, elist, data->closure);
672         if (excb != NULL)
673                 excb (data->book, error, elist, data->closure);
674
675         g_object_unref (elist);
676
677         if (error != NULL)
678                 g_error_free (error);
679
680         g_object_unref (data->book);
681         g_slice_free (AsyncData, data);
682 }
683
684 /**
685  * e_book_async_get_required_fields:
686  * @book: an #EBook
687  * @cb: (scope async): function to call when the operation finishes
688  * @closure: data to pass to callback function
689  *
690  * Gets a list of fields that are required to be filled in for
691  * all contacts in this @book. This function does not block.
692  *
693  * Returns: %TRUE if the operation was started, %FALSE otherwise.
694  *
695  * Deprecated: 3.0: Use e_book_get_required_fields_async() instead.
696  **/
697 gboolean
698 e_book_async_get_required_fields (EBook *book,
699                                   EBookEListCallback cb,
700                                   gpointer closure)
701 {
702         AsyncData *data;
703
704         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
705
706         data = g_slice_new0 (AsyncData);
707         data->book = g_object_ref (book);
708         data->callback = cb;
709         data->closure = closure;
710
711         e_client_get_backend_property (
712                 E_CLIENT (book->priv->client),
713                 BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
714                 NULL, get_required_fields_reply, data);
715
716         return TRUE;
717 }
718
719 /**
720  * e_book_get_required_fields_async:
721  * @book: an #EBook
722  * @cb: (scope async): function to call when the operation finishes
723  * @closure: data to pass to callback function
724  *
725  * Gets a list of fields that are required to be filled in for
726  * all contacts in this @book. This function does not block.
727  *
728  * Returns: %TRUE if the operation was started, %FALSE otherwise.
729  *
730  * Since: 2.32
731  *
732  * Deprecated: 3.2: Use e_client_get_backend_property() and e_client_get_backend_property_finish()
733  * on an #EBookClient object with #BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
734  **/
735 gboolean
736 e_book_get_required_fields_async (EBook *book,
737                                   EBookEListAsyncCallback cb,
738                                   gpointer closure)
739 {
740         AsyncData *data;
741
742         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
743
744         data = g_slice_new0 (AsyncData);
745         data->book = g_object_ref (book);
746         data->excallback = cb;
747         data->closure = closure;
748
749         e_client_get_backend_property (
750                 E_CLIENT (book->priv->client),
751                 BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
752                 NULL, get_required_fields_reply, data);
753
754         return TRUE;
755 }
756
757 /**
758  * e_book_get_supported_fields:
759  * @book: an #EBook
760  * @fields: (out) (transfer full) (element-type utf8): a #GList of fields to set on success
761  * @error: a #GError to set on failure
762  *
763  * Gets a list of fields that can be stored for contacts
764  * in this @book. Other fields may be discarded. The list
765  * will contain pointers to allocated strings, and both the
766  * #GList and the strings must be freed by the caller.
767  *
768  * Returns: %TRUE if successful, %FALSE otherwise
769  *
770  * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
771  * an #EBookClient object with #BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
772  **/
773 gboolean
774 e_book_get_supported_fields (EBook *book,
775                              GList **fields,
776                              GError **error)
777 {
778         gchar *prop_value = NULL;
779         gboolean success;
780
781         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
782
783         if (fields != NULL)
784                 *fields = NULL;
785
786         success = e_client_get_backend_property_sync (
787                 E_CLIENT (book->priv->client),
788                 BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
789                 &prop_value, NULL, error);
790
791         if (success && fields != NULL) {
792                 GQueue queue = G_QUEUE_INIT;
793                 gchar **strv;
794                 gint ii;
795
796                 strv = g_strsplit (prop_value, ",", -1);
797
798                 for (ii = 0; strv != NULL && strv[ii] != NULL; ii++)
799                         g_queue_push_tail (&queue, strv[ii]);
800
801                 /* The GQueue now owns the strings in the string array,
802                  * so use g_free() instead of g_strfreev() to free just
803                  * the array itself. */
804                 g_free (strv);
805
806                 /* Transfer ownership of the GQueue content. */
807                 *fields = g_queue_peek_head_link (&queue);
808         }
809
810         g_free (prop_value);
811
812         return success;
813 }
814
815 static void
816 get_supported_fields_reply (GObject *source_object,
817                             GAsyncResult *result,
818                             gpointer user_data)
819 {
820         AsyncData *data = user_data;
821         EBookEListCallback cb = data->callback;
822         EBookEListAsyncCallback excb = data->excallback;
823         EList *elist;
824         gchar *prop_value = NULL;
825         GError *error = NULL;
826
827         e_client_get_backend_property_finish (
828                 E_CLIENT (source_object), result, &prop_value, &error);
829
830         /* Sanity check. */
831         g_return_if_fail (
832                 ((prop_value != NULL) && (error == NULL)) ||
833                 ((prop_value == NULL) && (error != NULL)));
834
835         /* In the event of an error, we pass an empty EList. */
836         elist = e_list_new (NULL, (EListFreeFunc) g_free, NULL);
837
838         if (prop_value != NULL) {
839                 gchar **strv;
840                 gint ii;
841
842                 strv = g_strsplit (prop_value, ",", -1);
843                 for (ii = 0; strv != NULL && strv[ii] != NULL; ii++) {
844                         gchar *utf8 = e_util_utf8_make_valid (strv[ii]);
845                         e_list_append (elist, utf8);
846                 }
847                 g_strfreev (strv);
848         }
849
850         if (cb != NULL && error == NULL)
851                 cb (data->book, E_BOOK_ERROR_OK, elist, data->closure);
852         if (cb != NULL && error != NULL)
853                 cb (data->book, error->code, elist, data->closure);
854         if (excb != NULL)
855                 excb (data->book, error, elist, data->closure);
856
857         g_object_unref (elist);
858
859         if (error != NULL)
860                 g_error_free (error);
861
862         g_object_unref (data->book);
863         g_slice_free (AsyncData, data);
864 }
865
866 /**
867  * e_book_async_get_supported_fields:
868  * @book: an #EBook
869  * @cb: (scope async): function to call when the operation finishes
870  * @closure: data to pass to callback function
871  *
872  * Gets a list of fields that can be stored for contacts
873  * in this @book. Other fields may be discarded. This
874  * function does not block.
875  *
876  * Returns: %TRUE if successful, %FALSE otherwise.
877  *
878  * Deprecated: 3.0: Use e_book_get_supported_fields_async() instead.
879  **/
880 gboolean
881 e_book_async_get_supported_fields (EBook *book,
882                                    EBookEListCallback cb,
883                                    gpointer closure)
884 {
885         AsyncData *data;
886
887         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
888
889         data = g_slice_new0 (AsyncData);
890         data->book = g_object_ref (book);
891         data->callback = cb;
892         data->closure = closure;
893
894         e_client_get_backend_property (
895                 E_CLIENT (book->priv->client),
896                 BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
897                 NULL, get_supported_fields_reply, data);
898
899         return TRUE;
900 }
901
902 /**
903  * e_book_get_supported_fields_async:
904  * @book: an #EBook
905  * @cb: (scope async): function to call when the operation finishes
906  * @closure: data to pass to callback function
907  *
908  * Gets a list of fields that can be stored for contacts
909  * in this @book. Other fields may be discarded. This
910  * function does not block.
911  *
912  * Returns: %TRUE if successful, %FALSE otherwise.
913  *
914  * Since: 2.32
915  *
916  * Deprecated: 3.2: Use e_client_get_backend_property() and e_client_get_backend_property_finish()
917  * on an #EBookClient object with #BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
918  **/
919 gboolean
920 e_book_get_supported_fields_async (EBook *book,
921                                    EBookEListAsyncCallback cb,
922                                    gpointer closure)
923 {
924         AsyncData *data;
925
926         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
927
928         data = g_slice_new0 (AsyncData);
929         data->book = g_object_ref (book);
930         data->excallback = cb;
931         data->closure = closure;
932
933         e_client_get_backend_property (
934                 E_CLIENT (book->priv->client),
935                 BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
936                 NULL, get_supported_fields_reply, data);
937
938         return TRUE;
939 }
940
941 /**
942  * e_book_get_supported_auth_methods:
943  * @book: an #EBook
944  * @auth_methods: (out) (transfer full) (element-type utf8): a #GList of auth methods to set on success
945  * @error: a #GError to set on failure
946  *
947  * Queries @book for the list of authentication methods it supports.
948  * The list will contain pointers to allocated strings, and both the
949  * #GList and the strings must be freed by the caller.
950  *
951  * Returns: %TRUE if successful, %FALSE otherwise
952  *
953  * Deprecated: 3.2: The property is no longer supported.
954  **/
955 gboolean
956 e_book_get_supported_auth_methods (EBook *book,
957                                    GList **auth_methods,
958                                    GError **error)
959 {
960         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
961
962         if (auth_methods != NULL)
963                 *auth_methods = NULL;
964
965         return TRUE;
966 }
967
968 /**
969  * e_book_async_get_supported_auth_methods:
970  * @book: an #EBook
971  * @cb: (scope async): function to call when the operation finishes
972  * @closure: data to pass to callback function
973  *
974  * Queries @book for the list of authentication methods it supports.
975  * This function does not block.
976  *
977  * Returns: %TRUE if successful, %FALSE otherwise.
978  *
979  * Deprecated: 3.0: The property is no longer supported.
980  **/
981 gboolean
982 e_book_async_get_supported_auth_methods (EBook *book,
983                                          EBookEListCallback cb,
984                                          gpointer closure)
985 {
986         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
987
988         if (cb != NULL) {
989                 /* Pass the callback an empty list. */
990                 EList *elist = e_list_new (NULL, NULL, NULL);
991                 cb (book, E_BOOK_ERROR_OK, elist, closure);
992                 g_object_unref (elist);
993         }
994
995         return TRUE;
996 }
997
998 /**
999  * e_book_get_supported_auth_methods_async:
1000  * @book: an #EBook
1001  * @cb: (scope async): function to call when the operation finishes
1002  * @closure: data to pass to callback function
1003  *
1004  * Queries @book for the list of authentication methods it supports.
1005  * This function does not block.
1006  *
1007  * Returns: %TRUE if successful, %FALSE otherwise.
1008  *
1009  * Since: 2.32
1010  *
1011  * Deprecated: 3.2: The property is no longer supported.
1012  **/
1013 gboolean
1014 e_book_get_supported_auth_methods_async (EBook *book,
1015                                          EBookEListAsyncCallback cb,
1016                                          gpointer closure)
1017 {
1018         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1019
1020         if (cb != NULL) {
1021                 /* Pass the callback an empty list. */
1022                 EList *elist = e_list_new (NULL, NULL, NULL);
1023                 cb (book, NULL, elist, closure);
1024                 g_object_unref (elist);
1025         }
1026
1027         return TRUE;
1028 }
1029
1030 /**
1031  * e_book_get_contact:
1032  * @book: an #EBook
1033  * @id: a unique string ID specifying the contact
1034  * @contact: (out) (transfer full): an #EContact
1035  * @error: a #GError to set on failure
1036  *
1037  * Fills in @contact with the contents of the vcard in @book
1038  * corresponding to @id.
1039  *
1040  * Returns: %TRUE if successful, %FALSE otherwise
1041  *
1042  * Deprecated: 3.2: Use e_book_client_get_contact_sync() instead.
1043  **/
1044 gboolean
1045 e_book_get_contact (EBook *book,
1046                     const gchar *id,
1047                     EContact **contact,
1048                     GError **error)
1049 {
1050         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1051         g_return_val_if_fail (id != NULL, FALSE);
1052         g_return_val_if_fail (contact != NULL, FALSE);
1053
1054         return e_book_client_get_contact_sync (
1055                 book->priv->client, id, contact, NULL, error);
1056 }
1057
1058 static void
1059 get_contact_reply (GObject *source_object,
1060                    GAsyncResult *result,
1061                    gpointer user_data)
1062 {
1063         AsyncData *data = user_data;
1064         EBookContactCallback cb = data->callback;
1065         EBookContactAsyncCallback excb = data->excallback;
1066         EContact *contact = NULL;
1067         GError *error = NULL;
1068
1069         e_book_client_get_contact_finish (
1070                 E_BOOK_CLIENT (source_object), result, &contact, &error);
1071
1072         if (cb != NULL && error == NULL)
1073                 cb (data->book, E_BOOK_ERROR_OK, contact, data->closure);
1074         if (cb != NULL && error != NULL)
1075                 cb (data->book, error->code, NULL, data->closure);
1076         if (excb != NULL)
1077                 excb (data->book, error, contact, data->closure);
1078
1079         if (contact != NULL)
1080                 g_object_unref (contact);
1081
1082         if (error != NULL)
1083                 g_error_free (error);
1084
1085         g_object_unref (data->book);
1086         g_slice_free (AsyncData, data);
1087 }
1088
1089 /**
1090  * e_book_async_get_contact:
1091  * @book: an #EBook
1092  * @id: a unique string ID specifying the contact
1093  * @cb: (scope async): function to call when operation finishes
1094  * @closure: data to pass to callback function
1095  *
1096  * Retrieves a contact specified by @id from @book.
1097  *
1098  * Returns: %FALSE if successful, %TRUE otherwise
1099  *
1100  * Deprecated: 3.0: Use e_book_get_contact_async() instead.
1101  **/
1102 gboolean
1103 e_book_async_get_contact (EBook *book,
1104                           const gchar *id,
1105                           EBookContactCallback cb,
1106                           gpointer closure)
1107 {
1108         AsyncData *data;
1109
1110         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1111         g_return_val_if_fail (id != NULL, FALSE);
1112
1113         data = g_slice_new0 (AsyncData);
1114         data->book = g_object_ref (book);
1115         data->callback = cb;
1116         data->closure = closure;
1117
1118         e_book_client_get_contact (
1119                 E_BOOK_CLIENT (book->priv->client),
1120                 id, NULL, get_contact_reply, data);
1121
1122         return TRUE;
1123 }
1124
1125 /**
1126  * e_book_get_contact_async:
1127  * @book: an #EBook
1128  * @id: a unique string ID specifying the contact
1129  * @cb: (scope async): function to call when operation finishes
1130  * @closure: data to pass to callback function
1131  *
1132  * Retrieves a contact specified by @id from @book.
1133  *
1134  * Returns: %FALSE if successful, %TRUE otherwise
1135  *
1136  * Since: 2.32
1137  *
1138  * Deprecated: 3.2: Use e_book_client_get_contact() and e_book_client_get_contact_finish() instead.
1139  **/
1140 gboolean
1141 e_book_get_contact_async (EBook *book,
1142                           const gchar *id,
1143                           EBookContactAsyncCallback cb,
1144                           gpointer closure)
1145 {
1146         AsyncData *data;
1147
1148         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1149         g_return_val_if_fail (id != NULL, FALSE);
1150
1151         data = g_slice_new0 (AsyncData);
1152         data->book = g_object_ref (book);
1153         data->excallback = cb;
1154         data->closure = closure;
1155
1156         e_book_client_get_contact (
1157                 E_BOOK_CLIENT (book->priv->client),
1158                 id, NULL, get_contact_reply, data);
1159
1160         return TRUE;
1161 }
1162
1163 /**
1164  * e_book_remove_contact:
1165  * @book: an #EBook
1166  * @id: a string
1167  * @error: a #GError to set on failure
1168  *
1169  * Removes the contact with id @id from @book.
1170  *
1171  * Returns: %TRUE if successful, %FALSE otherwise
1172  *
1173  * Deprecated: 3.2: Use e_book_client_remove_contact_by_uid_sync() or e_book_client_remove_contact_sync() instead.
1174  **/
1175 gboolean
1176 e_book_remove_contact (EBook *book,
1177                        const gchar *id,
1178                        GError **error)
1179 {
1180         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1181         g_return_val_if_fail (id != NULL, FALSE);
1182
1183         return e_book_client_remove_contact_by_uid_sync (
1184                 book->priv->client, id, NULL, error);
1185 }
1186
1187 static void
1188 remove_contact_reply (GObject *source_object,
1189                       GAsyncResult *result,
1190                       gpointer user_data)
1191 {
1192         AsyncData *data = user_data;
1193         EBookCallback cb = data->callback;
1194         EBookAsyncCallback excb = data->excallback;
1195         GError *error = NULL;
1196
1197         e_book_client_remove_contact_finish (
1198                 E_BOOK_CLIENT (source_object), result, &error);
1199
1200         if (cb != NULL && error == NULL)
1201                 cb (data->book, E_BOOK_ERROR_OK, data->closure);
1202         if (cb != NULL && error != NULL)
1203                 cb (data->book, error->code, data->closure);
1204         if (excb != NULL)
1205                 excb (data->book, error, data->closure);
1206
1207         if (error != NULL)
1208                 g_error_free (error);
1209
1210         g_object_unref (data->book);
1211         g_slice_free (AsyncData, data);
1212 }
1213
1214 /**
1215  * e_book_remove_contacts:
1216  * @book: an #EBook
1217  * @ids: (element-type utf8): an #GList of const gchar *id's
1218  * @error: a #GError to set on failure
1219  *
1220  * Removes the contacts with ids from the list @ids from @book.  This is
1221  * always more efficient than calling e_book_remove_contact() if you
1222  * have more than one id to remove, as some backends can implement it
1223  * as a batch request.
1224  *
1225  * Returns: %TRUE if successful, %FALSE otherwise
1226  *
1227  * Deprecated: 3.2: Use e_book_client_remove_contacts_sync() instead.
1228  **/
1229 gboolean
1230 e_book_remove_contacts (EBook *book,
1231                         GList *ids,
1232                         GError **error)
1233 {
1234         GSList *slist = NULL;
1235         gboolean success;
1236
1237         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1238         g_return_val_if_fail (ids != NULL, FALSE);
1239
1240         /* XXX Never use GSList in a public API. */
1241         while (ids != NULL) {
1242                 slist = g_slist_prepend (slist, ids->data);
1243                 ids = g_list_next (ids);
1244         }
1245         slist = g_slist_reverse (slist);
1246
1247         success = e_book_client_remove_contacts_sync (
1248                 book->priv->client, slist, NULL, error);
1249
1250         g_slist_free (slist);
1251
1252         return success;
1253 }
1254
1255 /**
1256  * e_book_async_remove_contact:
1257  * @book: an #EBook
1258  * @contact: an #EContact
1259  * @cb: (scope async): a function to call when the operation finishes
1260  * @closure: data to pass to callback function
1261  *
1262  * Removes @contact from @book.
1263  *
1264  * Returns: %TRUE if successful, %FALSE otherwise
1265  *
1266  * Deprecated: 3.0: Use e_book_remove_contact_async() instead.
1267  **/
1268 gboolean
1269 e_book_async_remove_contact (EBook *book,
1270                              EContact *contact,
1271                              EBookCallback cb,
1272                              gpointer closure)
1273 {
1274         AsyncData *data;
1275
1276         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1277         g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
1278
1279         data = g_slice_new0 (AsyncData);
1280         data->book = g_object_ref (book);
1281         data->callback = cb;
1282         data->closure = closure;
1283
1284         e_book_client_remove_contact (
1285                 E_BOOK_CLIENT (book->priv->client),
1286                 contact, NULL, remove_contact_reply, data);
1287
1288         return TRUE;
1289 }
1290
1291 /**
1292  * e_book_remove_contact_async:
1293  * @book: an #EBook
1294  * @contact: an #EContact
1295  * @cb: (scope async): a function to call when the operation finishes
1296  * @closure: data to pass to callback function
1297  *
1298  * Removes @contact from @book.
1299  *
1300  * Returns: %TRUE if successful, %FALSE otherwise
1301  *
1302  * Since: 2.32
1303  *
1304  * Deprecated: 3.2: Use e_book_client_remove_contact() and e_book_client_remove_contact_finish() instead.
1305  **/
1306 gboolean
1307 e_book_remove_contact_async (EBook *book,
1308                              EContact *contact,
1309                              EBookAsyncCallback cb,
1310                              gpointer closure)
1311 {
1312         AsyncData *data;
1313
1314         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1315         g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
1316
1317         data = g_slice_new0 (AsyncData);
1318         data->book = g_object_ref (book);
1319         data->excallback = cb;
1320         data->closure = closure;
1321
1322         e_book_client_remove_contact (
1323                 E_BOOK_CLIENT (book->priv->client),
1324                 contact, NULL, remove_contact_reply, data);
1325
1326         return TRUE;
1327 }
1328
1329 static void
1330 remove_contact_by_id_reply (GObject *source_object,
1331                             GAsyncResult *result,
1332                             gpointer user_data)
1333 {
1334         AsyncData *data = user_data;
1335         EBookCallback cb = data->callback;
1336         EBookAsyncCallback excb = data->excallback;
1337         GError *error = NULL;
1338
1339         e_book_client_remove_contact_by_uid_finish (
1340                 E_BOOK_CLIENT (source_object), result, &error);
1341
1342         if (cb != NULL && error == NULL)
1343                 cb (data->book, E_BOOK_ERROR_OK, data->closure);
1344         if (cb != NULL && error != NULL)
1345                 cb (data->book, error->code, data->closure);
1346         if (excb != NULL)
1347                 excb (data->book, error, data->closure);
1348
1349         if (error != NULL)
1350                 g_error_free (error);
1351
1352         g_object_unref (data->book);
1353         g_slice_free (AsyncData, data);
1354 }
1355
1356 /**
1357  * e_book_async_remove_contact_by_id:
1358  * @book: an #EBook
1359  * @id: a unique ID string specifying the contact
1360  * @cb: (scope async): a function to call when the operation finishes
1361  * @closure: data to pass to callback function
1362  *
1363  * Removes the contact with id @id from @book.
1364  *
1365  * Returns: %TRUE if successful, %FALSE otherwise
1366  *
1367  * Deprecated: 3.0: Use e_book_remove_contact_by_id_async() instead.
1368  **/
1369 gboolean
1370 e_book_async_remove_contact_by_id (EBook *book,
1371                                    const gchar *id,
1372                                    EBookCallback cb,
1373                                    gpointer closure)
1374 {
1375         AsyncData *data;
1376
1377         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1378         g_return_val_if_fail (id != NULL, FALSE);
1379
1380         data = g_slice_new0 (AsyncData);
1381         data->book = g_object_ref (book);
1382         data->callback = cb;
1383         data->closure = closure;
1384
1385         e_book_client_remove_contact_by_uid (
1386                 E_BOOK_CLIENT (book->priv->client),
1387                 id, NULL, remove_contact_by_id_reply, data);
1388
1389         return TRUE;
1390 }
1391
1392 /**
1393  * e_book_remove_contact_by_id_async:
1394  * @book: an #EBook
1395  * @id: a unique ID string specifying the contact
1396  * @cb: (scope async): a function to call when the operation finishes
1397  * @closure: data to pass to callback function
1398  *
1399  * Removes the contact with id @id from @book.
1400  *
1401  * Returns: %TRUE if successful, %FALSE otherwise
1402  *
1403  * Since: 2.32
1404  *
1405  * Deprecated: 3.2: Use e_book_client_remove_contact_by_uid() and e_book_client_remove_contact_by_uid_finish() instead.
1406  **/
1407 gboolean
1408 e_book_remove_contact_by_id_async (EBook *book,
1409                                    const gchar *id,
1410                                    EBookAsyncCallback cb,
1411                                    gpointer closure)
1412 {
1413         AsyncData *data;
1414
1415         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1416         g_return_val_if_fail (id != NULL, FALSE);
1417
1418         data = g_slice_new0 (AsyncData);
1419         data->book = g_object_ref (book);
1420         data->excallback = cb;
1421         data->closure = closure;
1422
1423         e_book_client_remove_contact_by_uid (
1424                 E_BOOK_CLIENT (book->priv->client),
1425                 id, NULL, remove_contact_by_id_reply, data);
1426
1427         return TRUE;
1428 }
1429
1430 static void
1431 remove_contacts_reply (GObject *source_object,
1432                        GAsyncResult *result,
1433                        gpointer user_data)
1434 {
1435         AsyncData *data = user_data;
1436         EBookCallback cb = data->callback;
1437         EBookAsyncCallback excb = data->excallback;
1438         GError *error = NULL;
1439
1440         e_book_client_remove_contacts_finish (
1441                 E_BOOK_CLIENT (source_object), result, &error);
1442
1443         if (cb != NULL && error == NULL)
1444                 cb (data->book, E_BOOK_ERROR_OK, data->closure);
1445         if (cb != NULL && error != NULL)
1446                 cb (data->book, error->code, data->closure);
1447         if (excb != NULL)
1448                 excb (data->book, error, data->closure);
1449
1450         if (error != NULL)
1451                 g_error_free (error);
1452
1453         g_object_unref (data->book);
1454         g_slice_free (AsyncData, data);
1455 }
1456
1457 /**
1458  * e_book_async_remove_contacts:
1459  * @book: an #EBook
1460  * @ids: (element-type utf8): a #GList of const gchar *id's
1461  * @cb: (scope async): a function to call when the operation finishes
1462  * @closure: data to pass to callback function
1463  *
1464  * Removes the contacts with ids from the list @ids from @book.  This is
1465  * always more efficient than calling e_book_remove_contact() if you
1466  * have more than one id to remove, as some backends can implement it
1467  * as a batch request.
1468  *
1469  * Returns: %TRUE if successful, %FALSE otherwise
1470  *
1471  * Deprecated: 3.0: Use e_book_remove_contacts_async() instead.
1472  **/
1473 gboolean
1474 e_book_async_remove_contacts (EBook *book,
1475                               GList *ids,
1476                               EBookCallback cb,
1477                               gpointer closure)
1478 {
1479         AsyncData *data;
1480         GSList *slist = NULL;
1481
1482         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1483
1484         data = g_slice_new0 (AsyncData);
1485         data->book = g_object_ref (book);
1486         data->callback = cb;
1487         data->closure = closure;
1488
1489         /* XXX Never use GSList in a public API. */
1490         while (ids != NULL) {
1491                 slist = g_slist_prepend (slist, ids->data);
1492                 ids = g_list_next (ids);
1493         }
1494         slist = g_slist_reverse (slist);
1495
1496         e_book_client_remove_contacts (
1497                 E_BOOK_CLIENT (book->priv->client),
1498                 slist, NULL, remove_contacts_reply, data);
1499
1500         g_slist_free (slist);
1501
1502         return TRUE;
1503 }
1504
1505 /**
1506  * e_book_remove_contacts_async:
1507  * @book: an #EBook
1508  * @ids: (element-type utf8): a #GList of const gchar *id's
1509  * @cb: (scope async): a function to call when the operation finishes
1510  * @closure: data to pass to callback function
1511  *
1512  * Removes the contacts with ids from the list @ids from @book.  This is
1513  * always more efficient than calling e_book_remove_contact() if you
1514  * have more than one id to remove, as some backends can implement it
1515  * as a batch request.
1516  *
1517  * Returns: %TRUE if successful, %FALSE otherwise
1518  *
1519  * Since: 2.32
1520  *
1521  * Deprecated: 3.2: Use e_book_client_remove_contacts() and e_book_client_remove_contacts_finish() instead.
1522  **/
1523 gboolean
1524 e_book_remove_contacts_async (EBook *book,
1525                               GList *ids,
1526                               EBookAsyncCallback cb,
1527                               gpointer closure)
1528 {
1529         AsyncData *data;
1530         GSList *slist = NULL;
1531
1532         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1533
1534         data = g_slice_new0 (AsyncData);
1535         data->book = g_object_ref (book);
1536         data->excallback = cb;
1537         data->closure = closure;
1538
1539         /* XXX Never use GSList in a public API. */
1540         while (ids != NULL) {
1541                 slist = g_slist_prepend (slist, ids->data);
1542                 ids = g_list_next (ids);
1543         }
1544         slist = g_slist_reverse (slist);
1545
1546         e_book_client_remove_contacts (
1547                 E_BOOK_CLIENT (book->priv->client),
1548                 slist, NULL, remove_contacts_reply, data);
1549
1550         g_slist_free (slist);
1551
1552         return TRUE;
1553 }
1554
1555 /**
1556  * e_book_get_book_view:
1557  * @book: an #EBook
1558  * @query: an #EBookQuery
1559  * @requested_fields: (allow-none) (element-type utf8): a #GList containing the names of fields to
1560  * return, or NULL for all
1561  * @max_results: the maximum number of contacts to show (or 0 for all)
1562  * @book_view: (out): A #EBookView pointer, will be set to the view
1563  * @error: a #GError to set on failure
1564  *
1565  * Query @book with @query, creating a #EBookView in @book_view with the fields
1566  * specified by @requested_fields and limited at @max_results records. On an
1567  * error, @error is set and %FALSE returned.
1568  *
1569  * Returns: %TRUE if successful, %FALSE otherwise
1570  *
1571  * Deprecated: 3.2: Use e_book_client_get_view_sync() instead.
1572  **/
1573 gboolean
1574 e_book_get_book_view (EBook *book,
1575                       EBookQuery *query,
1576                       GList *requested_fields,
1577                       gint max_results,
1578                       EBookView **book_view,
1579                       GError **error)
1580 {
1581         EBookClientView *client_view = NULL;
1582         gchar *sexp;
1583         gboolean success;
1584
1585         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1586         g_return_val_if_fail (query != NULL, FALSE);
1587         g_return_val_if_fail (book_view != NULL, FALSE);
1588
1589         sexp = e_book_query_to_string (query);
1590
1591         success = e_book_client_get_view_sync (
1592                 book->priv->client, sexp, &client_view, NULL, error);
1593
1594         g_free (sexp);
1595
1596         /* Sanity check. */
1597         g_return_val_if_fail (
1598                 (success && (client_view != NULL)) ||
1599                 (!success && (client_view == NULL)), FALSE);
1600
1601         if (client_view != NULL) {
1602                 *book_view = _e_book_view_new (book, client_view);
1603                 g_object_unref (client_view);
1604         }
1605
1606         return success;
1607 }
1608
1609 static void
1610 get_book_view_reply (GObject *source_object,
1611                      GAsyncResult *result,
1612                      gpointer user_data)
1613 {
1614         AsyncData *data = user_data;
1615         EBookBookViewCallback cb = data->callback;
1616         EBookBookViewAsyncCallback excb = data->excallback;
1617         EBookClientView *client_view = NULL;
1618         EBookView *view = NULL;
1619         GError *error = NULL;
1620
1621         e_book_client_get_view_finish (
1622                 E_BOOK_CLIENT (source_object),
1623                 result, &client_view, &error);
1624
1625         /* Sanity check. */
1626         g_return_if_fail (
1627                 ((client_view != NULL) && (error == NULL)) ||
1628                 ((client_view == NULL) && (error != NULL)));
1629
1630         if (client_view != NULL) {
1631                 view = _e_book_view_new (data->book, client_view);
1632                 g_object_unref (client_view);
1633         }
1634
1635         if (cb != NULL && error == NULL)
1636                 cb (data->book, E_BOOK_ERROR_OK, view, data->closure);
1637         if (cb != NULL && error != NULL)
1638                 cb (data->book, error->code, NULL, data->closure);
1639         if (excb != NULL)
1640                 excb (data->book, error, view, data->closure);
1641
1642         if (error != NULL)
1643                 g_error_free (error);
1644
1645         g_object_unref (data->book);
1646         g_slice_free (AsyncData, data);
1647 }
1648
1649 /**
1650  * e_book_async_get_book_view:
1651  * @book: an #EBook
1652  * @query: an #EBookQuery
1653  * @requested_fields: (element-type utf8): a #GList containing the names of fields to return, or NULL for all
1654  * @max_results: the maximum number of contacts to show (or 0 for all)
1655  * @cb: (scope async): a function to call when the operation finishes
1656  * @closure: data to pass to callback function
1657  *
1658  * Query @book with @query, creating a #EBookView with the fields
1659  * specified by @requested_fields and limited at @max_results records.
1660  *
1661  * Returns: %FALSE if successful, %TRUE otherwise
1662  *
1663  * Deprecated: 3.0: Use e_book_get_book_view_async() instead.
1664  **/
1665 gboolean
1666 e_book_async_get_book_view (EBook *book,
1667                             EBookQuery *query,
1668                             GList *requested_fields,
1669                             gint max_results,
1670                             EBookBookViewCallback cb,
1671                             gpointer closure)
1672 {
1673         AsyncData *data;
1674         gchar *sexp;
1675
1676         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1677         g_return_val_if_fail (query != NULL, FALSE);
1678
1679         data = g_slice_new0 (AsyncData);
1680         data->book = g_object_ref (book);
1681         data->callback = cb;
1682         data->closure = closure;
1683
1684         sexp = e_book_query_to_string (query);
1685
1686         e_book_client_get_view (
1687                 book->priv->client, sexp,
1688                 NULL, get_book_view_reply, data);
1689
1690         g_free (sexp);
1691
1692         return TRUE;
1693 }
1694
1695 /**
1696  * e_book_get_book_view_async:
1697  * @book: an #EBook
1698  * @query: an #EBookQuery
1699  * @requested_fields: (allow-none) (element-type utf8): a #GList containing the names of fields to
1700  * return, or NULL for all
1701  * @max_results: the maximum number of contacts to show (or 0 for all)
1702  * @cb: (scope async): a function to call when the operation finishes
1703  * @closure: data to pass to callback function
1704  *
1705  * Query @book with @query, creating a #EBookView with the fields
1706  * specified by @requested_fields and limited at @max_results records.
1707  *
1708  * Returns: %FALSE if successful, %TRUE otherwise
1709  *
1710  * Since: 2.32
1711  *
1712  * Deprecated: 3.2: Use e_book_client_get_view() and e_book_client_get_view_finish() instead.
1713  **/
1714 gboolean
1715 e_book_get_book_view_async (EBook *book,
1716                             EBookQuery *query,
1717                             GList *requested_fields,
1718                             gint max_results,
1719                             EBookBookViewAsyncCallback cb,
1720                             gpointer closure)
1721 {
1722         AsyncData *data;
1723         gchar *sexp;
1724
1725         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1726         g_return_val_if_fail (query != NULL, FALSE);
1727
1728         data = g_slice_new0 (AsyncData);
1729         data->book = g_object_ref (book);
1730         data->excallback = cb;
1731         data->closure = closure;
1732
1733         sexp = e_book_query_to_string (query);
1734
1735         e_book_client_get_view (
1736                 book->priv->client, sexp,
1737                 NULL, get_book_view_reply, data);
1738
1739         g_free (sexp);
1740
1741         return TRUE;
1742 }
1743
1744 /**
1745  * e_book_get_contacts:
1746  * @book: an #EBook
1747  * @query: an #EBookQuery
1748  * @contacts: (element-type utf8): a #GList pointer, will be set to the list of contacts
1749  * @error: a #GError to set on failure
1750  *
1751  * Query @book with @query, setting @contacts to the list of contacts which
1752  * matched. On failed, @error will be set and %FALSE returned.
1753  *
1754  * Returns: %TRUE on success, %FALSE otherwise
1755  *
1756  * Deprecated: 3.2: Use e_book_client_get_contacts_sync() instead.
1757  **/
1758 gboolean
1759 e_book_get_contacts (EBook *book,
1760                      EBookQuery *query,
1761                      GList **contacts,
1762                      GError **error)
1763 {
1764         GSList *slist = NULL;
1765         gchar *sexp;
1766         gboolean success;
1767
1768         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1769         g_return_val_if_fail (query != NULL, FALSE);
1770
1771         if (contacts != NULL)
1772                 *contacts = NULL;
1773
1774         sexp = e_book_query_to_string (query);
1775
1776         success = e_book_client_get_contacts_sync (
1777                 E_BOOK_CLIENT (book->priv->client),
1778                 sexp, &slist, NULL, error);
1779
1780         g_free (sexp);
1781
1782         /* XXX Never use GSList in a public API. */
1783         if (success && contacts != NULL) {
1784                 GList *list = NULL;
1785                 GSList *link;
1786
1787                 for (link = slist; link != NULL; link = g_slist_next (link)) {
1788                         EContact *contact = E_CONTACT (link->data);
1789                         list = g_list_prepend (list, g_object_ref (contact));
1790                 }
1791
1792                 *contacts = g_list_reverse (list);
1793         }
1794
1795         g_slist_free_full (slist, (GDestroyNotify) g_object_unref);
1796
1797         return success;
1798 }
1799
1800 static void
1801 get_contacts_reply (GObject *source_object,
1802                     GAsyncResult *result,
1803                     gpointer user_data)
1804 {
1805         AsyncData *data = user_data;
1806         EBookListAsyncCallback excb = data->excallback;
1807         EBookListCallback cb = data->callback;
1808         GSList *slist = NULL;
1809         GList *list = NULL;
1810         GError *error = NULL;
1811
1812         e_book_client_get_contacts_finish (
1813                 E_BOOK_CLIENT (source_object), result, &slist, &error);
1814
1815         /* XXX Never use GSList in a public API. */
1816         if (error == NULL) {
1817                 GSList *link;
1818
1819                 for (link = slist; link != NULL; link = g_slist_next (link)) {
1820                         EContact *contact = E_CONTACT (link->data);
1821                         list = g_list_prepend (list, g_object_ref (contact));
1822                 }
1823
1824                 list = g_list_reverse (list);
1825         }
1826
1827         if (cb != NULL && error == NULL)
1828                 cb (data->book, E_BOOK_ERROR_OK, list, data->closure);
1829         if (cb != NULL && error != NULL)
1830                 cb (data->book, error->code, list, data->closure);
1831         if (excb != NULL)
1832                 excb (data->book, error, list, data->closure);
1833
1834         g_list_free_full (list, (GDestroyNotify) g_object_unref);
1835         g_slist_free_full (slist, (GDestroyNotify) g_object_unref);
1836
1837         if (error != NULL)
1838                 g_error_free (error);
1839
1840         g_object_unref (data->book);
1841         g_slice_free (AsyncData, data);
1842 }
1843
1844 /**
1845  * e_book_async_get_contacts:
1846  * @book: an #EBook
1847  * @query: an #EBookQuery
1848  * @cb: (scope async): a function to call when the operation finishes
1849  * @closure: data to pass to callback function
1850  *
1851  * Query @book with @query.
1852  *
1853  * Returns: %FALSE on success, %TRUE otherwise
1854  *
1855  * Deprecated: 3.0: Use e_book_get_contacts_async() instead.
1856  **/
1857 gboolean
1858 e_book_async_get_contacts (EBook *book,
1859                            EBookQuery *query,
1860                            EBookListCallback cb,
1861                            gpointer closure)
1862 {
1863         AsyncData *data;
1864         gchar *sexp;
1865
1866         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1867         g_return_val_if_fail (query != NULL, FALSE);
1868
1869         data = g_slice_new0 (AsyncData);
1870         data->book = g_object_ref (book);
1871         data->callback = cb;
1872         data->closure = closure;
1873
1874         sexp = e_book_query_to_string (query);
1875
1876         e_book_client_get_contacts (
1877                 E_BOOK_CLIENT (book->priv->client),
1878                 sexp, NULL, get_contacts_reply, data);
1879
1880         g_free (sexp);
1881
1882         return TRUE;
1883 }
1884
1885 /**
1886  * e_book_get_contacts_async:
1887  * @book: an #EBook
1888  * @query: an #EBookQuery
1889  * @cb: (scope async): a function to call when the operation finishes
1890  * @closure: data to pass to callback function
1891  *
1892  * Query @book with @query.
1893  *
1894  * Returns: %FALSE on success, %TRUE otherwise
1895  *
1896  * Since: 2.32
1897  *
1898  * Deprecated: 3.2: Use e_book_client_get_contacts() and e_book_client_get_contacts_finish() instead.
1899  **/
1900 gboolean
1901 e_book_get_contacts_async (EBook *book,
1902                            EBookQuery *query,
1903                            EBookListAsyncCallback cb,
1904                            gpointer closure)
1905 {
1906         AsyncData *data;
1907         gchar *sexp;
1908
1909         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1910         g_return_val_if_fail (query != NULL, FALSE);
1911
1912         data = g_slice_new0 (AsyncData);
1913         data->book = g_object_ref (book);
1914         data->excallback = cb;
1915         data->closure = closure;
1916
1917         sexp = e_book_query_to_string (query);
1918
1919         e_book_client_get_contacts (
1920                 E_BOOK_CLIENT (book->priv->client),
1921                 sexp, NULL, get_contacts_reply, data);
1922
1923         g_free (sexp);
1924
1925         return TRUE;
1926 }
1927
1928 /**
1929  * e_book_get_changes: (skip)
1930  * @book: an #EBook
1931  * @changeid:  the change ID
1932  * @changes: (out) (transfer full): return location for a #GList of #EBookChange items
1933  * @error: a #GError to set on failure.
1934  *
1935  * Get the set of changes since the previous call to e_book_get_changes()
1936  * for a given change ID.
1937  *
1938  * Returns: %TRUE on success, %FALSE otherwise
1939  *
1940  * Deprecated: 3.2: This function has been dropped completely.
1941  */
1942 gboolean
1943 e_book_get_changes (EBook *book,
1944                     const gchar *changeid,
1945                     GList **changes,
1946                     GError **error)
1947 {
1948         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1949
1950         g_set_error (
1951                 error, E_BOOK_ERROR,
1952                 E_BOOK_ERROR_NOT_SUPPORTED,
1953                 "Not supported");
1954
1955         return FALSE;
1956 }
1957
1958 /**
1959  * e_book_async_get_changes:
1960  * @book: an #EBook
1961  * @changeid:  the change ID
1962  * @cb: (scope async): function to call when operation finishes
1963  * @closure: data to pass to callback function
1964  *
1965  * Get the set of changes since the previous call to
1966  * e_book_async_get_changes() for a given change ID.
1967  *
1968  * Returns: %TRUE on success, %FALSE otherwise
1969  *
1970  * Deprecated: 3.0: Use e_book_get_changes_async() instead.
1971  */
1972 gboolean
1973 e_book_async_get_changes (EBook *book,
1974                           const gchar *changeid,
1975                           EBookListCallback cb,
1976                           gpointer closure)
1977 {
1978         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
1979
1980         cb (book, E_BOOK_ERROR_NOT_SUPPORTED, NULL, closure);
1981
1982         return TRUE;
1983 }
1984
1985 /**
1986  * e_book_get_changes_async:
1987  * @book: an #EBook
1988  * @changeid:  the change ID
1989  * @cb: (scope async): function to call when operation finishes
1990  * @closure: data to pass to callback function
1991  *
1992  * Get the set of changes since the previous call to
1993  * e_book_async_get_changes() for a given change ID.
1994  *
1995  * Returns: %TRUE on success, %FALSE otherwise
1996  *
1997  * Since: 2.32
1998  *
1999  * Deprecated: 3.2: This function has been dropped completely.
2000  */
2001 gboolean
2002 e_book_get_changes_async (EBook *book,
2003                           const gchar *changeid,
2004                           EBookListAsyncCallback cb,
2005                           gpointer closure)
2006 {
2007         GError *error;
2008
2009         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2010
2011         error = g_error_new (
2012                 E_BOOK_ERROR,
2013                 E_BOOK_ERROR_NOT_SUPPORTED,
2014                 "Not supported");
2015
2016         cb (book, error, NULL, closure);
2017
2018         g_error_free (error);
2019
2020         return TRUE;
2021 }
2022
2023 /**
2024  * e_book_free_change_list:
2025  * @change_list: (element-type EBookChange): a #GList of #EBookChange items
2026  *
2027  * Free the contents of #change_list, and the list itself.
2028  *
2029  * Deprecated: 3.2: Related function has been dropped completely.
2030  */
2031 void
2032 e_book_free_change_list (GList *change_list)
2033 {
2034         GList *l;
2035         for (l = change_list; l; l = l->next) {
2036                 EBookChange *change = l->data;
2037
2038                 g_object_unref (change->contact);
2039                 g_slice_free (EBookChange, change);
2040         }
2041
2042         g_list_free (change_list);
2043 }
2044
2045 /**
2046  * e_book_cancel:
2047  * @book: an #EBook
2048  * @error: a #GError to set on failure
2049  *
2050  * Used to cancel an already running operation on @book.  This
2051  * function makes a synchronous CORBA to the backend telling it to
2052  * cancel the operation.  If the operation wasn't cancellable (either
2053  * transiently or permanently) or had already comopleted on the server
2054  * side, this function will return E_BOOK_STATUS_COULD_NOT_CANCEL, and
2055  * the operation will continue uncancelled.  If the operation could be
2056  * cancelled, this function will return E_BOOK_ERROR_OK, and the
2057  * blocked e_book function corresponding to current operation will
2058  * return with a status of E_BOOK_STATUS_CANCELLED.
2059  *
2060  * Returns: %TRUE on success, %FALSE otherwise
2061  *
2062  * Deprecated: 3.2: Use e_client_cancel_all() or e_client_cancel_op() on an #EBookClient object instead.
2063  **/
2064 gboolean
2065 e_book_cancel (EBook *book,
2066                GError **error)
2067 {
2068         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2069
2070         e_client_cancel_all (E_CLIENT (book->priv->client));
2071
2072         return TRUE;
2073 }
2074
2075 /**
2076  * e_book_cancel_async_op:
2077  *
2078  * Similar to above e_book_cancel function, only cancels last, still running,
2079  * asynchronous operation.
2080  *
2081  * Since: 2.24
2082  *
2083  * Deprecated: 3.2: Use e_client_cancel_all() or e_client_cancel_op() on an #EBookClient object instead.
2084  **/
2085 gboolean
2086 e_book_cancel_async_op (EBook *book,
2087                         GError **error)
2088 {
2089         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2090
2091         e_client_cancel_all (E_CLIENT (book->priv->client));
2092
2093         return TRUE;
2094 }
2095
2096 /**
2097  * e_book_open:
2098  * @book: an #EBook
2099  * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
2100  * @error: a #GError to set on failure
2101  *
2102  * Opens the addressbook, making it ready for queries and other operations.
2103  *
2104  * Returns: %TRUE if the book was successfully opened, %FALSE otherwise.
2105  *
2106  * Deprecated: 3.2: Use e_client_open_sync() on an #EBookClient object instead.
2107  */
2108 gboolean
2109 e_book_open (EBook *book,
2110              gboolean only_if_exists,
2111              GError **error)
2112 {
2113         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2114
2115         return e_client_open_sync (
2116                 E_CLIENT (book->priv->client),
2117                 only_if_exists, NULL, error);
2118 }
2119
2120 static void
2121 open_reply (GObject *source_object,
2122             GAsyncResult *result,
2123             gpointer user_data)
2124 {
2125         AsyncData *data = user_data;
2126         EBookCallback cb = data->callback;
2127         EBookAsyncCallback excb = data->excallback;
2128         GError *error = NULL;
2129
2130         e_client_open_finish (E_CLIENT (source_object), result, &error);
2131
2132         if (cb != NULL && error == NULL)
2133                 cb (data->book, E_BOOK_ERROR_OK, data->closure);
2134         if (cb != NULL && error != NULL)
2135                 cb (data->book, error->code, data->closure);
2136         if (excb != NULL)
2137                 excb (data->book, error, data->closure);
2138
2139         if (error != NULL)
2140                 g_error_free (error);
2141
2142         g_object_unref (data->book);
2143         g_slice_free (AsyncData, data);
2144 }
2145
2146 /**
2147  * e_book_async_open:
2148  * @book: an #EBook
2149  * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
2150  * @open_response: (scope call) (closure closure): a function to call when the operation finishes
2151  * @closure: data to pass to callback function
2152  *
2153  * Opens the addressbook, making it ready for queries and other operations.
2154  * This function does not block.
2155  *
2156  * Returns: %FALSE if successful, %TRUE otherwise.
2157  *
2158  * Deprecated: 3.0: Use e_book_open_async() instead.
2159  **/
2160 gboolean
2161 e_book_async_open (EBook *book,
2162                    gboolean only_if_exists,
2163                    EBookCallback cb,
2164                    gpointer closure)
2165 {
2166         AsyncData *data;
2167
2168         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2169
2170         data = g_slice_new0 (AsyncData);
2171         data->book = g_object_ref (book);
2172         data->callback = cb;
2173         data->closure = closure;
2174
2175         e_client_open (
2176                 E_CLIENT (book->priv->client),
2177                 only_if_exists, NULL, open_reply, data);
2178
2179         return TRUE;
2180 }
2181
2182 /**
2183  * e_book_open_async:
2184  * @book: an #EBook
2185  * @only_if_exists: if %TRUE, fail if this book doesn't already exist, otherwise create it first
2186  * @open_response: (scope call): a function to call when the operation finishes
2187  * @closure: data to pass to callback function
2188  *
2189  * Opens the addressbook, making it ready for queries and other operations.
2190  * This function does not block.
2191  *
2192  * Returns: %FALSE if successful, %TRUE otherwise.
2193  *
2194  * Since: 2.32
2195  *
2196  * Deprecated: 3.2: Use e_client_open() and e_client_open_finish() on an #EBookClient object instead.
2197  **/
2198 gboolean
2199 e_book_open_async (EBook *book,
2200                    gboolean only_if_exists,
2201                    EBookAsyncCallback cb,
2202                    gpointer closure)
2203 {
2204         AsyncData *data;
2205
2206         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2207
2208         data = g_slice_new0 (AsyncData);
2209         data->book = g_object_ref (book);
2210         data->excallback = cb;
2211         data->closure = closure;
2212
2213         e_client_open (
2214                 E_CLIENT (book->priv->client),
2215                 only_if_exists, NULL, open_reply, data);
2216
2217         return TRUE;
2218 }
2219
2220 /**
2221  * e_book_remove:
2222  * @book: an #EBook
2223  * @error: a #GError to set on failure
2224  *
2225  * Removes the backing data for this #EBook. For example, with the file backend this
2226  * deletes the database file. You cannot get it back!
2227  *
2228  * Returns: %TRUE on success, %FALSE on failure.
2229  *
2230  * Deprecated: 3.2: Use e_client_remove_sync() on an #EBookClient object instead.
2231  */
2232 gboolean
2233 e_book_remove (EBook *book,
2234                GError **error)
2235 {
2236         ESource *source;
2237         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2238
2239         source = e_book_get_source (book);
2240
2241         return e_source_remove_sync (source, NULL, error);
2242 }
2243
2244 static void
2245 remove_reply (GObject *source_object,
2246               GAsyncResult *result,
2247               gpointer user_data)
2248 {
2249         AsyncData *data = user_data;
2250         EBookAsyncCallback excb = data->excallback;
2251         EBookCallback cb = data->callback;
2252         GError *error = NULL;
2253
2254         e_source_remove_finish (E_SOURCE (source_object), result, &error);
2255
2256         if (cb != NULL && error == NULL)
2257                 cb (data->book, E_BOOK_ERROR_OK, data->closure);
2258
2259         if (cb != NULL && error != NULL)
2260                 cb (data->book, error->code, data->closure);
2261
2262         if (excb != NULL)
2263                 excb (data->book, error, data->closure);
2264
2265         if (error != NULL)
2266                 g_error_free (error);
2267
2268         g_object_unref (data->book);
2269         g_slice_free (AsyncData, data);
2270 }
2271
2272 /**
2273  * e_book_async_remove:
2274  * @book: an #EBook
2275  * @cb: (scope async): a function to call when the operation finishes
2276  * @closure: data to pass to callback function
2277  *
2278  * Remove the backing data for this #EBook. For example, with the file backend this
2279  * deletes the database file. You cannot get it back!
2280  *
2281  * Returns: %FALSE if successful, %TRUE otherwise.
2282  *
2283  * Deprecated: 3.0: Use e_book_remove_async() instead.
2284  **/
2285 gboolean
2286 e_book_async_remove (EBook *book,
2287                      EBookCallback cb,
2288                      gpointer closure)
2289 {
2290         ESource *source;
2291         AsyncData *data;
2292
2293         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2294
2295         data = g_slice_new0 (AsyncData);
2296         data->book = g_object_ref (book);
2297         data->callback = cb;
2298         data->closure = closure;
2299
2300         source = e_book_get_source (book);
2301
2302         e_source_remove (source, NULL, remove_reply, data);
2303
2304         return TRUE;
2305 }
2306
2307 /**
2308  * e_book_remove_async:
2309  * @book: an #EBook
2310  * @cb: (scope async): a function to call when the operation finishes
2311  * @closure: data to pass to callback function
2312  *
2313  * Remove the backing data for this #EBook. For example, with the file backend this
2314  * deletes the database file. You cannot get it back!
2315  *
2316  * Returns: %FALSE if successful, %TRUE otherwise.
2317  *
2318  * Since: 2.32
2319  *
2320  * Deprecated: 3.2: Use e_client_remove() and e_client_remove_finish() on an #EBookClient object instead.
2321  **/
2322 gboolean
2323 e_book_remove_async (EBook *book,
2324                      EBookAsyncCallback cb,
2325                      gpointer closure)
2326 {
2327         ESource *source;
2328         AsyncData *data;
2329
2330         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2331
2332         data = g_slice_new0 (AsyncData);
2333         data->book = g_object_ref (book);
2334         data->excallback = cb;
2335         data->closure = closure;
2336
2337         source = e_book_get_source (book);
2338
2339         e_source_remove (source, NULL, remove_reply, data);
2340
2341         return TRUE;
2342 }
2343
2344 /**
2345  * e_book_get_source:
2346  * @book: an #EBook
2347  *
2348  * Get the #ESource that this book has loaded.
2349  *
2350  * Returns: (transfer none): The source.
2351  *
2352  * Deprecated: 3.2: Use e_client_get_source() on an #EBookClient object instead.
2353  */
2354 ESource *
2355 e_book_get_source (EBook *book)
2356 {
2357         g_return_val_if_fail (E_IS_BOOK (book), NULL);
2358
2359         return book->priv->source;
2360 }
2361
2362 /**
2363  * e_book_get_static_capabilities:
2364  * @book: an #EBook
2365  * @error: an #GError to set on failure
2366  *
2367  * Get the list of capabilities which the backend for this address book
2368  * supports. This string should not be freed.
2369  *
2370  * Returns: The capabilities list
2371  *
2372  * Deprecated: 3.2: Use e_client_get_capabilities() on an #EBookClient object.
2373  */
2374 const gchar *
2375 e_book_get_static_capabilities (EBook *book,
2376                                 GError **error)
2377 {
2378         g_return_val_if_fail (E_IS_BOOK (book), NULL);
2379
2380         if (book->priv->cap == NULL) {
2381                 gboolean success;
2382
2383                 success = e_client_retrieve_capabilities_sync (
2384                         E_CLIENT (book->priv->client),
2385                         &book->priv->cap, NULL, error);
2386
2387                 /* Sanity check. */
2388                 g_return_val_if_fail (
2389                         (success && (book->priv->cap != NULL)) ||
2390                         (!success && (book->priv->cap == NULL)), NULL);
2391         }
2392
2393         return book->priv->cap;
2394 }
2395
2396 /**
2397  * e_book_check_static_capability:
2398  * @book: an #EBook
2399  * @cap: A capability string
2400  *
2401  * Check to see if the backend for this address book supports the capability
2402  * @cap.
2403  *
2404  * Returns: %TRUE if the backend supports @cap, %FALSE otherwise.
2405  *
2406  * Deprecated: 3.2: Use e_client_check_capability() on an #EBookClient object instead.
2407  */
2408 gboolean
2409 e_book_check_static_capability (EBook *book,
2410                                 const gchar *cap)
2411 {
2412         const gchar *caps;
2413
2414         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2415
2416         caps = e_book_get_static_capabilities (book, NULL);
2417
2418         /* XXX this is an inexact test but it works for our use */
2419         if (caps && strstr (caps, cap))
2420                 return TRUE;
2421
2422         return FALSE;
2423 }
2424
2425 /**
2426  * e_book_is_opened:
2427  * @book: and #EBook
2428  *
2429  * Check if this book has been opened.
2430  *
2431  * Returns: %TRUE if this book has been opened, otherwise %FALSE.
2432  *
2433  * Deprecated: 3.2: Use e_client_is_opened() on an #EBookClient object instead.
2434  */
2435 gboolean
2436 e_book_is_opened (EBook *book)
2437 {
2438         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2439
2440         return e_client_is_opened (E_CLIENT (book->priv->client));
2441 }
2442
2443 /**
2444  * e_book_is_writable:
2445  * @book: an #EBook
2446  *
2447  * Check if this book is writable.
2448  *
2449  * Returns: %TRUE if this book is writable, otherwise %FALSE.
2450  *
2451  * Deprecated: 3.2: Use e_client_is_readonly() on an #EBookClient object instead.
2452  */
2453 gboolean
2454 e_book_is_writable (EBook *book)
2455 {
2456         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2457
2458         return !e_client_is_readonly (E_CLIENT (book->priv->client));
2459 }
2460
2461 /**
2462  * e_book_is_online:
2463  * @book: an #EBook
2464  *
2465  * Check if this book is connected.
2466  *
2467  * Returns: %TRUE if this book is connected, otherwise %FALSE.
2468  *
2469  * Deprecated: 3.2: Use e_client_is_online() on an #EBookClient object instead.
2470  **/
2471 gboolean
2472 e_book_is_online (EBook *book)
2473 {
2474         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2475
2476         return e_client_is_online (E_CLIENT (book->priv->client));
2477 }
2478
2479 #define SELF_UID_PATH_ID "org.gnome.evolution-data-server.addressbook"
2480 #define SELF_UID_KEY "self-contact-uid"
2481
2482 static EContact *
2483 make_me_card (void)
2484 {
2485         GString *vcard;
2486         const gchar *s;
2487         EContact *contact;
2488
2489         vcard = g_string_new ("BEGIN:VCARD\nVERSION:3.0\n");
2490
2491         s = g_get_user_name ();
2492         if (s)
2493                 g_string_append_printf (vcard, "NICKNAME:%s\n", s);
2494
2495         s = g_get_real_name ();
2496         if (s && strcmp (s, "Unknown") != 0) {
2497                 ENameWestern *western;
2498
2499                 g_string_append_printf (vcard, "FN:%s\n", s);
2500
2501                 western = e_name_western_parse (s);
2502                 g_string_append_printf (
2503                         vcard, "N:%s;%s;%s;%s;%s\n",
2504                         western->last ? western->last : "",
2505                         western->first ? western->first : "",
2506                         western->middle ? western->middle : "",
2507                         western->prefix ? western->prefix : "",
2508                         western->suffix ? western->suffix : "");
2509                 e_name_western_free (western);
2510         }
2511         g_string_append (vcard, "END:VCARD");
2512
2513         contact = e_contact_new_from_vcard (vcard->str);
2514
2515         g_string_free (vcard, TRUE);
2516
2517         return contact;
2518 }
2519
2520 /**
2521  * e_book_get_self:
2522  * @registry: an #ESourceRegistry
2523  * @contact: (out): an #EContact pointer to set
2524  * @book: (out): an #EBook pointer to set
2525  * @error: a #GError to set on failure
2526  *
2527  * Get the #EContact referring to the user of the address book
2528  * and set it in @contact and @book.
2529  *
2530  * Returns: %TRUE if successful, otherwise %FALSE.
2531  *
2532  * Deprecated: 3.2: Use e_book_client_get_self() instead.
2533  **/
2534 gboolean
2535 e_book_get_self (ESourceRegistry *registry,
2536                  EContact **contact,
2537                  EBook **book,
2538                  GError **error)
2539 {
2540         ESource *source;
2541         GError *e = NULL;
2542         GSettings *settings;
2543         gboolean status;
2544         gchar *uid;
2545
2546         g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), FALSE);
2547
2548         source = e_source_registry_ref_builtin_address_book (registry);
2549         *book = e_book_new (source, &e);
2550         g_object_unref (source);
2551
2552         if (!*book) {
2553                 if (error)
2554                         g_propagate_error (error, e);
2555                 return FALSE;
2556         }
2557
2558         status = e_book_open (*book, FALSE, &e);
2559         if (status == FALSE) {
2560                 g_object_unref (*book);
2561                 *book = NULL;
2562                 if (error)
2563                         g_propagate_error (error, e);
2564                 return FALSE;
2565         }
2566
2567         settings = g_settings_new (SELF_UID_PATH_ID);
2568         uid = g_settings_get_string (settings, SELF_UID_KEY);
2569         g_object_unref (settings);
2570
2571         if (uid) {
2572                 gboolean got;
2573
2574                 /* Don't care about errors because we'll create a new card on failure */
2575                 got = e_book_get_contact (*book, uid, contact, NULL);
2576                 g_free (uid);
2577                 if (got)
2578                         return TRUE;
2579         }
2580
2581         *contact = make_me_card ();
2582         if (!e_book_add_contact (*book, *contact, &e)) {
2583                 /* TODO: return NULL or the contact anyway? */
2584                 g_object_unref (*book);
2585                 *book = NULL;
2586                 g_object_unref (*contact);
2587                 *contact = NULL;
2588                 if (error)
2589                         g_propagate_error (error, e);
2590                 return FALSE;
2591         }
2592
2593         e_book_set_self (*book, *contact, NULL);
2594
2595         return TRUE;
2596 }
2597
2598 /**
2599  * e_book_set_self:
2600  * @book: an #EBook
2601  * @contact: an #EContact
2602  * @error: a #GError to set on failure
2603  *
2604  * Specify that @contact residing in @book is the #EContact that
2605  * refers to the user of the address book.
2606  *
2607  * Returns: %TRUE if successful, %FALSE otherwise.
2608  *
2609  * Deprecated: 3.2: Use e_book_client_set_self() instead.
2610  **/
2611 gboolean
2612 e_book_set_self (EBook *book,
2613                  EContact *contact,
2614                  GError **error)
2615 {
2616         GSettings *settings;
2617
2618         g_return_val_if_fail (E_IS_BOOK (book), FALSE);
2619         g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
2620
2621         settings = g_settings_new (SELF_UID_PATH_ID);
2622         g_settings_set_string (settings, SELF_UID_KEY, e_contact_get_const (contact, E_CONTACT_UID));
2623         g_object_unref (settings);
2624
2625         return TRUE;
2626 }
2627
2628 /**
2629  * e_book_is_self:
2630  * @contact: an #EContact
2631  *
2632  * Check if @contact is the user of the address book.
2633  *
2634  * Returns: %TRUE if @contact is the user, %FALSE otherwise.
2635  *
2636  * Deprecated: 3.2: Use e_book_client_is_self() instead.
2637  **/
2638 gboolean
2639 e_book_is_self (EContact *contact)
2640 {
2641         GSettings *settings;
2642         gchar *uid;
2643         gboolean rv;
2644
2645         g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
2646
2647         settings = g_settings_new (SELF_UID_PATH_ID);
2648         uid = g_settings_get_string (settings, SELF_UID_KEY);
2649         g_object_unref (settings);
2650
2651         rv = (uid && !strcmp (uid, e_contact_get_const (contact, E_CONTACT_UID)));
2652
2653         g_free (uid);
2654
2655         return rv;
2656 }
2657
2658 /**
2659  * e_book_new:
2660  * @source: an #ESource
2661  * @error: return location for a #GError, or %NULL
2662  *
2663  * Creates a new #EBook corresponding to the given @source.  There are
2664  * only two operations that are valid on this book at this point:
2665  * e_book_open(), and e_book_remove().
2666  *
2667  * Returns: a new but unopened #EBook.
2668  *
2669  * Deprecated: 3.2: Use e_book_client_new() instead.
2670  */
2671 EBook *
2672 e_book_new (ESource *source,
2673             GError **error)
2674 {
2675         g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2676
2677         return g_initable_new (
2678                 E_TYPE_BOOK, NULL, error,
2679                 "source", source, NULL);
2680 }
2681