1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
4 * Copyright (C) 2006 OpenedHand Ltd
5 * Copyright (C) 2009 Intel Corporation
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.
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
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
20 * Author: Ross Burton <ross@linux.intel.com>
25 #include <glib/gi18n.h>
28 /* Private D-Bus classes. */
29 #include <e-dbus-address-book.h>
31 #include <libebook-contacts/libebook-contacts.h>
33 #include "e-data-book-factory.h"
34 #include "e-data-book.h"
35 #include "e-data-book-view.h"
36 #include "e-book-backend.h"
37 #include "e-book-backend-sexp.h"
38 #include "e-book-backend-factory.h"
39 #include "e-dbus-localed.h"
41 #define E_DATA_BOOK_GET_PRIVATE(obj) \
42 (G_TYPE_INSTANCE_GET_PRIVATE \
43 ((obj), E_TYPE_DATA_BOOK, EDataBookPrivate))
45 struct _EDataBookPrivate {
46 GDBusConnection *connection;
47 EDBusAddressBook *dbus_interface;
48 EModule *direct_module;
49 EDataBookDirect *direct_book;
51 EBookBackend *backend;
54 GRecMutex pending_ops_lock;
55 GHashTable *pending_ops; /* opid -> OperationData */
56 GHashTable *direct_ops; /* opid to DirectOperationData for still running operations */
58 /* Operations are queued while an
59 * open operation is in progress. */
64 guint localed_watch_id;
65 EDBusLocale1 *localed_proxy;
66 GCancellable *localed_cancel;
76 static EOperationPool *ops_pool = NULL;
87 OP_GET_BACKEND_PROPERTY,
93 volatile gint ref_count;
96 guint32 id; /* operation id */
97 EDataBook *book; /* book */
98 GCancellable *cancellable;
99 GDBusMethodInvocation *invocation;
105 /* OP_REMOVE_CONTACTS */
107 /* OP_ADD_CONTACTS */
108 /* OP_MODIFY_CONTACTS */
111 /* OP_GET_CONTACTS */
112 /* OP_GET_CONTACTS_UIDS */
114 /* OP_GET_BACKEND_PROPERTY */
115 const gchar *prop_name;
123 GAsyncReadyCallback callback;
125 GCancellable *cancellable;
126 GSimpleAsyncResult *result;
128 gboolean is_sync_call;
129 gboolean sync_call_complete;
130 GMutex sync_result_mutex;
131 GCond sync_result_condition;
132 } DirectOperationData;
134 /* EModule's can never be free'd, however the use count can change
135 * Here we ensure that there is only one ever created by way of
136 * static variables and locks
138 static GHashTable *modules_table = NULL;
139 G_LOCK_DEFINE (modules_table);
141 /* Forward Declarations */
142 static void e_data_book_initable_init (GInitableIface *interface);
143 static DirectOperationData *direct_operation_data_push (EDataBook *book,
145 GAsyncReadyCallback callback,
147 GCancellable *cancellable,
150 static void direct_operation_data_free (DirectOperationData *data);
151 static void direct_operation_complete (DirectOperationData *data);
152 static void direct_operation_wait (DirectOperationData *data);
153 static void e_data_book_respond_close (EDataBook *book,
157 G_DEFINE_TYPE_WITH_CODE (
161 G_IMPLEMENT_INTERFACE (
163 e_data_book_initable_init))
166 load_module (const gchar *module_path)
168 EModule *module = NULL;
170 G_LOCK (modules_table);
173 modules_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
175 module = g_hash_table_lookup (modules_table, module_path);
178 module = e_module_new (module_path);
180 g_warning ("Failed to open EModule at path: %s", module_path);
182 g_hash_table_insert (modules_table, g_strdup (module_path), module);
185 G_UNLOCK (modules_table);
190 static DirectOperationData *
191 direct_operation_data_push (EDataBook *book,
193 GAsyncReadyCallback callback,
195 GCancellable *cancellable,
199 DirectOperationData *data;
201 data = g_slice_new (DirectOperationData);
202 data->callback = callback;
203 data->user_data = user_data;
204 data->cancellable = g_object_ref (cancellable);
205 data->result = g_simple_async_result_new (
210 data->is_sync_call = sync_call;
211 data->sync_call_complete = FALSE;
213 if (data->is_sync_call) {
214 g_mutex_init (&data->sync_result_mutex);
215 g_cond_init (&data->sync_result_condition);
218 g_hash_table_insert (book->priv->direct_ops, GUINT_TO_POINTER (opid), data);
224 direct_operation_data_free (DirectOperationData *data)
227 if (data->is_sync_call) {
228 g_mutex_clear (&data->sync_result_mutex);
229 g_cond_clear (&data->sync_result_condition);
232 g_object_unref (data->result);
233 g_object_unref (data->cancellable);
234 g_slice_free (DirectOperationData, data);
239 direct_operation_complete (DirectOperationData *data)
241 /* If it was a sync call, we have the calling thread
242 * waiting on the sync call condition, it's up to
243 * the sync call to free the data with direct_operation_data_free().
245 * Otherwise for async calls we need to complete
246 * in the calling thread.
248 if (data->is_sync_call) {
249 g_mutex_lock (&data->sync_result_mutex);
250 data->sync_call_complete = TRUE;
251 g_cond_signal (&data->sync_result_condition);
252 g_mutex_unlock (&data->sync_result_mutex);
254 g_simple_async_result_complete_in_idle (data->result);
255 direct_operation_data_free (data);
260 direct_operation_wait (DirectOperationData *data)
262 g_mutex_lock (&data->sync_result_mutex);
263 while (data->sync_call_complete == FALSE)
264 g_cond_wait (&data->sync_result_condition, &data->sync_result_mutex);
265 g_mutex_unlock (&data->sync_result_mutex);
269 construct_bookview_path (void)
271 static volatile gint counter = 1;
273 g_atomic_int_inc (&counter);
275 return g_strdup_printf (
276 "/org/gnome/evolution/dataserver/AddressBookView/%d/%d",
281 op_sender_vanished_cb (GDBusConnection *connection,
283 GCancellable *cancellable)
285 g_cancellable_cancel (cancellable);
288 static OperationData *
289 op_ref (OperationData *data)
291 g_return_val_if_fail (data != NULL, data);
292 g_return_val_if_fail (data->ref_count > 0, data);
294 g_atomic_int_inc (&data->ref_count);
299 static OperationData *
300 op_new (OperationID op,
302 GDBusMethodInvocation *invocation)
306 data = g_slice_new0 (OperationData);
309 data->id = e_operation_pool_reserve_opid (ops_pool);
310 data->book = g_object_ref (book);
311 data->cancellable = g_cancellable_new ();
313 /* This is optional so we can fake client requests. */
314 if (invocation != NULL) {
315 GDBusConnection *connection;
318 data->invocation = g_object_ref (invocation);
320 connection = e_data_book_get_connection (book);
321 sender = g_dbus_method_invocation_get_sender (invocation);
323 data->watcher_id = g_bus_watch_name_on_connection (
325 G_BUS_NAME_WATCHER_FLAGS_NONE,
326 (GBusNameAppearedCallback) NULL,
327 (GBusNameVanishedCallback) op_sender_vanished_cb,
328 g_object_ref (data->cancellable),
329 (GDestroyNotify) g_object_unref);
332 g_rec_mutex_lock (&book->priv->pending_ops_lock);
333 g_hash_table_insert (
334 book->priv->pending_ops,
335 GUINT_TO_POINTER (data->id),
337 g_rec_mutex_unlock (&book->priv->pending_ops_lock);
343 op_unref (OperationData *data)
345 g_return_if_fail (data != NULL);
346 g_return_if_fail (data->ref_count > 0);
348 if (g_atomic_int_dec_and_test (&data->ref_count)) {
352 g_free (data->d.uid);
354 case OP_REMOVE_CONTACTS:
357 (GDestroyNotify) g_free);
359 case OP_ADD_CONTACTS:
360 case OP_MODIFY_CONTACTS:
363 (GDestroyNotify) g_free);
366 case OP_GET_CONTACTS:
367 case OP_GET_CONTACTS_UIDS:
368 g_free (data->d.query);
374 g_object_unref (data->book);
375 g_object_unref (data->cancellable);
377 if (data->invocation != NULL)
378 g_object_unref (data->invocation);
380 if (data->watcher_id > 0)
381 g_bus_unwatch_name (data->watcher_id);
383 g_slice_free (OperationData, data);
388 op_dispatch (EDataBook *book,
391 g_mutex_lock (&book->priv->open_lock);
393 /* If an open operation is currently in progress, queue this
394 * operation to be dispatched when the open operation finishes. */
395 if (book->priv->open_opid > 0) {
396 g_queue_push_tail (&book->priv->open_queue, data);
398 if (data->op == OP_OPEN)
399 book->priv->open_opid = data->id;
400 e_operation_pool_push (ops_pool, data);
403 g_mutex_unlock (&book->priv->open_lock);
406 static OperationData *
407 op_claim (EDataBook *book,
409 DirectOperationData **direct)
412 DirectOperationData *direct_data;
414 g_return_val_if_fail (E_IS_DATA_BOOK (book), NULL);
416 e_operation_pool_release_opid (ops_pool, opid);
418 g_rec_mutex_lock (&book->priv->pending_ops_lock);
419 data = g_hash_table_lookup (
420 book->priv->pending_ops,
421 GUINT_TO_POINTER (opid));
423 /* Steal the hash table's reference. */
425 book->priv->pending_ops,
426 GUINT_TO_POINTER (opid));
429 direct_data = g_hash_table_lookup (
430 book->priv->direct_ops,
431 GUINT_TO_POINTER (opid));
432 if (direct_data != NULL) {
434 book->priv->direct_ops,
435 GUINT_TO_POINTER (opid));
437 g_rec_mutex_unlock (&book->priv->pending_ops_lock);
439 g_warn_if_fail (direct_data == NULL || direct != NULL);
441 *direct = direct_data;
446 static DirectOperationData *
447 op_complete (EDataBook *book,
450 DirectOperationData *direct_data;
452 g_return_val_if_fail (E_IS_DATA_BOOK (book), NULL);
454 e_operation_pool_release_opid (ops_pool, opid);
456 g_rec_mutex_lock (&book->priv->pending_ops_lock);
457 g_hash_table_remove (
458 book->priv->pending_ops,
459 GUINT_TO_POINTER (opid));
461 direct_data = g_hash_table_lookup (
462 book->priv->direct_ops,
463 GUINT_TO_POINTER (opid));
464 if (direct_data != NULL) {
466 book->priv->direct_ops,
467 GUINT_TO_POINTER (opid));
469 g_rec_mutex_unlock (&book->priv->pending_ops_lock);
475 data_book_convert_to_client_error (GError *error)
477 g_return_if_fail (error != NULL);
479 if (error->domain != E_DATA_BOOK_ERROR)
482 switch (error->code) {
483 case E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE:
484 error->domain = E_CLIENT_ERROR;
485 error->code = E_CLIENT_ERROR_REPOSITORY_OFFLINE;
488 case E_DATA_BOOK_STATUS_PERMISSION_DENIED:
489 error->domain = E_CLIENT_ERROR;
490 error->code = E_CLIENT_ERROR_PERMISSION_DENIED;
493 case E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND:
494 error->domain = E_BOOK_CLIENT_ERROR;
495 error->code = E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND;
498 case E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS:
499 error->domain = E_BOOK_CLIENT_ERROR;
500 error->code = E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS;
503 case E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED:
504 error->domain = E_CLIENT_ERROR;
505 error->code = E_CLIENT_ERROR_AUTHENTICATION_FAILED;
508 case E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD:
509 error->domain = E_CLIENT_ERROR;
510 error->code = E_CLIENT_ERROR_UNSUPPORTED_AUTHENTICATION_METHOD;
513 case E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE:
514 error->domain = E_CLIENT_ERROR;
515 error->code = E_CLIENT_ERROR_TLS_NOT_AVAILABLE;
518 case E_DATA_BOOK_STATUS_NO_SUCH_BOOK:
519 error->domain = E_BOOK_CLIENT_ERROR;
520 error->code = E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK;
523 case E_DATA_BOOK_STATUS_BOOK_REMOVED:
524 error->domain = E_BOOK_CLIENT_ERROR;
525 error->code = E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE;
528 case E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE:
529 error->domain = E_CLIENT_ERROR;
530 error->code = E_CLIENT_ERROR_OFFLINE_UNAVAILABLE;
533 case E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED:
534 error->domain = E_CLIENT_ERROR;
535 error->code = E_CLIENT_ERROR_SEARCH_SIZE_LIMIT_EXCEEDED;
538 case E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED:
539 error->domain = E_CLIENT_ERROR;
540 error->code = E_CLIENT_ERROR_SEARCH_TIME_LIMIT_EXCEEDED;
543 case E_DATA_BOOK_STATUS_INVALID_QUERY:
544 error->domain = E_CLIENT_ERROR;
545 error->code = E_CLIENT_ERROR_INVALID_QUERY;
548 case E_DATA_BOOK_STATUS_QUERY_REFUSED:
549 error->domain = E_CLIENT_ERROR;
550 error->code = E_CLIENT_ERROR_QUERY_REFUSED;
553 case E_DATA_BOOK_STATUS_COULD_NOT_CANCEL:
554 error->domain = E_CLIENT_ERROR;
555 error->code = E_CLIENT_ERROR_COULD_NOT_CANCEL;
558 case E_DATA_BOOK_STATUS_NO_SPACE:
559 error->domain = E_BOOK_CLIENT_ERROR;
560 error->code = E_BOOK_CLIENT_ERROR_NO_SPACE;
563 case E_DATA_BOOK_STATUS_INVALID_ARG:
564 error->domain = E_CLIENT_ERROR;
565 error->code = E_CLIENT_ERROR_INVALID_ARG;
568 case E_DATA_BOOK_STATUS_NOT_SUPPORTED:
569 error->domain = E_CLIENT_ERROR;
570 error->code = E_CLIENT_ERROR_NOT_SUPPORTED;
573 case E_DATA_BOOK_STATUS_NOT_OPENED:
574 error->domain = E_CLIENT_ERROR;
575 error->code = E_CLIENT_ERROR_NOT_OPENED;
578 case E_DATA_BOOK_STATUS_OUT_OF_SYNC:
579 error->domain = E_CLIENT_ERROR;
580 error->code = E_CLIENT_ERROR_OUT_OF_SYNC;
583 case E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD:
584 case E_DATA_BOOK_STATUS_OTHER_ERROR:
585 case E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION:
586 error->domain = E_CLIENT_ERROR;
587 error->code = E_CLIENT_ERROR_OTHER_ERROR;
591 g_warn_if_reached ();
596 operation_thread (gpointer data,
599 OperationData *op = data;
600 EBookBackend *backend;
604 backend = e_data_book_get_backend (op->book);
608 e_book_backend_open (
609 backend, op->book, op->id,
610 op->cancellable, FALSE);
613 case OP_ADD_CONTACTS:
614 e_book_backend_create_contacts (
615 backend, op->book, op->id,
616 op->cancellable, op->d.vcards);
620 e_book_backend_get_contact (
621 backend, op->book, op->id,
622 op->cancellable, op->d.uid);
625 case OP_GET_CONTACTS:
626 e_book_backend_get_contact_list (
627 backend, op->book, op->id,
628 op->cancellable, op->d.query);
631 case OP_GET_CONTACTS_UIDS:
632 e_book_backend_get_contact_list_uids (
633 backend, op->book, op->id,
634 op->cancellable, op->d.query);
637 case OP_MODIFY_CONTACTS:
638 e_book_backend_modify_contacts (
639 backend, op->book, op->id,
640 op->cancellable, op->d.vcards);
643 case OP_REMOVE_CONTACTS:
644 e_book_backend_remove_contacts (
645 backend, op->book, op->id,
646 op->cancellable, op->d.ids);
650 e_book_backend_refresh (
651 backend, op->book, op->id, op->cancellable);
654 case OP_GET_BACKEND_PROPERTY:
655 e_book_backend_get_backend_property (
656 backend, op->book, op->id,
657 op->cancellable, op->d.prop_name);
663 EBookBackendSExp *card_sexp;
664 GDBusConnection *connection;
666 GError *error = NULL;
668 card_sexp = e_book_backend_sexp_new (op->d.query);
670 g_dbus_method_invocation_return_error_literal (
673 E_CLIENT_ERROR_INVALID_QUERY,
676 op_complete (op->book, op->id);
680 object_path = construct_bookview_path ();
681 connection = e_data_book_get_connection (op->book);
683 view = e_data_book_view_new (
685 connection, object_path, &error);
687 g_object_unref (card_sexp);
691 ((view != NULL) && (error == NULL)) ||
692 ((view == NULL) && (error != NULL)));
695 /* Translators: This is prefix to a detailed error message */
696 g_prefix_error (&error, "%s", _("Invalid query: "));
697 data_book_convert_to_client_error (error);
698 g_dbus_method_invocation_take_error (
699 op->invocation, error);
701 op_complete (op->book, op->id);
702 g_free (object_path);
706 e_book_backend_add_view (backend, view);
708 e_dbus_address_book_complete_get_view (
709 op->book->priv->dbus_interface,
713 op_complete (op->book, op->id);
714 g_free (object_path);
719 /* close just cancels all pending ops and frees data book */
720 e_book_backend_remove_client (backend, op->book);
722 g_rec_mutex_lock (&op->book->priv->pending_ops_lock);
724 g_hash_table_iter_init (&iter, op->book->priv->pending_ops);
725 while (g_hash_table_iter_next (&iter, NULL, &value)) {
726 OperationData *cancel_op = value;
727 g_cancellable_cancel (cancel_op->cancellable);
730 g_rec_mutex_unlock (&op->book->priv->pending_ops_lock);
732 if (op->book->priv->dbus_interface)
733 e_dbus_address_book_complete_close (
734 op->book->priv->dbus_interface,
737 /* Let direct calls return, notify the direct callers that it's closed */
738 e_data_book_respond_close (op->book, op->id, NULL);
745 static OperationData *
746 op_direct_new (OperationID op,
748 GCancellable *cancellable,
749 GAsyncReadyCallback callback,
753 DirectOperationData **ret_data)
756 DirectOperationData *direct_data;
758 data = g_slice_new0 (OperationData);
761 data->book = g_object_ref (book);
762 data->id = e_operation_pool_reserve_opid (ops_pool);
765 data->cancellable = g_object_ref (cancellable);
767 data->cancellable = g_cancellable_new ();
769 g_rec_mutex_lock (&book->priv->pending_ops_lock);
770 g_hash_table_insert (
771 book->priv->pending_ops,
772 GUINT_TO_POINTER (data->id),
774 direct_data = direct_operation_data_push (
775 book, data->id, callback, user_data,
776 data->cancellable, source_tag, sync_call);
777 g_rec_mutex_unlock (&book->priv->pending_ops_lock);
780 *ret_data = direct_data;
786 * e_data_book_status_to_string:
791 e_data_book_status_to_string (EDataBookStatus status)
794 static struct _statuses {
795 EDataBookStatus status;
798 { E_DATA_BOOK_STATUS_SUCCESS, N_("Success") },
799 { E_DATA_BOOK_STATUS_BUSY, N_("Backend is busy") },
800 { E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, N_("Repository offline") },
801 { E_DATA_BOOK_STATUS_PERMISSION_DENIED, N_("Permission denied") },
802 { E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, N_("Contact not found") },
803 { E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS, N_("Contact ID already exists") },
804 { E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED, N_("Authentication Failed") },
805 { E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED, N_("Authentication Required") },
806 { E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD, N_("Unsupported field") },
807 { E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD, N_("Unsupported authentication method") },
808 { E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE, N_("TLS not available") },
809 { E_DATA_BOOK_STATUS_NO_SUCH_BOOK, N_("Address book does not exist") },
810 { E_DATA_BOOK_STATUS_BOOK_REMOVED, N_("Book removed") },
811 { E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE, N_("Not available in offline mode") },
812 { E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED, N_("Search size limit exceeded") },
813 { E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED, N_("Search time limit exceeded") },
814 { E_DATA_BOOK_STATUS_INVALID_QUERY, N_("Invalid query") },
815 { E_DATA_BOOK_STATUS_QUERY_REFUSED, N_("Query refused") },
816 { E_DATA_BOOK_STATUS_COULD_NOT_CANCEL, N_("Could not cancel") },
817 /* { E_DATA_BOOK_STATUS_OTHER_ERROR, N_("Other error") }, */
818 { E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION, N_("Invalid server version") },
819 { E_DATA_BOOK_STATUS_NO_SPACE, N_("No space") },
820 { E_DATA_BOOK_STATUS_INVALID_ARG, N_("Invalid argument") },
821 /* Translators: The string for NOT_SUPPORTED error */
822 { E_DATA_BOOK_STATUS_NOT_SUPPORTED, N_("Not supported") },
823 { E_DATA_BOOK_STATUS_NOT_OPENED, N_("Backend is not opened yet") },
824 { E_DATA_BOOK_STATUS_OUT_OF_SYNC, N_("Object is out of sync") }
827 for (i = 0; i < G_N_ELEMENTS (statuses); i++) {
828 if (statuses[i].status == status)
829 return _(statuses[i].msg);
832 return _("Other error");
835 /* Create the EDataBook error quark */
837 e_data_book_error_quark (void)
839 #define ERR_PREFIX "org.gnome.evolution.dataserver.AddressBook."
841 static const GDBusErrorEntry entries[] = {
842 { E_DATA_BOOK_STATUS_SUCCESS, ERR_PREFIX "Success" },
843 { E_DATA_BOOK_STATUS_BUSY, ERR_PREFIX "Busy" },
844 { E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, ERR_PREFIX "RepositoryOffline" },
845 { E_DATA_BOOK_STATUS_PERMISSION_DENIED, ERR_PREFIX "PermissionDenied" },
846 { E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND, ERR_PREFIX "ContactNotFound" },
847 { E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS, ERR_PREFIX "ContactIDAlreadyExists" },
848 { E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED, ERR_PREFIX "AuthenticationFailed" },
849 { E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED, ERR_PREFIX "AuthenticationRequired" },
850 { E_DATA_BOOK_STATUS_UNSUPPORTED_FIELD, ERR_PREFIX "UnsupportedField" },
851 { E_DATA_BOOK_STATUS_UNSUPPORTED_AUTHENTICATION_METHOD, ERR_PREFIX "UnsupportedAuthenticationMethod" },
852 { E_DATA_BOOK_STATUS_TLS_NOT_AVAILABLE, ERR_PREFIX "TLSNotAvailable" },
853 { E_DATA_BOOK_STATUS_NO_SUCH_BOOK, ERR_PREFIX "NoSuchBook" },
854 { E_DATA_BOOK_STATUS_BOOK_REMOVED, ERR_PREFIX "BookRemoved" },
855 { E_DATA_BOOK_STATUS_OFFLINE_UNAVAILABLE, ERR_PREFIX "OfflineUnavailable" },
856 { E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED, ERR_PREFIX "SearchSizeLimitExceeded" },
857 { E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED, ERR_PREFIX "SearchTimeLimitExceeded" },
858 { E_DATA_BOOK_STATUS_INVALID_QUERY, ERR_PREFIX "InvalidQuery" },
859 { E_DATA_BOOK_STATUS_QUERY_REFUSED, ERR_PREFIX "QueryRefused" },
860 { E_DATA_BOOK_STATUS_COULD_NOT_CANCEL, ERR_PREFIX "CouldNotCancel" },
861 { E_DATA_BOOK_STATUS_OTHER_ERROR, ERR_PREFIX "OtherError" },
862 { E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION, ERR_PREFIX "InvalidServerVersion" },
863 { E_DATA_BOOK_STATUS_NO_SPACE, ERR_PREFIX "NoSpace" },
864 { E_DATA_BOOK_STATUS_INVALID_ARG, ERR_PREFIX "InvalidArg" },
865 { E_DATA_BOOK_STATUS_NOT_SUPPORTED, ERR_PREFIX "NotSupported" },
866 { E_DATA_BOOK_STATUS_NOT_OPENED, ERR_PREFIX "NotOpened" },
867 { E_DATA_BOOK_STATUS_OUT_OF_SYNC, ERR_PREFIX "OutOfSync" }
872 static volatile gsize quark_volatile = 0;
874 g_dbus_error_register_error_domain ("e-data-book-error", &quark_volatile, entries, G_N_ELEMENTS (entries));
876 return (GQuark) quark_volatile;
880 * e_data_book_create_error:
885 e_data_book_create_error (EDataBookStatus status,
886 const gchar *custom_msg)
888 if (status == E_DATA_BOOK_STATUS_SUCCESS)
891 return g_error_new_literal (E_DATA_BOOK_ERROR, status, custom_msg ? custom_msg : e_data_book_status_to_string (status));
895 * e_data_book_create_error_fmt:
900 e_data_book_create_error_fmt (EDataBookStatus status,
901 const gchar *custom_msg_fmt,
909 return e_data_book_create_error (status, NULL);
911 va_start (ap, custom_msg_fmt);
912 custom_msg = g_strdup_vprintf (custom_msg_fmt, ap);
915 error = e_data_book_create_error (status, custom_msg);
923 * e_data_book_string_slist_to_comma_string:
925 * Takes a list of strings and converts it to a comma-separated string of
926 * values; free returned pointer with g_free()
931 e_data_book_string_slist_to_comma_string (const GSList *strings)
937 tmp = g_string_new ("");
938 for (l = strings; l != NULL; l = l->next) {
939 const gchar *str = l->data;
944 if (strchr (str, ',')) {
945 g_warning ("%s: String cannot contain comma; skipping value '%s'\n", G_STRFUNC, str);
950 g_string_append_c (tmp, ',');
951 g_string_append (tmp, str);
954 res = e_util_utf8_make_valid (tmp->str);
956 g_string_free (tmp, TRUE);
962 data_book_handle_open_cb (EDBusAddressBook *interface,
963 GDBusMethodInvocation *invocation,
968 op = op_new (OP_OPEN, book, invocation);
970 op_dispatch (book, op);
976 data_book_handle_refresh_cb (EDBusAddressBook *interface,
977 GDBusMethodInvocation *invocation,
982 op = op_new (OP_REFRESH, book, invocation);
984 op_dispatch (book, op);
990 data_book_handle_get_contact_cb (EDBusAddressBook *interface,
991 GDBusMethodInvocation *invocation,
997 op = op_new (OP_GET_CONTACT, book, invocation);
998 op->d.uid = g_strdup (in_uid);
1000 op_dispatch (book, op);
1006 data_book_handle_get_contact_list_cb (EDBusAddressBook *interface,
1007 GDBusMethodInvocation *invocation,
1008 const gchar *in_query,
1013 op = op_new (OP_GET_CONTACTS, book, invocation);
1014 op->d.query = g_strdup (in_query);
1016 op_dispatch (book, op);
1022 data_book_handle_get_contact_list_uids_cb (EDBusAddressBook *interface,
1023 GDBusMethodInvocation *invocation,
1024 const gchar *in_query,
1029 op = op_new (OP_GET_CONTACTS_UIDS, book, invocation);
1030 op->d.query = g_strdup (in_query);
1032 op_dispatch (book, op);
1038 data_book_handle_create_contacts_cb (EDBusAddressBook *interface,
1039 GDBusMethodInvocation *invocation,
1040 const gchar * const *in_vcards,
1045 op = op_new (OP_ADD_CONTACTS, book, invocation);
1046 op->d.vcards = e_util_strv_to_slist (in_vcards);
1048 op_dispatch (book, op);
1054 data_book_handle_modify_contacts_cb (EDBusAddressBook *interface,
1055 GDBusMethodInvocation *invocation,
1056 const gchar * const *in_vcards,
1061 op = op_new (OP_MODIFY_CONTACTS, book, invocation);
1062 op->d.vcards = e_util_strv_to_slist (in_vcards);
1064 op_dispatch (book, op);
1070 data_book_handle_remove_contacts_cb (EDBusAddressBook *interface,
1071 GDBusMethodInvocation *invocation,
1072 const gchar * const *in_uids,
1077 op = op_new (OP_REMOVE_CONTACTS, book, invocation);
1079 /* Allow an empty array to be removed */
1080 for (; in_uids && *in_uids; in_uids++) {
1081 op->d.ids = g_slist_prepend (op->d.ids, g_strdup (*in_uids));
1084 op_dispatch (book, op);
1090 data_book_handle_get_view_cb (EDBusAddressBook *interface,
1091 GDBusMethodInvocation *invocation,
1092 const gchar *in_query,
1097 op = op_new (OP_GET_VIEW, book, invocation);
1098 op->d.query = g_strdup (in_query);
1100 /* This operation is never queued. */
1101 e_operation_pool_push (ops_pool, op);
1107 data_book_handle_close_cb (EDBusAddressBook *interface,
1108 GDBusMethodInvocation *invocation,
1113 op = op_new (OP_CLOSE, book, invocation);
1114 /* unref here makes sure the book is freed in a separate thread */
1115 g_object_unref (book);
1117 /* This operation is never queued. */
1118 e_operation_pool_push (ops_pool, op);
1124 e_data_book_respond_open (EDataBook *book,
1128 DirectOperationData *direct = NULL;
1129 OperationData *data;
1130 GError *copy = NULL;
1132 g_return_if_fail (E_IS_DATA_BOOK (book));
1134 data = op_claim (book, opid, &direct);
1135 g_return_if_fail (data != NULL);
1137 /* Translators: This is prefix to a detailed error message */
1138 g_prefix_error (&error, "%s", _("Cannot open book: "));
1140 /* This function is deprecated, but it's the only way to
1141 * set EBookBackend's internal 'opened' flag. We should
1142 * be the only ones calling this. */
1143 if (error != NULL) {
1144 data_book_convert_to_client_error (error);
1145 copy = g_error_copy (error);
1147 e_book_backend_notify_opened (book->priv->backend, copy);
1150 gboolean result = FALSE;
1153 g_simple_async_result_set_error (
1157 "%s", error->message);
1158 g_error_free (error);
1160 g_simple_async_result_set_check_cancellable (
1162 direct->cancellable);
1164 if (!g_cancellable_is_cancelled (direct->cancellable))
1168 g_simple_async_result_set_op_res_gboolean (direct->result, result);
1170 /* Deliver the result to the caller */
1171 direct_operation_complete (direct);
1172 } else if (error == NULL) {
1173 e_dbus_address_book_complete_open (
1174 book->priv->dbus_interface,
1177 g_dbus_method_invocation_take_error (
1178 data->invocation, error);
1183 /* Dispatch any pending operations. */
1184 g_mutex_lock (&book->priv->open_lock);
1186 if (opid == book->priv->open_opid) {
1189 book->priv->open_opid = 0;
1191 while (!g_queue_is_empty (&book->priv->open_queue)) {
1192 op = g_queue_pop_head (&book->priv->open_queue);
1193 e_operation_pool_push (ops_pool, op);
1197 g_mutex_unlock (&book->priv->open_lock);
1201 * e_data_book_respond_refresh:
1202 * @book: An addressbook client interface.
1203 * @error: Operation error, if any, automatically freed if passed it.
1205 * Notifies listeners of the completion of the refresh method call.
1210 e_data_book_respond_refresh (EDataBook *book,
1214 OperationData *data;
1216 g_return_if_fail (E_IS_DATA_BOOK (book));
1218 data = op_claim (book, opid, NULL);
1219 g_return_if_fail (data != NULL);
1221 /* Translators: This is prefix to a detailed error message */
1222 g_prefix_error (&error, "%s", _("Cannot refresh address book: "));
1224 if (error == NULL) {
1225 e_dbus_address_book_complete_refresh (
1226 book->priv->dbus_interface,
1229 data_book_convert_to_client_error (error);
1230 g_dbus_method_invocation_take_error (
1231 data->invocation, error);
1238 * e_data_book_respond_get_backend_property:
1240 * FIXME: Document me.
1245 e_data_book_respond_get_backend_property (EDataBook *book,
1248 const gchar *prop_value)
1250 OperationData *data;
1252 g_return_if_fail (E_IS_DATA_BOOK (book));
1254 data = op_claim (book, opid, NULL);
1255 g_return_if_fail (data != NULL);
1257 if (error == NULL) {
1258 e_data_book_report_backend_property_changed (
1259 book, data->d.prop_name, prop_value);
1261 /* This should never happen, since all backend property
1262 * requests now originate from our constructed() method. */
1263 g_warning ("%s: %s", G_STRFUNC, error->message);
1264 g_error_free (error);
1271 * e_data_book_respond_set_backend_property:
1273 * FIXME: Document me.
1277 * Deprecated: 3.8: This function no longer does anything.
1280 e_data_book_respond_set_backend_property (EDataBook *book,
1288 e_data_book_respond_get_contact (EDataBook *book,
1293 DirectOperationData *direct = NULL;
1294 OperationData *data;
1296 g_return_if_fail (E_IS_DATA_BOOK (book));
1298 data = op_claim (book, opid, &direct);
1299 g_return_if_fail (data != NULL);
1302 /* Translators: This is prefix to a detailed error message */
1303 g_prefix_error (&error, "%s", _("Cannot get contact: "));
1304 data_book_convert_to_client_error (error);
1310 g_simple_async_result_set_error (
1314 "%s", error->message);
1315 g_error_free (error);
1317 g_simple_async_result_set_check_cancellable (
1319 direct->cancellable);
1321 if (!g_cancellable_is_cancelled (direct->cancellable)) {
1324 contact = e_contact_new_from_vcard (vcard);
1326 /* Give it an EContact for the return value */
1327 g_simple_async_result_set_op_res_gpointer (direct->result, contact, g_object_unref);
1331 /* Deliver the result to the caller */
1332 direct_operation_complete (direct);
1334 } else if (error == NULL) {
1337 utf8_vcard = e_util_utf8_make_valid (vcard);
1339 e_dbus_address_book_complete_get_contact (
1340 book->priv->dbus_interface,
1344 g_free (utf8_vcard);
1346 g_dbus_method_invocation_take_error (
1347 data->invocation, error);
1354 e_data_book_respond_get_contact_list (EDataBook *book,
1357 const GSList *cards)
1359 DirectOperationData *direct = NULL;
1360 OperationData *data;
1362 g_return_if_fail (E_IS_DATA_BOOK (book));
1364 data = op_claim (book, opid, &direct);
1365 g_return_if_fail (data != NULL);
1368 /* Translators: This is prefix to a detailed error message */
1369 g_prefix_error (&error, "%s", _("Cannot get contact list: "));
1370 data_book_convert_to_client_error (error);
1376 g_simple_async_result_set_error (
1380 "%s", error->message);
1381 g_error_free (error);
1383 g_simple_async_result_set_check_cancellable (
1385 direct->cancellable);
1387 if (!g_cancellable_is_cancelled (direct->cancellable)) {
1390 GSList *contacts = NULL;
1392 for (l = cards; l; l = l->next) {
1393 const gchar *vcard = l->data;
1395 contact = e_contact_new_from_vcard (vcard);
1396 contacts = g_slist_prepend (contacts, contact);
1399 contacts = g_slist_reverse (contacts);
1401 /* Give it an EContact for the return value */
1402 g_simple_async_result_set_op_res_gpointer (
1403 direct->result, contacts,
1404 (GDestroyNotify) e_util_free_object_slist);
1408 /* Deliver the result to the caller */
1409 direct_operation_complete (direct);
1411 } else if (error == NULL) {
1416 length = g_slist_length ((GSList *) cards);
1417 strv = g_new0 (gchar *, length + 1);
1419 while (cards != NULL) {
1420 strv[ii++] = e_util_utf8_make_valid (cards->data);
1421 cards = g_slist_next ((GSList *) cards);
1424 e_dbus_address_book_complete_get_contact_list (
1425 book->priv->dbus_interface,
1427 (const gchar * const *) strv);
1431 g_dbus_method_invocation_take_error (
1432 data->invocation, error);
1439 * e_data_book_respond_get_contact_list_uids:
1441 * FIXME: Document me.
1446 e_data_book_respond_get_contact_list_uids (EDataBook *book,
1451 DirectOperationData *direct = NULL;
1452 OperationData *data;
1454 g_return_if_fail (E_IS_DATA_BOOK (book));
1456 data = op_claim (book, opid, &direct);
1457 g_return_if_fail (data != NULL);
1460 /* Translators: This is prefix to a detailed error message */
1461 g_prefix_error (&error, "%s", _("Cannot get contact list uids: "));
1462 data_book_convert_to_client_error (error);
1468 g_simple_async_result_set_error (
1472 "%s", error->message);
1473 g_error_free (error);
1475 g_simple_async_result_set_check_cancellable (
1477 direct->cancellable);
1479 if (!g_cancellable_is_cancelled (direct->cancellable)) {
1480 GSList *ret_uids = NULL;
1482 ret_uids = e_util_copy_string_slist (NULL, uids);
1484 g_simple_async_result_set_op_res_gpointer (
1485 direct->result, ret_uids,
1486 (GDestroyNotify) e_util_free_string_slist);
1490 /* Deliver the result to the caller */
1491 direct_operation_complete (direct);
1493 } else if (error == NULL) {
1498 length = g_slist_length ((GSList *) uids);
1499 strv = g_new0 (gchar *, length + 1);
1501 while (uids != NULL) {
1502 strv[ii++] = e_util_utf8_make_valid (uids->data);
1503 uids = g_slist_next ((GSList *) uids);
1506 e_dbus_address_book_complete_get_contact_list_uids (
1507 book->priv->dbus_interface,
1509 (const gchar * const *) strv);
1513 g_dbus_method_invocation_take_error (
1514 data->invocation, error);
1521 * e_data_book_respond_create_contacts:
1523 * FIXME: Document me!
1528 e_data_book_respond_create_contacts (EDataBook *book,
1531 const GSList *contacts)
1533 OperationData *data;
1535 g_return_if_fail (E_IS_DATA_BOOK (book));
1537 data = op_claim (book, opid, NULL);
1538 g_return_if_fail (data != NULL);
1540 /* Translators: This is prefix to a detailed error message */
1541 g_prefix_error (&error, "%s", _("Cannot add contact: "));
1543 if (error == NULL) {
1544 EBookBackend *backend;
1549 backend = e_data_book_get_backend (book);
1551 length = g_slist_length ((GSList *) contacts);
1552 strv = g_new0 (gchar *, length + 1);
1554 while (contacts != NULL) {
1555 EContact *contact = E_CONTACT (contacts->data);
1558 uid = e_contact_get_const (contact, E_CONTACT_UID);
1559 strv[ii++] = e_util_utf8_make_valid (uid);
1561 e_book_backend_notify_update (backend, contact);
1563 contacts = g_slist_next ((GSList *) contacts);
1566 e_dbus_address_book_complete_create_contacts (
1567 book->priv->dbus_interface,
1569 (const gchar * const *) strv);
1571 e_book_backend_notify_complete (backend);
1575 data_book_convert_to_client_error (error);
1576 g_dbus_method_invocation_take_error (
1577 data->invocation, error);
1584 * e_data_book_respond_modify_contacts:
1586 * FIXME: Document me!
1591 e_data_book_respond_modify_contacts (EDataBook *book,
1594 const GSList *contacts)
1596 OperationData *data;
1598 g_return_if_fail (E_IS_DATA_BOOK (book));
1600 data = op_claim (book, opid, NULL);
1601 g_return_if_fail (data != NULL);
1603 /* Translators: This is prefix to a detailed error message */
1604 g_prefix_error (&error, "%s", _("Cannot modify contacts: "));
1606 if (error == NULL) {
1607 EBookBackend *backend;
1609 backend = e_data_book_get_backend (book);
1611 e_dbus_address_book_complete_modify_contacts (
1612 book->priv->dbus_interface,
1615 while (contacts != NULL) {
1616 EContact *contact = E_CONTACT (contacts->data);
1617 e_book_backend_notify_update (backend, contact);
1618 contacts = g_slist_next ((GSList *) contacts);
1621 e_book_backend_notify_complete (backend);
1623 data_book_convert_to_client_error (error);
1624 g_dbus_method_invocation_take_error (
1625 data->invocation, error);
1632 e_data_book_respond_remove_contacts (EDataBook *book,
1637 OperationData *data;
1639 g_return_if_fail (E_IS_DATA_BOOK (book));
1641 data = op_claim (book, opid, NULL);
1642 g_return_if_fail (data != NULL);
1644 /* Translators: This is prefix to a detailed error message */
1645 g_prefix_error (&error, "%s", _("Cannot remove contacts: "));
1647 if (error == NULL) {
1648 EBookBackend *backend;
1650 backend = e_data_book_get_backend (book);
1652 e_dbus_address_book_complete_remove_contacts (
1653 book->priv->dbus_interface,
1656 while (ids != NULL) {
1657 e_book_backend_notify_remove (backend, ids->data);
1658 ids = g_slist_next ((GSList *) ids);
1661 e_book_backend_notify_complete (backend);
1663 data_book_convert_to_client_error (error);
1664 g_dbus_method_invocation_take_error (
1665 data->invocation, error);
1672 * e_data_book_report_error:
1674 * FIXME: Document me.
1679 e_data_book_report_error (EDataBook *book,
1680 const gchar *message)
1682 g_return_if_fail (E_IS_DATA_BOOK (book));
1683 g_return_if_fail (message != NULL);
1685 e_dbus_address_book_emit_error (book->priv->dbus_interface, message);
1689 * e_data_book_report_readonly:
1691 * FIXME: Document me.
1695 * Deprecated: 3.8: Use e_book_backend_set_writable() instead.
1698 e_data_book_report_readonly (EDataBook *book,
1701 g_return_if_fail (E_IS_DATA_BOOK (book));
1703 e_book_backend_set_writable (book->priv->backend, !readonly);
1707 * e_data_book_report_online:
1709 * FIXME: Document me.
1713 * Deprecated: 3.8: Use e_backend_set_online() instead.
1716 e_data_book_report_online (EDataBook *book,
1719 g_return_if_fail (E_IS_DATA_BOOK (book));
1721 e_backend_set_online (E_BACKEND (book->priv->backend), is_online);
1725 * e_data_book_report_opened:
1727 * Reports to associated client that opening phase of the book is finished.
1728 * error being NULL means successfully, otherwise reports an error which
1729 * happened during opening phase. By opening phase is meant a process
1730 * including successfull authentication to the server/storage.
1734 * Deprecated: 3.8: This function no longer does anything.
1737 e_data_book_report_opened (EDataBook *book,
1738 const GError *error)
1744 * e_data_book_report_backend_property_changed:
1746 * FIXME: Document me.
1751 e_data_book_report_backend_property_changed (EDataBook *book,
1752 const gchar *prop_name,
1753 const gchar *prop_value)
1755 EDBusAddressBook *dbus_interface;
1758 g_return_if_fail (E_IS_DATA_BOOK (book));
1759 g_return_if_fail (prop_name != NULL);
1761 if (prop_value == NULL)
1764 dbus_interface = book->priv->dbus_interface;
1766 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
1767 strv = g_strsplit (prop_value, ",", -1);
1768 e_dbus_address_book_set_capabilities (
1769 dbus_interface, (const gchar * const *) strv);
1773 if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_REVISION))
1774 e_dbus_address_book_set_revision (dbus_interface, prop_value);
1776 if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
1777 strv = g_strsplit (prop_value, ",", -1);
1778 e_dbus_address_book_set_required_fields (
1779 dbus_interface, (const gchar * const *) strv);
1783 if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
1784 strv = g_strsplit (prop_value, ",", -1);
1785 e_dbus_address_book_set_supported_fields (
1786 dbus_interface, (const gchar * const *) strv);
1790 /* Disregard anything else. */
1794 data_book_interpret_locale_value (const gchar *value)
1796 gchar *interpreted_value = NULL;
1799 split = g_strsplit (value, "=", 2);
1801 if (split && split[0] && split[1])
1802 interpreted_value = g_strdup (split[1]);
1806 if (!interpreted_value)
1807 g_warning ("Failed to interpret locale value: %s", value);
1809 return interpreted_value;
1813 data_book_interpret_locale (const gchar * const * locale)
1816 gchar *interpreted_locale = NULL;
1818 /* Prioritize LC_COLLATE and then LANG values
1819 * in the 'locale' specified by localed.
1821 * If localed explicitly specifies no locale, then
1822 * default to checking system locale.
1826 for (i = 0; locale[i] != NULL && interpreted_locale == NULL; i++) {
1828 if (strncmp (locale[i], "LC_COLLATE", 10))
1829 interpreted_locale = data_book_interpret_locale_value (locale[i]);
1832 for (i = 0; locale[i] != NULL && interpreted_locale == NULL; i++) {
1834 if (strncmp (locale[i], "LANG", 4))
1835 interpreted_locale = data_book_interpret_locale_value (locale[i]);
1839 if (!interpreted_locale) {
1840 const gchar *system_locale = setlocale (LC_COLLATE, NULL);
1842 interpreted_locale = g_strdup (system_locale);
1845 return interpreted_locale;
1849 data_book_locale_changed (GObject *object,
1853 EDBusLocale1 *locale_proxy = E_DBUS_LOCALE1 (object);
1854 EDataBook *book = (EDataBook *)user_data;
1855 EBookBackend *backend;
1857 backend = book->priv->backend;
1860 const gchar * const *locale;
1861 gchar *interpreted_locale;
1863 locale = e_dbus_locale1_get_locale (locale_proxy);
1864 interpreted_locale = data_book_interpret_locale (locale);
1866 e_book_backend_set_locale (backend, interpreted_locale);
1868 e_dbus_address_book_set_locale (book->priv->dbus_interface, interpreted_locale);
1870 g_free (interpreted_locale);
1875 data_book_localed_ready (GObject *source_object,
1879 EDataBook *book = (EDataBook *)user_data;
1880 GError *error = NULL;
1882 book->priv->localed_proxy = e_dbus_locale1_proxy_new_finish (res, &error);
1884 if (book->priv->localed_proxy == NULL) {
1885 g_warning ("Error fetching localed proxy: %s", error->message);
1886 g_error_free (error);
1889 if (book->priv->localed_cancel) {
1890 g_object_unref (book->priv->localed_cancel);
1891 book->priv->localed_cancel = NULL;
1894 if (book->priv->localed_proxy) {
1895 g_signal_connect (book->priv->localed_proxy, "notify::locale",
1896 G_CALLBACK (data_book_locale_changed), book);
1898 /* Initial refresh the locale */
1899 data_book_locale_changed (G_OBJECT (book->priv->localed_proxy), NULL, book);
1904 data_book_localed_appeared (GDBusConnection *connection,
1906 const gchar *name_owner,
1909 EDataBook *book = (EDataBook *)user_data;
1911 book->priv->localed_cancel = g_cancellable_new ();
1913 e_dbus_locale1_proxy_new (connection,
1914 G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
1915 "org.freedesktop.locale1",
1916 "/org/freedesktop/locale1",
1917 book->priv->localed_cancel,
1918 data_book_localed_ready,
1923 data_book_localed_vanished (GDBusConnection *connection,
1927 EDataBook *book = (EDataBook *)user_data;
1929 if (book->priv->localed_cancel) {
1930 g_cancellable_cancel (book->priv->localed_cancel);
1931 g_object_unref (book->priv->localed_cancel);
1932 book->priv->localed_cancel = NULL;
1935 if (book->priv->localed_proxy) {
1936 g_object_unref (book->priv->localed_proxy);
1937 book->priv->localed_proxy = NULL;
1942 data_book_set_backend (EDataBook *book,
1943 EBookBackend *backend)
1945 g_return_if_fail (E_IS_BOOK_BACKEND (backend));
1946 g_return_if_fail (book->priv->backend == NULL);
1948 book->priv->backend = g_object_ref (backend);
1952 data_book_set_connection (EDataBook *book,
1953 GDBusConnection *connection)
1955 g_return_if_fail (connection == NULL ||
1956 G_IS_DBUS_CONNECTION (connection));
1957 g_return_if_fail (book->priv->connection == NULL);
1960 book->priv->connection = g_object_ref (connection);
1964 data_book_set_object_path (EDataBook *book,
1965 const gchar *object_path)
1967 g_return_if_fail (book->priv->object_path == NULL);
1969 book->priv->object_path = g_strdup (object_path);
1973 data_book_set_property (GObject *object,
1975 const GValue *value,
1978 switch (property_id) {
1980 data_book_set_backend (
1981 E_DATA_BOOK (object),
1982 g_value_get_object (value));
1985 case PROP_CONNECTION:
1986 data_book_set_connection (
1987 E_DATA_BOOK (object),
1988 g_value_get_object (value));
1991 case PROP_OBJECT_PATH:
1992 data_book_set_object_path (
1993 E_DATA_BOOK (object),
1994 g_value_get_string (value));
1998 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
2002 data_book_get_property (GObject *object,
2007 switch (property_id) {
2009 g_value_set_object (
2011 e_data_book_get_backend (
2012 E_DATA_BOOK (object)));
2015 case PROP_CONNECTION:
2016 g_value_set_object (
2018 e_data_book_get_connection (
2019 E_DATA_BOOK (object)));
2022 case PROP_OBJECT_PATH:
2023 g_value_set_string (
2025 e_data_book_get_object_path (
2026 E_DATA_BOOK (object)));
2030 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
2034 data_book_dispose (GObject *object)
2036 EDataBookPrivate *priv;
2038 priv = E_DATA_BOOK_GET_PRIVATE (object);
2040 if (priv->connection != NULL) {
2041 g_object_unref (priv->connection);
2042 priv->connection = NULL;
2045 if (priv->backend != NULL) {
2046 g_object_unref (priv->backend);
2047 priv->backend = NULL;
2050 if (priv->direct_book) {
2051 g_object_unref (priv->direct_book);
2052 priv->direct_book = NULL;
2055 if (priv->direct_module) {
2056 g_type_module_unuse (G_TYPE_MODULE (priv->direct_module));
2057 priv->direct_module = NULL;
2060 if (priv->localed_cancel) {
2061 g_cancellable_cancel (priv->localed_cancel);
2062 g_object_unref (priv->localed_cancel);
2063 priv->localed_cancel = NULL;
2066 if (priv->localed_proxy) {
2067 g_object_unref (priv->localed_proxy);
2068 priv->localed_proxy = NULL;
2071 /* Chain up to parent's dispose() metnod. */
2072 G_OBJECT_CLASS (e_data_book_parent_class)->dispose (object);
2076 data_book_finalize (GObject *object)
2078 EDataBookPrivate *priv;
2080 priv = E_DATA_BOOK_GET_PRIVATE (object);
2082 g_free (priv->object_path);
2084 if (priv->pending_ops) {
2085 g_hash_table_destroy (priv->pending_ops);
2086 priv->pending_ops = NULL;
2089 g_rec_mutex_clear (&priv->pending_ops_lock);
2090 if (priv->direct_ops) {
2091 g_hash_table_destroy (priv->direct_ops);
2092 priv->direct_ops = NULL;
2095 if (priv->dbus_interface) {
2096 g_object_unref (priv->dbus_interface);
2097 priv->dbus_interface = NULL;
2100 g_mutex_clear (&priv->open_lock);
2102 /* This should be empty now, else we leak memory. */
2103 g_warn_if_fail (g_queue_is_empty (&priv->open_queue));
2105 if (priv->localed_watch_id > 0)
2106 g_bus_unwatch_name (priv->localed_watch_id);
2108 /* Chain up to parent's finalize() method. */
2109 G_OBJECT_CLASS (e_data_book_parent_class)->finalize (object);
2113 data_book_initable_init (GInitable *initable,
2114 GCancellable *cancellable,
2119 const gchar *locale;
2120 GBusType bus_type = G_BUS_TYPE_SYSTEM;
2122 book = E_DATA_BOOK (initable);
2124 if (book->priv->connection != NULL && book->priv->object_path != NULL) {
2125 book->priv->dbus_interface =
2126 e_dbus_address_book_skeleton_new ();
2129 book->priv->dbus_interface, "handle-open",
2130 G_CALLBACK (data_book_handle_open_cb), book);
2132 book->priv->dbus_interface, "handle-refresh",
2133 G_CALLBACK (data_book_handle_refresh_cb), book);
2135 book->priv->dbus_interface, "handle-get-contact",
2136 G_CALLBACK (data_book_handle_get_contact_cb), book);
2138 book->priv->dbus_interface, "handle-get-contact-list",
2139 G_CALLBACK (data_book_handle_get_contact_list_cb), book);
2141 book->priv->dbus_interface, "handle-get-contact-list-uids",
2142 G_CALLBACK (data_book_handle_get_contact_list_uids_cb), book);
2144 book->priv->dbus_interface, "handle-create-contacts",
2145 G_CALLBACK (data_book_handle_create_contacts_cb), book);
2147 book->priv->dbus_interface, "handle-remove-contacts",
2148 G_CALLBACK (data_book_handle_remove_contacts_cb), book);
2150 book->priv->dbus_interface, "handle-modify-contacts",
2151 G_CALLBACK (data_book_handle_modify_contacts_cb), book);
2153 book->priv->dbus_interface, "handle-get-view",
2154 G_CALLBACK (data_book_handle_get_view_cb), book);
2156 book->priv->dbus_interface, "handle-close",
2157 G_CALLBACK (data_book_handle_close_cb), book);
2159 /* This will be NULL for a backend that does not support
2160 * direct read access. */
2161 book->priv->direct_book =
2162 e_book_backend_get_direct_book (book->priv->backend);
2164 if (book->priv->direct_book != NULL) {
2167 success = e_data_book_direct_register_gdbus_object (
2168 book->priv->direct_book,
2169 book->priv->connection,
2170 book->priv->object_path,
2176 g_object_bind_property (
2177 book->priv->backend, "cache-dir",
2178 book->priv->dbus_interface, "cache-dir",
2179 G_BINDING_SYNC_CREATE);
2181 g_object_bind_property (
2182 book->priv->backend, "online",
2183 book->priv->dbus_interface, "online",
2184 G_BINDING_SYNC_CREATE);
2186 g_object_bind_property (
2187 book->priv->backend, "writable",
2188 book->priv->dbus_interface, "writable",
2189 G_BINDING_SYNC_CREATE);
2191 /* XXX Initialize the rest of the properties by faking client
2192 * requests. At present it's the only way to fish values
2193 * from EBookBackend's antiquated API. */
2195 op = op_new (OP_GET_BACKEND_PROPERTY, book, NULL);
2196 op->d.prop_name = CLIENT_BACKEND_PROPERTY_CAPABILITIES;
2197 e_book_backend_get_backend_property (
2198 book->priv->backend, book, op->id,
2199 op->cancellable, op->d.prop_name);
2202 op = op_new (OP_GET_BACKEND_PROPERTY, book, NULL);
2203 op->d.prop_name = CLIENT_BACKEND_PROPERTY_REVISION;
2204 e_book_backend_get_backend_property (
2205 book->priv->backend, book, op->id,
2206 op->cancellable, op->d.prop_name);
2209 op = op_new (OP_GET_BACKEND_PROPERTY, book, NULL);
2210 op->d.prop_name = BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
2211 e_book_backend_get_backend_property (
2212 book->priv->backend, book, op->id,
2213 op->cancellable, op->d.prop_name);
2216 op = op_new (OP_GET_BACKEND_PROPERTY, book, NULL);
2217 op->d.prop_name = BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
2218 e_book_backend_get_backend_property (
2219 book->priv->backend, book, op->id,
2220 op->cancellable, op->d.prop_name);
2223 /* Fetch backend configured locale and set that as the initial
2224 * value on the dbus object
2226 locale = e_book_backend_get_locale (book->priv->backend);
2227 e_dbus_address_book_set_locale (book->priv->dbus_interface, locale);
2229 /* When running tests, we pretend to be the "org.freedesktop.locale1" service
2230 * on the session bus instead of the real location on the system bus.
2232 if (g_getenv ("EDS_TESTING") != NULL)
2233 bus_type = G_BUS_TYPE_SESSION;
2235 /* Watch system bus for locale change notifications */
2236 book->priv->localed_watch_id =
2237 g_bus_watch_name (bus_type,
2238 "org.freedesktop.locale1",
2239 G_BUS_NAME_WATCHER_FLAGS_NONE,
2240 data_book_localed_appeared,
2241 data_book_localed_vanished,
2245 return g_dbus_interface_skeleton_export (
2246 G_DBUS_INTERFACE_SKELETON (book->priv->dbus_interface),
2247 book->priv->connection,
2248 book->priv->object_path,
2256 e_data_book_class_init (EDataBookClass *class)
2258 GObjectClass *object_class;
2260 g_type_class_add_private (class, sizeof (EDataBookPrivate));
2262 object_class = G_OBJECT_CLASS (class);
2263 object_class->set_property = data_book_set_property;
2264 object_class->get_property = data_book_get_property;
2265 object_class->dispose = data_book_dispose;
2266 object_class->finalize = data_book_finalize;
2268 g_object_class_install_property (
2271 g_param_spec_object (
2274 "The backend driving this connection",
2275 E_TYPE_BOOK_BACKEND,
2277 G_PARAM_CONSTRUCT_ONLY |
2278 G_PARAM_STATIC_STRINGS));
2280 g_object_class_install_property (
2283 g_param_spec_object (
2286 "The GDBusConnection on which to "
2287 "export the address book interface",
2288 G_TYPE_DBUS_CONNECTION,
2290 G_PARAM_CONSTRUCT_ONLY |
2291 G_PARAM_STATIC_STRINGS));
2293 g_object_class_install_property (
2296 g_param_spec_string (
2299 "The object path at which to "
2300 "export the address book interface",
2303 G_PARAM_CONSTRUCT_ONLY |
2304 G_PARAM_STATIC_STRINGS));
2307 ops_pool = e_operation_pool_new (10, operation_thread, NULL);
2311 e_data_book_initable_init (GInitableIface *interface)
2313 interface->init = data_book_initable_init;
2317 e_data_book_init (EDataBook *ebook)
2319 ebook->priv = E_DATA_BOOK_GET_PRIVATE (ebook);
2321 ebook->priv->pending_ops = g_hash_table_new_full (
2322 (GHashFunc) g_direct_hash,
2323 (GEqualFunc) g_direct_equal,
2324 (GDestroyNotify) NULL,
2325 (GDestroyNotify) op_unref);
2326 ebook->priv->direct_ops = g_hash_table_new_full (
2327 g_direct_hash, g_direct_equal, NULL,
2328 (GDestroyNotify) direct_operation_data_free);
2329 g_rec_mutex_init (&ebook->priv->pending_ops_lock);
2330 g_mutex_init (&ebook->priv->open_lock);
2335 * @backend: an #EBookBackend
2336 * @connection: a #GDBusConnection
2337 * @object_path: object path for the D-Bus interface
2338 * @error: return location for a #GError, or %NULL
2340 * Creates a new #EDataBook and exports the AddressBook D-Bus interface
2341 * on @connection at @object_path. The #EDataBook handles incoming remote
2342 * method invocations and forwards them to the @backend. If the AddressBook
2343 * interface fails to export, the function sets @error and returns %NULL.
2345 * Returns: an #EDataBook, or %NULL on error
2348 e_data_book_new (EBookBackend *backend,
2349 GDBusConnection *connection,
2350 const gchar *object_path,
2353 g_return_val_if_fail (E_IS_BOOK_BACKEND (backend), NULL);
2354 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
2355 g_return_val_if_fail (object_path != NULL, NULL);
2357 return g_initable_new (
2358 E_TYPE_DATA_BOOK, NULL, error,
2360 "connection", connection,
2361 "object-path", object_path,
2366 * e_data_book_new_direct:
2367 * @registry: The #ESourceRegistry
2368 * @source: The #ESource to create a book for
2369 * @backend_path: The full path to the backend module to use
2370 * @backend_name: The #EDataFactory type name to use from the module specified by @backend_path
2371 * @config: The backend specific configuration string specified by the #EDataBookDirect
2372 * @error: (allow-none): return location for a #GError, or %NULL
2374 * Creates an #EDataBook for Direct Read Access, the @backend_path, @backend_name and @config
2375 * parameters are fetched from an #EDataBookDirect reported over D-Bus from the server side
2376 * counter part of a given backend.
2378 * <note><para>This API is intended for internal use only, if you want client side
2379 * direct read access then use e_book_client_connect_direct_sync() instead</para></note>
2381 * Returns: (transfer full): A newly created #EDataBook for direct read access,
2382 * otherwise %NULL is returned and @error is set.
2387 e_data_book_new_direct (ESourceRegistry *registry,
2389 const gchar *backend_path,
2390 const gchar *backend_name,
2391 const gchar *config,
2394 EDataBook *book = NULL;
2396 EBookBackend *backend;
2399 GTypeClass *factory_class;
2401 g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
2402 g_return_val_if_fail (E_IS_SOURCE (source), NULL);
2403 g_return_val_if_fail (backend_path && backend_path[0], NULL);
2404 g_return_val_if_fail (backend_name && backend_name[0], NULL);
2406 module = load_module (backend_path);
2409 error, E_CLIENT_ERROR,
2410 E_CLIENT_ERROR_OTHER_ERROR,
2411 "Failed to load module at specified path: %s", backend_path);
2412 goto new_direct_finish;
2415 if (!g_type_module_use (G_TYPE_MODULE (module))) {
2417 error, E_CLIENT_ERROR,
2418 E_CLIENT_ERROR_OTHER_ERROR,
2419 "Failed to use EModule at path: %s", backend_path);
2420 goto new_direct_finish;
2423 factory_type = g_type_from_name (backend_name);
2424 if (factory_type == 0) {
2426 error, E_CLIENT_ERROR,
2427 E_CLIENT_ERROR_OTHER_ERROR,
2428 "Failed to get backend factory '%s' from EModule at path: %s",
2429 backend_name, backend_path);
2430 g_type_module_unuse (G_TYPE_MODULE (module));
2431 goto new_direct_finish;
2434 factory_class = g_type_class_ref (factory_type);
2435 backend_type = E_BOOK_BACKEND_FACTORY_CLASS (factory_class)->backend_type;
2436 g_type_class_unref (factory_class);
2438 backend = g_object_new (
2440 "registry", registry,
2441 "source", source, NULL);
2443 /* The backend must be configured for direct access
2444 * before calling g_initable_init() because backends
2445 * now can open thier content at initable_init() time. */
2446 e_book_backend_configure_direct (backend, config);
2448 if (!g_initable_init (G_INITABLE (backend), NULL, error)) {
2449 g_object_unref (backend);
2450 g_type_module_unuse (G_TYPE_MODULE (module));
2451 goto new_direct_finish;
2454 book = g_initable_new (
2455 E_TYPE_DATA_BOOK, NULL, error,
2456 "backend", backend, NULL);
2457 g_object_unref (backend);
2460 g_type_module_unuse (G_TYPE_MODULE (module));
2461 goto new_direct_finish;
2464 book->priv->direct_module = module;
2472 * e_data_book_get_backend:
2473 * @book: an #EDataBook
2475 * Returns the #EBookBackend to which incoming remote method invocations
2476 * are being forwarded.
2478 * Returns: the #EBookBackend
2481 e_data_book_get_backend (EDataBook *book)
2483 g_return_val_if_fail (E_IS_DATA_BOOK (book), NULL);
2485 return book->priv->backend;
2489 * e_data_book_get_connection:
2490 * @book: an #EDataBook
2492 * Returns the #GDBusConnection on which the AddressBook D-Bus interface
2495 * Returns: the #GDBusConnection
2500 e_data_book_get_connection (EDataBook *book)
2502 g_return_val_if_fail (E_IS_DATA_BOOK (book), NULL);
2504 return book->priv->connection;
2508 * e_data_book_get_object_path:
2509 * @book: an #EDataBook
2511 * Returns the object path at which the AddressBook D-Bus interface is
2514 * Returns: the object path
2519 e_data_book_get_object_path (EDataBook *book)
2521 g_return_val_if_fail (E_IS_DATA_BOOK (book), NULL);
2523 return book->priv->object_path;
2526 /*************************************************************************
2527 * Direct Read Access APIs *
2528 *************************************************************************/
2531 e_data_book_open_finish (EDataBook *book,
2532 GAsyncResult *result,
2537 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
2538 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2540 res = g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (result));
2541 g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
2547 * e_data_book_open_sync:
2548 * @book: an #EDataBook
2549 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2550 * @error: (allow-none): return location for a #GError, or %NULL
2552 * Opens the #EDataBook and it's backend.
2554 * <note><para>This API is intended for internal use only, if you want client side
2555 * direct read access then use e_book_client_connect_direct_sync() instead</para></note>
2557 * Returns: %TRUE on success. If %FALSE is returned, @error will be set
2562 e_data_book_open_sync (EDataBook *book,
2563 GCancellable *cancellable,
2566 DirectOperationData *data = NULL;
2568 gboolean result = FALSE;
2570 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
2572 op = op_direct_new (OP_OPEN, book, cancellable, NULL, NULL, e_data_book_open_sync, TRUE, &data);
2574 op_dispatch (book, op);
2576 direct_operation_wait (data);
2577 result = e_data_book_open_finish (book, G_ASYNC_RESULT (data->result), error);
2578 direct_operation_data_free (data);
2584 e_data_book_respond_close (EDataBook *book,
2588 DirectOperationData *data;
2590 data = op_complete (book, opid);
2593 gboolean result = FALSE;
2596 g_simple_async_result_set_error (
2600 "%s", error->message);
2603 if (!g_cancellable_is_cancelled (data->cancellable))
2606 g_simple_async_result_set_check_cancellable (
2611 g_simple_async_result_set_op_res_gboolean (data->result, result);
2613 /* Deliver the result to the caller */
2614 direct_operation_complete (data);
2618 g_error_free (error);
2622 * e_data_book_close:
2623 * @book: an #EDataBook
2624 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2625 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2627 * @user_data: (closure): data to pass to @callback
2629 * Closes the @book and its backend.
2631 * <note><para>This API is intended for internal use only, if you want client side
2632 * direct read access then use e_book_client_connect_direct_sync() instead</para></note>
2637 e_data_book_close (EDataBook *book,
2638 GCancellable *cancellable,
2639 GAsyncReadyCallback callback,
2644 g_return_if_fail (E_IS_DATA_BOOK (book));
2646 op = op_direct_new (OP_CLOSE, book, cancellable, callback, user_data, e_data_book_close, FALSE, NULL);
2648 /* This operation is never queued. */
2649 e_operation_pool_push (ops_pool, op);
2653 * e_data_book_close_finish:
2654 * @book: an #EDataBook
2655 * @result: a #GAsyncResult
2656 * @error: (allow-none): return location for a #GError, or %NULL
2658 * Finishes the operation started with e_data_book_close(). If an
2659 * error occurs, then this function sets @error and returns %FALSE.
2661 * Returns: %TRUE on success
2666 e_data_book_close_finish (EDataBook *book,
2667 GAsyncResult *result,
2672 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
2673 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2675 res = g_simple_async_result_get_op_res_gboolean (G_SIMPLE_ASYNC_RESULT (result));
2676 g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
2682 * e_data_book_close_sync:
2683 * @book: an #EDataBook
2684 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2685 * @error: (allow-none): return location for a #GError, or %NULL
2687 * Closes the @book and its backend.
2689 * <note><para>This API is intended for internal use only, if you want client side
2690 * direct read access then use e_book_client_connect_direct_sync() instead</para></note>
2692 * Returns: %TRUE on success. If %FALSE is returned, @error will be set
2697 e_data_book_close_sync (EDataBook *book,
2698 GCancellable *cancellable,
2701 DirectOperationData *data = NULL;
2703 gboolean result = FALSE;
2705 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
2707 op = op_direct_new (OP_CLOSE, book, cancellable, NULL, NULL, e_data_book_close_sync, TRUE, &data);
2709 /* This operation is never queued. */
2710 e_operation_pool_push (ops_pool, op);
2712 direct_operation_wait (data);
2713 result = e_data_book_close_finish (book, G_ASYNC_RESULT (data->result), error);
2714 direct_operation_data_free (data);
2720 * e_data_book_get_contact:
2721 * @book: an #EDataBook
2722 * @uid: a unique string ID specifying the contact
2723 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2724 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2726 * @user_data: (closure): data to pass to @callback
2728 * Retrieves #EContact from the @book for the gived @uid.
2729 * The call is finished by e_data_book_get_contact_finish()
2730 * from the @callback.
2732 * <note><para>This API is intended for internal use only, if you want client side
2733 * direct read access then use e_book_client_connect_direct_sync() instead</para></note>
2738 e_data_book_get_contact (EDataBook *book,
2740 GCancellable *cancellable,
2741 GAsyncReadyCallback callback,
2746 g_return_if_fail (E_IS_DATA_BOOK (book));
2747 g_return_if_fail (uid && uid[0]);
2749 op = op_direct_new (OP_GET_CONTACT, book, cancellable, callback, user_data, e_data_book_get_contact, FALSE, NULL);
2750 op->d.uid = g_strdup (uid);
2752 op_dispatch (book, op);
2756 * e_data_book_get_contact_finish:
2757 * @book: an #EDataBook
2758 * @result: a #GAsyncResult
2759 * @contact: return location for the fetched #EContact
2760 * @error: (allow-none): return location for a #GError, or %NULL
2762 * Finishes the operation started with e_data_book_get_contact(). If an
2763 * error occurs, then this function sets @error and returns %FALSE.
2765 * Returns: %TRUE on success
2770 e_data_book_get_contact_finish (EDataBook *book,
2771 GAsyncResult *result,
2775 EContact *ret_contact;
2777 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
2778 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2780 ret_contact = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
2781 g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
2785 *contact = g_object_ref (ret_contact);
2790 return ret_contact != NULL;
2794 * e_data_book_get_contact_sync:
2795 * @book: an #EDataBook
2796 * @uid: a unique string ID specifying the contact
2797 * @contact: return location for the fetched #EContact
2798 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2799 * @error: (allow-none): return location for a #GError, or %NULL
2801 * Retrieves an #EContact from the @book for the gived @uid.
2803 * <note><para>This API is intended for internal use only, if you want client side
2804 * direct read access then use e_book_client_connect_direct_sync() instead</para></note>
2806 * Returns: %TRUE on success. If %FALSE is returned, @error will be set
2811 e_data_book_get_contact_sync (EDataBook *book,
2814 GCancellable *cancellable,
2817 DirectOperationData *data = NULL;
2819 gboolean result = FALSE;
2821 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
2822 g_return_val_if_fail (uid && uid[0], FALSE);
2824 op = op_direct_new (OP_GET_CONTACT, book, cancellable, NULL, NULL, e_data_book_get_contact_sync, TRUE, &data);
2825 op->d.uid = g_strdup (uid);
2827 op_dispatch (book, op);
2829 direct_operation_wait (data);
2830 result = e_data_book_get_contact_finish (book, G_ASYNC_RESULT (data->result), contact, error);
2831 direct_operation_data_free (data);
2837 * e_data_book_get_contacts:
2838 * @book: an #EDataBook
2839 * @sexp: an S-expression representing the query
2840 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2841 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2843 * @user_data: (closure): data to pass to @callback
2845 * Query @book with @sexp, receiving a list of contacts which
2846 * matched. The call is finished by e_data_book_get_contacts_finish()
2847 * from the @callback.
2849 * <note><para>This API is intended for internal use only, if you want client side
2850 * direct read access then use e_book_client_connect_direct_sync() instead</para></note>
2855 e_data_book_get_contacts (EDataBook *book,
2857 GCancellable *cancellable,
2858 GAsyncReadyCallback callback,
2863 g_return_if_fail (E_IS_DATA_BOOK (book));
2865 op = op_direct_new (OP_GET_CONTACTS, book, cancellable, callback, user_data, e_data_book_get_contacts, FALSE, NULL);
2866 op->d.query = g_strdup (sexp);
2868 op_dispatch (book, op);
2872 * e_data_book_get_contacts_finish:
2873 * @book: an #EDataBook
2874 * @result: a #GAsyncResult
2875 * @contacts: (element-type EContact) (out): a #GSList of matched #EContacts
2876 * @error: (allow-none): return location for a #GError, or %NULL
2878 * Finishes the operation started with e_data_book_get_contacts(). If an
2879 * error occurs, then this function sets @error and returns %FALSE.
2881 * Returns: %TRUE on success
2886 e_data_book_get_contacts_finish (EDataBook *book,
2887 GAsyncResult *result,
2891 GSList *ret_contacts;
2893 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
2894 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
2896 ret_contacts = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
2900 *contacts = e_util_copy_object_slist (NULL, ret_contacts);
2905 /* If there was an error, the return is FALSE, otherwise
2906 * the call was successfull even if no results were found
2908 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
2915 * e_data_book_get_contacts_sync:
2916 * @book: an #EDataBook
2917 * @sexp: an S-expression representing the query
2918 * @contacts: (element-type EContact) (out): a #GSList of matched #EContacts
2919 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2920 * @error: (allow-none): return location for a #GError, or %NULL
2922 * Query @book with @sexp, receiving a list of contacts which
2925 * <note><para>This API is intended for internal use only, if you want client side
2926 * direct read access then use e_book_client_connect_direct_sync() instead</para></note>
2928 * Returns: %TRUE on success. If %FALSE is returned, @error will be set
2933 e_data_book_get_contacts_sync (EDataBook *book,
2936 GCancellable *cancellable,
2939 DirectOperationData *data = NULL;
2941 gboolean result = FALSE;
2943 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
2945 op = op_direct_new (OP_GET_CONTACTS, book, cancellable, NULL, NULL, e_data_book_get_contacts_sync, TRUE, &data);
2946 op->d.query = g_strdup (sexp);
2948 op_dispatch (book, op);
2950 direct_operation_wait (data);
2951 result = e_data_book_get_contacts_finish (book, G_ASYNC_RESULT (data->result), contacts, error);
2952 direct_operation_data_free (data);
2958 * e_data_book_get_contacts_uids:
2959 * @book: an #EDataBook
2960 * @sexp: an S-expression representing the query
2961 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
2962 * @callback: (scope async): a #GAsyncReadyCallback to call when the request
2964 * @user_data: (closure): data to pass to @callback
2966 * Query @book with @sexp, receiving a list of contacts UIDs which
2967 * matched. The call is finished by e_data_book_get_contacts_uids_finish()
2968 * from the @callback.
2970 * <note><para>This API is intended for internal use only, if you want client side
2971 * direct read access then use e_book_client_connect_direct_sync() instead</para></note>
2976 e_data_book_get_contacts_uids (EDataBook *book,
2978 GCancellable *cancellable,
2979 GAsyncReadyCallback callback,
2984 g_return_if_fail (E_IS_DATA_BOOK (book));
2986 op = op_direct_new (OP_GET_CONTACTS_UIDS, book, cancellable, callback, user_data, e_data_book_get_contacts_uids, FALSE, NULL);
2987 op->d.query = g_strdup (sexp);
2989 op_dispatch (book, op);
2993 * e_data_book_get_contacts_uids_finish:
2994 * @book: an #EDataBook
2995 * @result: a #GAsyncResult
2996 * @contacts_uids: (element-type utf8) (out): a #GSList of matched contact UIDs stored as strings
2997 * @error: (allow-none): return location for a #GError, or %NULL
2999 * Finishes the operation started with e_data_book_get_contacts_uids(). If an
3000 * error occurs, then this function sets @error and returns %FALSE.
3002 * Returns: %TRUE on success
3007 e_data_book_get_contacts_uids_finish (EDataBook *book,
3008 GAsyncResult *result,
3009 GSList **contacts_uids,
3014 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
3015 g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
3017 ret_uids = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
3019 if (contacts_uids) {
3021 *contacts_uids = e_util_copy_string_slist (NULL, ret_uids);
3023 *contacts_uids = NULL;
3026 /* If there was an error, the return is FALSE, otherwise
3027 * the call was successfull even if no results were found
3029 if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
3036 * e_data_book_get_contacts_uids_sync:
3037 * @book: an #EDataBook
3038 * @sexp: an S-expression representing the query
3039 * @contacts_uids: (element-type utf8) (out): a #GSList of matched contact UIDs stored as strings
3040 * @cancellable: (allow-none): optional #GCancellable object, or %NULL
3041 * @error: (allow-none): return location for a #GError, or %NULL
3043 * Query @book with @sexp, receiving a list of contacts UIDs which
3046 * <note><para>This API is intended for internal use only, if you want client side
3047 * direct read access then use e_book_client_connect_direct_sync() instead</para></note>
3049 * Returns: %TRUE on success. If %FALSE is returned, @error will be set
3054 e_data_book_get_contacts_uids_sync (EDataBook *book,
3056 GSList **contacts_uids,
3057 GCancellable *cancellable,
3060 DirectOperationData *data = NULL;
3062 gboolean result = FALSE;
3064 g_return_val_if_fail (E_IS_DATA_BOOK (book), FALSE);
3066 op = op_direct_new (OP_GET_CONTACTS_UIDS, book, cancellable, NULL, NULL, e_data_book_get_contacts_uids_sync, TRUE, &data);
3067 op->d.query = g_strdup (sexp);
3069 op_dispatch (book, op);
3071 direct_operation_wait (data);
3072 result = e_data_book_get_contacts_uids_finish (book, G_ASYNC_RESULT (data->result), contacts_uids, error);
3073 direct_operation_data_free (data);