[evolution-data-server/wip/mcrha/libical-glib] [Addressbook] Change API to be able to pass flags into create/modify/remove operations



commit 02b8883c1680eebc55e4b96b4bd2d658f8e32fd7
Author: Milan Crha <mcrha redhat com>
Date:   Thu Apr 11 12:30:13 2019 +0200

    [Addressbook] Change API to be able to pass flags into create/modify/remove operations

 CMakeLists.txt                                     |   6 +-
 .../evolution-data-server-docs.sgml.in             |   3 +-
 po/POTFILES.in                                     |   2 +-
 .../backends/carddav/e-book-backend-carddav.c      |   3 +
 .../backends/file/e-book-backend-file.c            |  29 +--
 .../backends/google/e-book-backend-google.c        |   6 +-
 .../backends/ldap/e-book-backend-ldap.c            |  15 +-
 src/addressbook/libebook-contacts/CMakeLists.txt   |   7 +-
 .../libebook-contacts/e-book-contacts-enums.h      | 148 ++++++++++++++++
 .../libebook-contacts/e-book-contacts-types.c      |  73 --------
 .../libebook-contacts/e-book-contacts-utils.c      | 168 ++++++++++++++++++
 ...ok-contacts-types.h => e-book-contacts-utils.h} | 148 ++++------------
 .../e-source-backend-summary-setup.h               |   2 +-
 .../libebook-contacts/libebook-contacts.h          |   5 +-
 src/addressbook/libebook/e-book-client.c           | 173 +++++++++++-------
 src/addressbook/libebook/e-book-client.h           |  22 ++-
 src/addressbook/libebook/e-book.c                  |  58 +++---
 .../libedata-book/e-book-backend-sync.c            |  27 ++-
 .../libedata-book/e-book-backend-sync.h            |  12 +-
 src/addressbook/libedata-book/e-book-backend.c     |  73 +++++---
 src/addressbook/libedata-book/e-book-backend.h     |  15 +-
 src/addressbook/libedata-book/e-book-cache.c       | 196 +++++++++++++++++++--
 src/addressbook/libedata-book/e-book-cache.h       |  26 ++-
 .../libedata-book/e-book-meta-backend.c            |  70 +++++---
 .../libedata-book/e-book-meta-backend.h            |   4 +
 src/addressbook/libedata-book/e-data-book.c        |  35 ++--
 src/examples/cursor/cursor-data.c                  |   2 +-
 .../org.gnome.evolution.dataserver.AddressBook.xml |   3 +
 tests/book-migration/setup-migration-test.c        |   2 +-
 tests/book-migration/test-migration.c              |   4 +-
 tests/libebook/client/client-test-utils.c          |   4 +-
 .../client/test-book-client-add-and-get-async.c    |   2 +-
 .../libebook/client/test-book-client-add-contact.c |   2 +-
 .../client/test-book-client-cursor-operations.c    |  15 +-
 .../client/test-book-client-custom-summary.c       |   2 +-
 .../libebook/client/test-book-client-e164-param.c  |   2 +-
 .../client/test-book-client-get-revision.c         |   2 +-
 .../client/test-book-client-modify-contact.c       |   4 +-
 .../client/test-book-client-photo-is-uri.c         |   8 +-
 .../client/test-book-client-preserve-uid.c         |   4 +-
 .../test-book-client-remove-contact-by-uid.c       |   4 +-
 .../client/test-book-client-remove-contact.c       |   6 +-
 .../client/test-book-client-remove-contacts.c      |   4 +-
 tests/libebook/client/test-book-client-self.c      |   2 +-
 .../libebook/client/test-book-client-write-write.c |   2 +-
 .../test-book-cache-cursor-calculate.c             |  12 +-
 tests/libedata-book/test-book-cache-offline.c      |  89 ++++++++--
 tests/libedata-book/test-book-cache-utils.c        |   4 +-
 tests/libedata-book/test-book-meta-backend.c       |  38 ++--
 49 files changed, 1045 insertions(+), 498 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b341fabb4..55d308a4e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,7 +40,7 @@ set(PROJECT_DISTCONFIGURE_PARAMS
 # D-Bus versioning
 # ******************************
 # Actual name can be modified with DBUS_SERVICES_PREFIX option
-set(ADDRESS_BOOK_DBUS_SERVICE_NAME     "org.gnome.evolution.dataserver.AddressBook9")
+set(ADDRESS_BOOK_DBUS_SERVICE_NAME     "org.gnome.evolution.dataserver.AddressBook10")
 set(CALENDAR_DBUS_SERVICE_NAME         "org.gnome.evolution.dataserver.Calendar8")
 set(SOURCES_DBUS_SERVICE_NAME          "org.gnome.evolution.dataserver.Sources5")
 set(USER_PROMPTER_DBUS_SERVICE_NAME    "org.gnome.evolution.dataserver.UserPrompter0")
@@ -64,11 +64,11 @@ set(LIBEDATASERVERUI_CURRENT 2)
 set(LIBEDATASERVERUI_REVISION 0)
 set(LIBEDATASERVERUI_AGE 0)
 
-set(LIBEBOOK_CURRENT 19)
+set(LIBEBOOK_CURRENT 20)
 set(LIBEBOOK_REVISION 1)
 set(LIBEBOOK_AGE 3)
 
-set(LIBEBOOK_CONTACTS_CURRENT 2)
+set(LIBEBOOK_CONTACTS_CURRENT 3)
 set(LIBEBOOK_CONTACTS_REVISION 0)
 set(LIBEBOOK_CONTACTS_AGE 0)
 
diff --git a/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in 
b/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
index 7742a7483..1f9d0318a 100644
--- a/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
+++ b/docs/reference/evolution-data-server/evolution-data-server-docs.sgml.in
@@ -283,7 +283,8 @@
 
     <chapter>
       <title>Addressbook related utilities</title>
-      <xi:include href="xml/e-book-contacts-types.xml"/>
+      <xi:include href="xml/e-book-contacts-enums.xml"/>
+      <xi:include href="xml/e-book-contacts-utils.xml"/>
       <xi:include href="xml/e-destination.xml"/>
       <xi:include href="xml/e-address-western.xml"/>
       <xi:include href="xml/e-name-western.xml"/>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0e1a75036..98382fb63 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -7,7 +7,7 @@ src/addressbook/backends/file/e-book-backend-file-migrate-bdb.c
 src/addressbook/backends/google/e-book-backend-google.c
 src/addressbook/backends/google/e-book-google-utils.c
 src/addressbook/backends/ldap/e-book-backend-ldap.c
-src/addressbook/libebook-contacts/e-book-contacts-types.c
+src/addressbook/libebook-contacts/e-book-contacts-utils.c
 src/addressbook/libebook-contacts/e-contact.c
 src/addressbook/libebook-contacts/e-phone-number.c
 src/addressbook/libebook/e-book.c
diff --git a/src/addressbook/backends/carddav/e-book-backend-carddav.c 
b/src/addressbook/backends/carddav/e-book-backend-carddav.c
index cfd44e701..a41ed3b90 100644
--- a/src/addressbook/backends/carddav/e-book-backend-carddav.c
+++ b/src/addressbook/backends/carddav/e-book-backend-carddav.c
@@ -566,6 +566,7 @@ ebb_carddav_search_changes_cb (EBookCache *book_cache,
                               const gchar *revision,
                               const gchar *object,
                               const gchar *extra,
+                              guint32 custom_flags,
                               EOfflineState offline_state,
                               gpointer user_data)
 {
@@ -1064,6 +1065,7 @@ ebb_carddav_save_contact_sync (EBookMetaBackend *meta_backend,
                               EConflictResolution conflict_resolution,
                               /* const */ EContact *contact,
                               const gchar *extra,
+                              guint32 opflags,
                               gchar **out_new_uid,
                               gchar **out_new_extra,
                               GCancellable *cancellable,
@@ -1173,6 +1175,7 @@ ebb_carddav_remove_contact_sync (EBookMetaBackend *meta_backend,
                                 const gchar *uid,
                                 const gchar *extra,
                                 const gchar *object,
+                                guint32 opflags,
                                 GCancellable *cancellable,
                                 GError **error)
 {
diff --git a/src/addressbook/backends/file/e-book-backend-file.c 
b/src/addressbook/backends/file/e-book-backend-file.c
index 7467f2aaa..0a44e900a 100644
--- a/src/addressbook/backends/file/e-book-backend-file.c
+++ b/src/addressbook/backends/file/e-book-backend-file.c
@@ -698,7 +698,7 @@ e_book_backend_file_bump_revision (EBookBackendFile *bf,
                bf->priv->revision = new_revision;
 
                e_book_backend_notify_property_changed (E_BOOK_BACKEND (bf),
-                                                       BOOK_BACKEND_PROPERTY_REVISION,
+                                                       E_BOOK_BACKEND_PROPERTY_REVISION,
                                                        bf->priv->revision);
        } else {
                g_free (new_revision);
@@ -1096,10 +1096,10 @@ book_backend_file_get_backend_property (EBookBackend *backend,
        if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
                return g_strdup ("local,do-initial-query,bulk-adds,bulk-modifies,bulk-removes,contact-lists");
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                return g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                GString *fields;
                gint ii;
 
@@ -1115,7 +1115,7 @@ book_backend_file_get_backend_property (EBookBackend *backend,
 
                return g_string_free (fields, FALSE);
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REVISION)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REVISION)) {
                gchar *prop_value;
 
                g_rw_lock_reader_lock (&(bf->priv->lock));
@@ -1154,7 +1154,7 @@ book_backend_file_open_sync (EBookBackendSync *backend,
                e_book_backend_file_load_revision (bf);
                e_book_backend_notify_property_changed (
                        E_BOOK_BACKEND (backend),
-                       BOOK_BACKEND_PROPERTY_REVISION,
+                       E_BOOK_BACKEND_PROPERTY_REVISION,
                        bf->priv->revision);
        }
        g_rw_lock_writer_unlock (&(bf->priv->lock));
@@ -1167,10 +1167,11 @@ book_backend_file_open_sync (EBookBackendSync *backend,
 
 static gboolean
 book_backend_file_create_contacts_sync (EBookBackendSync *backend,
-                                        const gchar * const *vcards,
-                                        GSList **out_contacts,
-                                        GCancellable *cancellable,
-                                        GError **error)
+                                       const gchar * const *vcards,
+                                       guint32 opflags,
+                                       GSList **out_contacts,
+                                       GCancellable *cancellable,
+                                       GError **error)
 {
        EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
        gboolean success = FALSE;
@@ -1229,10 +1230,11 @@ book_backend_file_create_contacts_sync (EBookBackendSync *backend,
 
 static gboolean
 book_backend_file_modify_contacts_sync (EBookBackendSync *backend,
-                                        const gchar * const *vcards,
-                                        GSList **out_contacts,
-                                        GCancellable *cancellable,
-                                        GError **error)
+                                       const gchar * const *vcards,
+                                       guint32 opflags,
+                                       GSList **out_contacts,
+                                       GCancellable *cancellable,
+                                       GError **error)
 {
        EBookBackendFile *bf = E_BOOK_BACKEND_FILE (backend);
        GSList           *ids = NULL;
@@ -1425,6 +1427,7 @@ book_backend_file_modify_contacts_sync (EBookBackendSync *backend,
 static gboolean
 book_backend_file_remove_contacts_sync (EBookBackendSync *backend,
                                        const gchar * const *uids,
+                                       guint32 opflags,
                                        GSList **out_removed_uids,
                                        GCancellable *cancellable,
                                        GError **error)
diff --git a/src/addressbook/backends/google/e-book-backend-google.c 
b/src/addressbook/backends/google/e-book-backend-google.c
index 4d83428f6..e96a4ea77 100644
--- a/src/addressbook/backends/google/e-book-backend-google.c
+++ b/src/addressbook/backends/google/e-book-backend-google.c
@@ -935,6 +935,7 @@ ebb_google_save_contact_sync (EBookMetaBackend *meta_backend,
                              EConflictResolution conflict_resolution,
                              /* const */ EContact *contact,
                              const gchar *extra,
+                             guint32 opflags,
                              gchar **out_new_uid,
                              gchar **out_new_extra,
                              GCancellable *cancellable,
@@ -1104,6 +1105,7 @@ ebb_google_remove_contact_sync (EBookMetaBackend *meta_backend,
                                const gchar *uid,
                                const gchar *extra,
                                const gchar *object,
+                               guint32 opflags,
                                GCancellable *cancellable,
                                GError **error)
 {
@@ -1156,10 +1158,10 @@ ebb_google_get_backend_property (EBookBackend *book_backend,
                        e_book_meta_backend_get_capabilities (E_BOOK_META_BACKEND (book_backend)),
                        NULL);
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                return g_strdup ("");
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                return g_strjoin (",",
                        e_contact_field_name (E_CONTACT_UID),
                        e_contact_field_name (E_CONTACT_REV),
diff --git a/src/addressbook/backends/ldap/e-book-backend-ldap.c 
b/src/addressbook/backends/ldap/e-book-backend-ldap.c
index 067a4aed5..bbde5e799 100644
--- a/src/addressbook/backends/ldap/e-book-backend-ldap.c
+++ b/src/addressbook/backends/ldap/e-book-backend-ldap.c
@@ -618,7 +618,7 @@ check_schema_support (EBookBackendLDAP *bl)
        }
 
        lst = e_data_book_string_slist_to_comma_string (bl->priv->supported_fields);
-       e_book_backend_notify_property_changed (E_BOOK_BACKEND (bl), BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, 
lst);
+       e_book_backend_notify_property_changed (E_BOOK_BACKEND (bl), 
E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS, lst);
        g_free (lst);
 }
 
@@ -4907,7 +4907,7 @@ book_backend_ldap_get_backend_property (EBookBackend *backend,
                else
                        return g_strdup ("net,anon-access,contact-lists");
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                GSList *fields = NULL;
                gchar *prop_value;
 
@@ -4923,7 +4923,7 @@ book_backend_ldap_get_backend_property (EBookBackend *backend,
 
                return prop_value;
 
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
 
                return e_data_book_string_slist_to_comma_string (bl->priv->supported_fields);
@@ -5066,7 +5066,8 @@ book_backend_ldap_create_contacts (EBookBackend *backend,
                                   EDataBook *book,
                                   guint32 opid,
                                   GCancellable *cancellable,
-                                  const gchar * const *vcards)
+                                  const gchar * const *vcards,
+                                  guint32 opflags)
 {
        LDAPCreateOp *create_op;
        EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
@@ -5211,7 +5212,8 @@ book_backend_ldap_modify_contacts (EBookBackend *backend,
                                    EDataBook *book,
                                    guint32 opid,
                                    GCancellable *cancellable,
-                                   const gchar * const *vcards)
+                                   const gchar * const *vcards,
+                                  guint32 opflags)
 {
        LDAPModifyOp *modify_op;
        EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
@@ -5293,7 +5295,8 @@ book_backend_ldap_remove_contacts (EBookBackend *backend,
                                    EDataBook *book,
                                    guint32 opid,
                                    GCancellable *cancellable,
-                                   const gchar * const *uids)
+                                   const gchar * const *uids,
+                                  guint32 opflags)
 {
        LDAPRemoveOp *remove_op;
        EBookBackendLDAP *bl = E_BOOK_BACKEND_LDAP (backend);
diff --git a/src/addressbook/libebook-contacts/CMakeLists.txt 
b/src/addressbook/libebook-contacts/CMakeLists.txt
index e9e325973..02ca9d530 100644
--- a/src/addressbook/libebook-contacts/CMakeLists.txt
+++ b/src/addressbook/libebook-contacts/CMakeLists.txt
@@ -1,4 +1,4 @@
-glib_mkenums(e-book-contacts-enumtypes e-book-contacts-types.h E_BOOK_CONTACTS_ENUMTYPES_H)
+glib_mkenums(e-book-contacts-enumtypes e-book-contacts-enums.h E_BOOK_CONTACTS_ENUMTYPES_H)
 
 add_pkgconfig_file(libebook-contacts.pc.in libebook-contacts-${API_VERSION}.pc)
 
@@ -36,7 +36,7 @@ set(DEPENDENCIES
 
 set(SOURCES
        e-address-western.c
-       e-book-contacts-types.c
+       e-book-contacts-utils.c
        e-book-query.c
        e-contact.c
        e-name-western.c
@@ -51,7 +51,8 @@ set(SOURCES
 set(HEADERS
        libebook-contacts.h
        e-address-western.h
-       e-book-contacts-types.h
+       e-book-contacts-enums.h
+       e-book-contacts-utils.h
        e-book-query.h
        e-contact.h
        e-name-western.h
diff --git a/src/addressbook/libebook-contacts/e-book-contacts-enums.h 
b/src/addressbook/libebook-contacts/e-book-contacts-enums.h
new file mode 100644
index 000000000..06a3e18fc
--- /dev/null
+++ b/src/addressbook/libebook-contacts/e-book-contacts-enums.h
@@ -0,0 +1,148 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Nat Friedman (nat ximian com)
+ *          Tristan Van Berkom <tristanvb openismus com>
+ */
+
+#if !defined (__LIBEBOOK_CONTACTS_H_INSIDE__) && !defined (LIBEBOOK_CONTACTS_COMPILATION)
+#error "Only <libebook-contacts/libebook-contacts.h> should be included directly."
+#endif
+
+#ifndef E_BOOK_CONTACTS_ENUMS_H
+#define E_BOOK_CONTACTS_ENUMS_H
+
+G_BEGIN_DECLS
+
+/**
+ * EBookClientViewFlags:
+ * @E_BOOK_CLIENT_VIEW_FLAGS_NONE:
+ *   Symbolic value for no flags
+ * @E_BOOK_CLIENT_VIEW_FLAGS_NOTIFY_INITIAL:
+ *   If this flag is set then all contacts matching the view's query will
+ *   be sent as notifications when starting the view, otherwise only future
+ *   changes will be reported.  The default for a #EBookClientView is %TRUE.
+ *
+ * Flags that control the behaviour of an #EBookClientView.
+ *
+ * Since: 3.4
+ */
+typedef enum { /*< flags >*/
+       E_BOOK_CLIENT_VIEW_FLAGS_NONE = 0,
+       E_BOOK_CLIENT_VIEW_FLAGS_NOTIFY_INITIAL = (1 << 0),
+} EBookClientViewFlags;
+
+/**
+ * EBookIndexType:
+ * @E_BOOK_INDEX_PREFIX: An index suitable for searching contacts with a prefix pattern
+ * @E_BOOK_INDEX_SUFFIX: An index suitable for searching contacts with a suffix pattern
+ * @E_BOOK_INDEX_PHONE: An index suitable for searching contacts for phone numbers.
+ * <note><para>Phone numbers must be convertible into FQTN according to E.164 to be
+ * stored in this index. The number "+9999999" for instance won't be stored because
+ * the country calling code "+999" currently is not assigned.</para></note>
+ * @E_BOOK_INDEX_SORT_KEY: Indicates that a given #EContactField should be usable as a sort key.
+ *
+ * The type of index defined by e_source_backend_summary_setup_set_indexed_fields()
+ */
+typedef enum {
+       E_BOOK_INDEX_PREFIX = 0,
+       E_BOOK_INDEX_SUFFIX,
+       E_BOOK_INDEX_PHONE,
+       E_BOOK_INDEX_SORT_KEY
+} EBookIndexType;
+
+/**
+ * EBookCursorSortType:
+ * @E_BOOK_CURSOR_SORT_ASCENDING: Sort results in ascending order
+ * @E_BOOK_CURSOR_SORT_DESCENDING: Sort results in descending order
+ *
+ * Specifies the sort order of an ordered query
+ *
+ * Since: 3.12
+ */
+typedef enum {
+       E_BOOK_CURSOR_SORT_ASCENDING = 0,
+       E_BOOK_CURSOR_SORT_DESCENDING
+} EBookCursorSortType;
+
+/**
+ * EBookCursorOrigin:
+ * @E_BOOK_CURSOR_ORIGIN_CURRENT:  The current cursor position
+ * @E_BOOK_CURSOR_ORIGIN_BEGIN:    The beginning of the cursor results.
+ * @E_BOOK_CURSOR_ORIGIN_END:      The ending of the cursor results.
+ *
+ * Specifies the start position to in the list of traversed contacts
+ * in calls to e_book_client_cursor_step().
+ *
+ * When an #EBookClientCursor is created, the current position implied by %E_BOOK_CURSOR_ORIGIN_CURRENT
+ * is the same as %E_BOOK_CURSOR_ORIGIN_BEGIN.
+ *
+ * Since: 3.12
+ */
+typedef enum {
+       E_BOOK_CURSOR_ORIGIN_CURRENT,
+       E_BOOK_CURSOR_ORIGIN_BEGIN,
+       E_BOOK_CURSOR_ORIGIN_END
+} EBookCursorOrigin;
+
+/**
+ * EBookCursorStepFlags:
+ * @E_BOOK_CURSOR_STEP_MOVE:  The cursor position should be modified while stepping
+ * @E_BOOK_CURSOR_STEP_FETCH: Traversed contacts should be listed and returned while stepping.
+ *
+ * Defines the behaviour of e_book_client_cursor_step().
+ *
+ * Since: 3.12
+ */
+typedef enum { /*< flags >*/
+       E_BOOK_CURSOR_STEP_MOVE = (1 << 0),
+       E_BOOK_CURSOR_STEP_FETCH = (1 << 1)
+} EBookCursorStepFlags;
+
+/**
+ * EBookOperationFlags:
+ * @E_BOOK_OPERATION_FLAG_NONE: no operation flags defined
+ * @E_BOOK_OPERATION_FLAG_CONFLICT_FAIL: conflict resolution mode, to fail and do not
+ *    do any changes, when a conflict is detected
+ * @E_BOOK_OPERATION_FLAG_CONFLICT_USE_NEWER: conflict resolution mode, to use newer
+ *    of the local and the server side data, when a conflict is detected
+ * @E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_SERVER: conflict resolution mode, to use
+ *    the server data (and local changed), when a conflict is detected
+ * @E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL: conflict resolution mode, to use
+ *    local data (and always overwrite server data), when a conflict is detected
+ * @E_BOOK_OPERATION_FLAG_CONFLICT_WRITE_COPY: conflict resolution mode, to create
+ *    a copy of the data, when a conflict is detected
+ *
+ * Book operation flags, to specify behavior in certain situations. The conflict
+ * resolution mode flags cannot be combined together, where the @E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL
+ * is the default behavior (and it is used when no other conflict resolution flag is set).
+ * The flags can be ignored when the operation or the backend don't support it.
+ *
+ * Since: 3.36
+ **/
+typedef enum { /*< flags >*/
+       E_BOOK_OPERATION_FLAG_NONE                      = 0,
+       E_BOOK_OPERATION_FLAG_CONFLICT_FAIL             = (1 << 0),
+       E_BOOK_OPERATION_FLAG_CONFLICT_USE_NEWER        = (1 << 1),
+       E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_SERVER      = (1 << 2),
+       E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL       = 0,
+       E_BOOK_OPERATION_FLAG_CONFLICT_WRITE_COPY       = (1 << 3)
+} EBookOperationFlags;
+
+G_END_DECLS
+
+#endif /* E_BOOK_CONTACTS_ENUMS_H */
diff --git a/src/addressbook/libebook-contacts/e-book-contacts-utils.c 
b/src/addressbook/libebook-contacts/e-book-contacts-utils.c
new file mode 100644
index 000000000..fb03480f0
--- /dev/null
+++ b/src/addressbook/libebook-contacts/e-book-contacts-utils.c
@@ -0,0 +1,168 @@
+/*
+ * This library is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "libedataserver/libedataserver.h"
+
+#include "e-book-contacts-utils.h"
+
+G_DEFINE_QUARK (e-book-client-error-quark, e_book_client_error)
+
+/**
+ * e_book_client_error_to_string:
+ * @code: an #EBookClientError code
+ *
+ * Get localized human readable description of the given error code.
+ *
+ * Returns: Localized human readable description of the given error code
+ *
+ * Since: 3.2
+ **/
+const gchar *
+e_book_client_error_to_string (EBookClientError code)
+{
+       switch (code) {
+       case E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK:
+               return _("No such book");
+       case E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND:
+               return _("Contact not found");
+       case E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS:
+               return _("Contact ID already exists");
+       case E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE:
+               return _("No such source");
+       case E_BOOK_CLIENT_ERROR_NO_SPACE:
+               return _("No space");
+       }
+
+       return _("Unknown error");
+}
+
+/**
+ * e_book_client_error_create:
+ * @code: an #EBookClientError code to create
+ * @custom_msg: custom message to use for the error; can be %NULL
+ *
+ * Returns: a new #GError containing an E_BOOK_CLIENT_ERROR of the given
+ * @code. If the @custom_msg is NULL, then the error message is
+ * the one returned from e_book_client_error_to_string() for the @code,
+ * otherwise the given message is used.
+ *
+ * Returned pointer should be freed with g_error_free().
+ *
+ * Since: 3.2
+ **/
+GError *
+e_book_client_error_create (EBookClientError code,
+                            const gchar *custom_msg)
+{
+       return g_error_new_literal (E_BOOK_CLIENT_ERROR, code, custom_msg ? custom_msg : 
e_book_client_error_to_string (code));
+}
+
+/**
+ * e_book_client_error_create_fmt:
+ * @code: an #EBookClientError
+ * @format: (nullable): message format, or %NULL to use the default message for the @code
+ * @...: arguments for the format
+ *
+ * Similar as e_book_client_error_create(), only here, instead of custom_msg,
+ * is used a printf() format to create a custom message for the error.
+ *
+ * Returns: (transfer full): a newly allocated #GError, which should be
+ *   freed with g_error_free(), when no longer needed.
+ *   The #GError has set the custom message, or the default message for
+ *   @code, when @format is %NULL.
+ *
+ * Since: 3.36
+ **/
+GError *
+e_book_client_error_create_fmt (EBookClientError code,
+                               const gchar *format,
+                               ...)
+{
+       GError *error;
+       gchar *custom_msg;
+       va_list ap;
+
+       if (!format)
+               return e_book_client_error_create (code, NULL);
+
+       va_start (ap, format);
+       custom_msg = g_strdup_vprintf (format, ap);
+       va_end (ap);
+
+       error = e_book_client_error_create (code, custom_msg);
+
+       g_free (custom_msg);
+
+       return error;
+}
+
+/**
+ * e_book_util_operation_flags_to_conflict_resolution:
+ * @flags: bit-or of #EBookOperationFlags
+ *
+ * Decodes the #EConflictResolution from the bit-or of #EBookOperationFlags.
+ *
+ * Returns: an #EConflictResolution as stored in the @flags
+ *
+ * Since: 3.36
+ **/
+EConflictResolution
+e_book_util_operation_flags_to_conflict_resolution (guint32 flags)
+{
+       if ((flags & E_BOOK_OPERATION_FLAG_CONFLICT_FAIL) != 0)
+               return E_CONFLICT_RESOLUTION_FAIL;
+       else if ((flags & E_BOOK_OPERATION_FLAG_CONFLICT_USE_NEWER) != 0)
+               return E_CONFLICT_RESOLUTION_USE_NEWER;
+       else if ((flags & E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_SERVER) != 0)
+               return E_CONFLICT_RESOLUTION_KEEP_SERVER;
+       else if ((flags & E_BOOK_OPERATION_FLAG_CONFLICT_WRITE_COPY) != 0)
+               return E_CONFLICT_RESOLUTION_WRITE_COPY;
+
+       /* E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL is the default */
+       return E_CONFLICT_RESOLUTION_KEEP_LOCAL;
+}
+
+/**
+ * e_book_util_conflict_resolution_to_operation_flags:
+ * @conflict_resolution: an #EConflictResolution
+ *
+ * Encodes the #EConflictResolution into the bit-or of #EBookOperationFlags.
+ * The returned value can be bit-or-ed with other #EBookOperationFlags values.
+ *
+ * Returns: a bit-or of #EBookOperationFlags, corresponding to the @conflict_resolution
+ *
+ * Since: 3.36
+ **/
+guint32
+e_book_util_conflict_resolution_to_operation_flags (EConflictResolution conflict_resolution)
+{
+       switch (conflict_resolution) {
+       case E_CONFLICT_RESOLUTION_FAIL:
+               return E_BOOK_OPERATION_FLAG_CONFLICT_FAIL;
+       case E_CONFLICT_RESOLUTION_USE_NEWER:
+               return E_BOOK_OPERATION_FLAG_CONFLICT_USE_NEWER;
+       case E_CONFLICT_RESOLUTION_KEEP_SERVER:
+               return E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_SERVER;
+       case E_CONFLICT_RESOLUTION_KEEP_LOCAL:
+               return E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL;
+       case E_CONFLICT_RESOLUTION_WRITE_COPY:
+               return E_BOOK_OPERATION_FLAG_CONFLICT_WRITE_COPY;
+       }
+
+       return E_BOOK_OPERATION_FLAG_CONFLICT_KEEP_LOCAL;
+}
diff --git a/src/addressbook/libebook-contacts/e-book-contacts-types.h 
b/src/addressbook/libebook-contacts/e-book-contacts-utils.h
similarity index 69%
rename from src/addressbook/libebook-contacts/e-book-contacts-types.h
rename to src/addressbook/libebook-contacts/e-book-contacts-utils.h
index 55c12c8b2..bea903c0d 100644
--- a/src/addressbook/libebook-contacts/e-book-contacts-types.h
+++ b/src/addressbook/libebook-contacts/e-book-contacts-utils.h
@@ -23,13 +23,15 @@
 #error "Only <libebook-contacts/libebook-contacts.h> should be included directly."
 #endif
 
-#ifndef __E_BOOK_CONTACTS_TYPES_H__
-#define __E_BOOK_CONTACTS_TYPES_H__
+#ifndef E_BOOK_CONTACTS_UTILS_H
+#define E_BOOK_CONTACTS_UTILS_H
 
+#include <libedataserver/libedataserver.h>
+#include <libebook-contacts/e-book-contacts-enums.h>
 #include <libebook-contacts/e-contact.h>
 
 /**
- * BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS: (value "required-fields")
+ * E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS: (value "required-fields")
  *
  * Provides comma-separated list of required fields by the book backend.
  * All of these attributes should be set, otherwise the backend will reject
@@ -40,10 +42,10 @@
  *
  * Since: 3.2
  **/
-#define BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS          "required-fields"
+#define E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS                "required-fields"
 
 /**
- * BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS: (value "supported-fields")
+ * E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS: (value "supported-fields")
  *
  * Provides comma-separated list of supported fields by the book backend.
  * Attributes other than those listed here can be discarded. This can be
@@ -54,10 +56,10 @@
  *
  * Since: 3.2
  **/
-#define BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS         "supported-fields"
+#define E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS       "supported-fields"
 
 /**
- * BOOK_BACKEND_PROPERTY_REVISION: (value "revision")
+ * E_BOOK_BACKEND_PROPERTY_REVISION: (value "revision")
  *
  * The current overall revision string, this can be used as
  * a quick check to see if data has changed at all since the
@@ -65,7 +67,7 @@
  *
  * Since: 3.4
  **/
-#define BOOK_BACKEND_PROPERTY_REVISION                 "revision"
+#define E_BOOK_BACKEND_PROPERTY_REVISION               "revision"
 
 /**
  * E_BOOK_CLIENT_ERROR:
@@ -78,44 +80,6 @@
 
 G_BEGIN_DECLS
 
-/**
- * EBookClientViewFlags:
- * @E_BOOK_CLIENT_VIEW_FLAGS_NONE:
- *   Symbolic value for no flags
- * @E_BOOK_CLIENT_VIEW_FLAGS_NOTIFY_INITIAL:
- *   If this flag is set then all contacts matching the view's query will
- *   be sent as notifications when starting the view, otherwise only future
- *   changes will be reported.  The default for a #EBookClientView is %TRUE.
- *
- * Flags that control the behaviour of an #EBookClientView.
- *
- * Since: 3.4
- */
-typedef enum {
-       E_BOOK_CLIENT_VIEW_FLAGS_NONE = 0,
-       E_BOOK_CLIENT_VIEW_FLAGS_NOTIFY_INITIAL = (1 << 0),
-} EBookClientViewFlags;
-
-/**
- * EBookClientError:
- * @E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK: Requested book did not exist
- * @E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND: Contact referred to was not found
- * @E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS: Tried to add a contact which already exists
- * @E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE: Referred #ESource does not exist
- * @E_BOOK_CLIENT_ERROR_NO_SPACE: Out of disk space
- *
- * Error codes returned by #EBookClient APIs, if an #EClientError was not available.
- *
- * Since: 3.2
- **/
-typedef enum {
-       E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK,
-       E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND,
-       E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS,
-       E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE,
-       E_BOOK_CLIENT_ERROR_NO_SPACE
-} EBookClientError;
-
 /**
  * EDataBookStatus:
  * @E_DATA_BOOK_STATUS_SUCCESS: No error
@@ -180,74 +144,38 @@ typedef enum {
 } EDataBookStatus;
 
 /**
- * EBookIndexType:
- * @E_BOOK_INDEX_PREFIX: An index suitable for searching contacts with a prefix pattern
- * @E_BOOK_INDEX_SUFFIX: An index suitable for searching contacts with a suffix pattern
- * @E_BOOK_INDEX_PHONE: An index suitable for searching contacts for phone numbers.
- * <note><para>Phone numbers must be convertible into FQTN according to E.164 to be
- * stored in this index. The number "+9999999" for instance won't be stored because
- * the country calling code "+999" currently is not assigned.</para></note>
- * @E_BOOK_INDEX_SORT_KEY: Indicates that a given #EContactField should be usable as a sort key.
- *
- * The type of index defined by e_source_backend_summary_setup_set_indexed_fields()
- */
-typedef enum {
-       E_BOOK_INDEX_PREFIX = 0,
-       E_BOOK_INDEX_SUFFIX,
-       E_BOOK_INDEX_PHONE,
-       E_BOOK_INDEX_SORT_KEY
-} EBookIndexType;
-
-/**
- * EBookCursorSortType:
- * @E_BOOK_CURSOR_SORT_ASCENDING: Sort results in ascending order
- * @E_BOOK_CURSOR_SORT_DESCENDING: Sort results in descending order
- *
- * Specifies the sort order of an ordered query
- *
- * Since: 3.12
- */
-typedef enum {
-       E_BOOK_CURSOR_SORT_ASCENDING = 0,
-       E_BOOK_CURSOR_SORT_DESCENDING
-} EBookCursorSortType;
-
-/**
- * EBookCursorOrigin:
- * @E_BOOK_CURSOR_ORIGIN_CURRENT:  The current cursor position
- * @E_BOOK_CURSOR_ORIGIN_BEGIN:    The beginning of the cursor results.
- * @E_BOOK_CURSOR_ORIGIN_END:      The ending of the cursor results.
- *
- * Specifies the start position to in the list of traversed contacts
- * in calls to e_book_client_cursor_step().
- *
- * When an #EBookClientCursor is created, the current position implied by %E_BOOK_CURSOR_ORIGIN_CURRENT
- * is the same as %E_BOOK_CURSOR_ORIGIN_BEGIN.
- *
- * Since: 3.12
- */
-typedef enum {
-       E_BOOK_CURSOR_ORIGIN_CURRENT,
-       E_BOOK_CURSOR_ORIGIN_BEGIN,
-       E_BOOK_CURSOR_ORIGIN_END
-} EBookCursorOrigin;
-
-/**
- * EBookCursorStepFlags:
- * @E_BOOK_CURSOR_STEP_MOVE:  The cursor position should be modified while stepping
- * @E_BOOK_CURSOR_STEP_FETCH: Traversed contacts should be listed and returned while stepping.
+ * EBookClientError:
+ * @E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK: Requested book did not exist
+ * @E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND: Contact referred to was not found
+ * @E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS: Tried to add a contact which already exists
+ * @E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE: Referred #ESource does not exist
+ * @E_BOOK_CLIENT_ERROR_NO_SPACE: Out of disk space
  *
- * Defines the behaviour of e_book_client_cursor_step().
+ * Error codes returned by #EBookClient APIs, if an #EClientError was not available.
  *
- * Since: 3.12
- */
+ * Since: 3.2
+ **/
 typedef enum {
-       E_BOOK_CURSOR_STEP_MOVE = (1 << 0),
-       E_BOOK_CURSOR_STEP_FETCH = (1 << 1)
-} EBookCursorStepFlags;
+       E_BOOK_CLIENT_ERROR_NO_SUCH_BOOK,
+       E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND,
+       E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS,
+       E_BOOK_CLIENT_ERROR_NO_SUCH_SOURCE,
+       E_BOOK_CLIENT_ERROR_NO_SPACE
+} EBookClientError;
 
 GQuark         e_book_client_error_quark       (void) G_GNUC_CONST;
 const gchar *  e_book_client_error_to_string   (EBookClientError code);
+GError *       e_book_client_error_create      (EBookClientError code,
+                                                const gchar *custom_msg);
+GError *       e_book_client_error_create_fmt  (EBookClientError code,
+                                                const gchar *format,
+                                                ...) G_GNUC_PRINTF (2, 3);
+
+EConflictResolution
+               e_book_util_operation_flags_to_conflict_resolution
+                                               (guint32 flags); /* bit-or of EBookOperationFlags */
+guint32                e_book_util_conflict_resolution_to_operation_flags /* bit-or of EBookOperationFlags */
+                                               (EConflictResolution conflict_resolution);
 
 #ifndef EDS_DISABLE_DEPRECATED
 
@@ -303,10 +231,8 @@ typedef struct {
        EContact        *contact;
 } EBookChange;
 
-GError *       e_book_client_error_create      (EBookClientError code,
-                                                const gchar *custom_msg);
 #endif /* EDS_DISABLE_DEPRECATED */
 
 G_END_DECLS
 
-#endif /* __E_BOOK_CONTACTS_TYPES_H__ */
+#endif /* E_BOOK_CONTACTS_UTILS_H */
diff --git a/src/addressbook/libebook-contacts/e-source-backend-summary-setup.h 
b/src/addressbook/libebook-contacts/e-source-backend-summary-setup.h
index 0206859b7..c2192d966 100644
--- a/src/addressbook/libebook-contacts/e-source-backend-summary-setup.h
+++ b/src/addressbook/libebook-contacts/e-source-backend-summary-setup.h
@@ -28,7 +28,7 @@
 
 #include <libedataserver/libedataserver.h>
 #include <libebook-contacts/e-contact.h>
-#include <libebook-contacts/e-book-contacts-types.h>
+#include <libebook-contacts/e-book-contacts-enums.h>
 
 /* Standard GObject macros */
 #define E_TYPE_SOURCE_BACKEND_SUMMARY_SETUP \
diff --git a/src/addressbook/libebook-contacts/libebook-contacts.h 
b/src/addressbook/libebook-contacts/libebook-contacts.h
index 87c58eed2..04e1bdb5a 100644
--- a/src/addressbook/libebook-contacts/libebook-contacts.h
+++ b/src/addressbook/libebook-contacts/libebook-contacts.h
@@ -22,13 +22,14 @@
 
 #include <libedataserver/libedataserver.h>
 
-#include <libebook-contacts/e-book-contacts-types.h>
+#include <libebook-contacts/e-book-contacts-enums.h>
+#include <libebook-contacts/e-book-contacts-enumtypes.h>
+#include <libebook-contacts/e-book-contacts-utils.h>
 #include <libebook-contacts/e-book-query.h>
 #include <libebook-contacts/e-name-western.h>
 #include <libebook-contacts/e-address-western.h>
 #include <libebook-contacts/e-contact.h>
 #include <libebook-contacts/e-vcard.h>
-#include <libebook-contacts/e-book-contacts-enumtypes.h>
 #include <libebook-contacts/e-source-backend-summary-setup.h>
 #include <libebook-contacts/e-phone-number.h>
 
diff --git a/src/addressbook/libebook/e-book-client.c b/src/addressbook/libebook/e-book-client.c
index 2c0557c3c..fb58e7637 100644
--- a/src/addressbook/libebook/e-book-client.c
+++ b/src/addressbook/libebook/e-book-client.c
@@ -82,6 +82,7 @@ struct _AsyncContext {
        gchar *sexp;
        gchar *uid;
        GMainContext *context;
+       guint32 opflags;
 };
 
 struct _SignalClosure {
@@ -197,11 +198,11 @@ run_in_thread_closure_free (RunInThreadClosure *run_in_thread_closure)
 
 /*
  * Well-known book backend properties:
- * @BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS: Retrieves comma-separated list
+ * @E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS: Retrieves comma-separated list
  *   of required fields by the backend. Use e_client_util_parse_comma_strings()
  *   to parse returned string value into a #GSList. These fields are required
  *   to be filled in for all contacts.
- * @BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS: Retrieves comma-separated list
+ * @E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS: Retrieves comma-separated list
  *   of supported fields by the backend. Use e_client_util_parse_comma_strings()
  *   to parse returned string value into a #GSList. These fields can be
  *   stored for contacts.
@@ -561,7 +562,7 @@ book_client_dbus_proxy_property_changed (EClient *client,
        }
 
        if (g_str_equal (property_name, "required-fields")) {
-               backend_prop_name = BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
+               backend_prop_name = E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
        }
 
        if (g_str_equal (property_name, "revision")) {
@@ -569,7 +570,7 @@ book_client_dbus_proxy_property_changed (EClient *client,
        }
 
        if (g_str_equal (property_name, "supported-fields")) {
-               backend_prop_name = BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
+               backend_prop_name = E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
        }
 
        if (g_str_equal (property_name, "writable")) {
@@ -904,7 +905,7 @@ book_client_get_backend_property_sync (EClient *client,
                return TRUE;
        }
 
-       if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                strv = e_dbus_address_book_dup_required_fields (dbus_proxy);
                if (strv != NULL)
                        *prop_value = g_strjoinv (",", strv);
@@ -914,7 +915,7 @@ book_client_get_backend_property_sync (EClient *client,
                return TRUE;
        }
 
-       if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                strv = e_dbus_address_book_dup_supported_fields (dbus_proxy);
                if (strv != NULL)
                        *prop_value = g_strjoinv (",", strv);
@@ -2012,7 +2013,7 @@ e_book_client_get_self (ESourceRegistry *registry,
        uid = NULL;
        contact = make_me_card ();
        success = e_book_client_add_contact_sync (
-               book_client, contact, &uid, NULL, error);
+               book_client, contact, E_BOOK_OPERATION_FLAG_NONE, &uid, NULL, error);
        if (!success) {
                g_object_unref (book_client);
                g_object_unref (contact);
@@ -2120,6 +2121,7 @@ book_client_add_contact_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_add_contact_sync (
                E_BOOK_CLIENT (source_object),
                async_context->contact,
+               async_context->opflags,
                &async_context->uid,
                cancellable, &local_error)) {
 
@@ -2138,6 +2140,7 @@ book_client_add_contact_thread (GSimpleAsyncResult *simple,
  * e_book_client_add_contact:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2150,10 +2153,11 @@ book_client_add_contact_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_add_contact (EBookClient *client,
-                           EContact *contact,
-                           GCancellable *cancellable,
-                           GAsyncReadyCallback callback,
-                           gpointer user_data)
+                          EContact *contact,
+                          guint32 opflags,
+                          GCancellable *cancellable,
+                          GAsyncReadyCallback callback,
+                          gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2163,6 +2167,7 @@ e_book_client_add_contact (EBookClient *client,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->contact = g_object_ref (contact);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -2231,6 +2236,7 @@ e_book_client_add_contact_finish (EBookClient *client,
  * e_book_client_add_contact_sync:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @out_added_uid: (out): UID of a newly added contact; can be %NULL
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
@@ -2248,10 +2254,11 @@ e_book_client_add_contact_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_add_contact_sync (EBookClient *client,
-                                EContact *contact,
-                                gchar **out_added_uid,
-                                GCancellable *cancellable,
-                                GError **error)
+                               EContact *contact,
+                               guint32 opflags,
+                               gchar **out_added_uid,
+                               GCancellable *cancellable,
+                               GError **error)
 {
        GSList link = { contact, NULL };
        GSList *uids = NULL;
@@ -2261,7 +2268,7 @@ e_book_client_add_contact_sync (EBookClient *client,
        g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
 
        success = e_book_client_add_contacts_sync (
-               client, &link, &uids, cancellable, error);
+               client, &link, opflags, &uids, cancellable, error);
 
        /* Sanity check. */
        g_return_val_if_fail (
@@ -2292,6 +2299,7 @@ book_client_add_contacts_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_add_contacts_sync (
                E_BOOK_CLIENT (source_object),
                async_context->object_list,
+               async_context->opflags,
                &async_context->string_list,
                cancellable, &local_error)) {
 
@@ -2310,6 +2318,7 @@ book_client_add_contacts_thread (GSimpleAsyncResult *simple,
  * e_book_client_add_contacts:
  * @client: an #EBookClient
  * @contacts: (element-type EContact): a #GSList of #EContact objects to add
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2322,10 +2331,11 @@ book_client_add_contacts_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_add_contacts (EBookClient *client,
-                            GSList *contacts,
-                            GCancellable *cancellable,
-                            GAsyncReadyCallback callback,
-                            gpointer user_data)
+                           GSList *contacts,
+                           guint32 opflags,
+                           GCancellable *cancellable,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2336,6 +2346,7 @@ e_book_client_add_contacts (EBookClient *client,
        async_context = g_slice_new0 (AsyncContext);
        async_context->object_list = g_slist_copy_deep (
                contacts, (GCopyFunc) g_object_ref, NULL);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -2406,6 +2417,7 @@ e_book_client_add_contacts_finish (EBookClient *client,
  * e_book_client_add_contacts_sync:
  * @client: an #EBookClient
  * @contacts: (element-type EContact): a #GSList of #EContact objects to add
+ * @opflags: bit-or of #EBookOperationFlags
  * @out_added_uids: (out) (element-type utf8) (allow-none): UIDs of newly
  *                  added contacts; can be %NULL
  * @cancellable: a #GCancellable; can be %NULL
@@ -2427,10 +2439,11 @@ e_book_client_add_contacts_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_add_contacts_sync (EBookClient *client,
-                                 GSList *contacts,
-                                 GSList **out_added_uids,
-                                 GCancellable *cancellable,
-                                 GError **error)
+                                GSList *contacts,
+                                guint32 opflags,
+                                GSList **out_added_uids,
+                                GCancellable *cancellable,
+                                GError **error)
 {
        GSList *link;
        gchar **strv;
@@ -2455,7 +2468,7 @@ e_book_client_add_contacts_sync (EBookClient *client,
 
        e_dbus_address_book_call_create_contacts_sync (
                client->priv->dbus_proxy,
-               (const gchar * const *) strv,
+               (const gchar * const *) strv, opflags,
                &uids, cancellable, &local_error);
 
        g_strfreev (strv);
@@ -2506,6 +2519,7 @@ book_client_modify_contact_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_modify_contact_sync (
                E_BOOK_CLIENT (source_object),
                async_context->contact,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -2523,6 +2537,7 @@ book_client_modify_contact_thread (GSimpleAsyncResult *simple,
  * e_book_client_modify_contact:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2535,10 +2550,11 @@ book_client_modify_contact_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_modify_contact (EBookClient *client,
-                              EContact *contact,
-                              GCancellable *cancellable,
-                              GAsyncReadyCallback callback,
-                              gpointer user_data)
+                             EContact *contact,
+                             guint32 opflags,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2548,6 +2564,7 @@ e_book_client_modify_contact (EBookClient *client,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->contact = g_object_ref (contact);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -2599,6 +2616,7 @@ e_book_client_modify_contact_finish (EBookClient *client,
  * e_book_client_modify_contact_sync:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -2610,9 +2628,10 @@ e_book_client_modify_contact_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_modify_contact_sync (EBookClient *client,
-                                   EContact *contact,
-                                   GCancellable *cancellable,
-                                   GError **error)
+                                  EContact *contact,
+                                  guint32 opflags,
+                                  GCancellable *cancellable,
+                                  GError **error)
 {
        GSList link = { contact, NULL };
 
@@ -2620,7 +2639,7 @@ e_book_client_modify_contact_sync (EBookClient *client,
        g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
 
        return e_book_client_modify_contacts_sync (
-               client, &link, cancellable, error);
+               client, &link, opflags, cancellable, error);
 }
 
 /* Helper for e_book_client_modify_contacts() */
@@ -2637,6 +2656,7 @@ book_client_modify_contacts_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_modify_contacts_sync (
                E_BOOK_CLIENT (source_object),
                async_context->object_list,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -2654,6 +2674,7 @@ book_client_modify_contacts_thread (GSimpleAsyncResult *simple,
  * e_book_client_modify_contacts:
  * @client: an #EBookClient
  * @contacts: (element-type EContact): a #GSList of #EContact objects
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2666,10 +2687,11 @@ book_client_modify_contacts_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_modify_contacts (EBookClient *client,
-                               GSList *contacts,
-                               GCancellable *cancellable,
-                               GAsyncReadyCallback callback,
-                               gpointer user_data)
+                              GSList *contacts,
+                              guint32 opflags,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2680,6 +2702,7 @@ e_book_client_modify_contacts (EBookClient *client,
        async_context = g_slice_new0 (AsyncContext);
        async_context->object_list = g_slist_copy_deep (
                contacts, (GCopyFunc) g_object_ref, NULL);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -2731,6 +2754,7 @@ e_book_client_modify_contacts_finish (EBookClient *client,
  * e_book_client_modify_contacts_sync:
  * @client: an #EBookClient
  * @contacts: (element-type EContact): a #GSList of #EContact objects
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: (allow-none): a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -2742,9 +2766,10 @@ e_book_client_modify_contacts_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_modify_contacts_sync (EBookClient *client,
-                                    GSList *contacts,
-                                    GCancellable *cancellable,
-                                    GError **error)
+                                   GSList *contacts,
+                                   guint32 opflags,
+                                   GCancellable *cancellable,
+                                   GError **error)
 {
        GSList *link;
        gchar **strv;
@@ -2768,7 +2793,7 @@ e_book_client_modify_contacts_sync (EBookClient *client,
 
        e_dbus_address_book_call_modify_contacts_sync (
                client->priv->dbus_proxy,
-               (const gchar * const *) strv,
+               (const gchar * const *) strv, opflags,
                cancellable, &local_error);
 
        g_strfreev (strv);
@@ -2796,6 +2821,7 @@ book_client_remove_contact_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_remove_contact_sync (
                E_BOOK_CLIENT (source_object),
                async_context->contact,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -2813,6 +2839,7 @@ book_client_remove_contact_thread (GSimpleAsyncResult *simple,
  * e_book_client_remove_contact:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2825,10 +2852,11 @@ book_client_remove_contact_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_remove_contact (EBookClient *client,
-                              /* const */ EContact *contact,
-                              GCancellable *cancellable,
-                              GAsyncReadyCallback callback,
-                              gpointer user_data)
+                             /* const */ EContact *contact,
+                             guint32 opflags,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback callback,
+                             gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2838,6 +2866,7 @@ e_book_client_remove_contact (EBookClient *client,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->contact = g_object_ref (contact);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -2889,6 +2918,7 @@ e_book_client_remove_contact_finish (EBookClient *client,
  * e_book_client_remove_contact_sync:
  * @client: an #EBookClient
  * @contact: an #EContact
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -2900,9 +2930,10 @@ e_book_client_remove_contact_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_remove_contact_sync (EBookClient *client,
-                                   EContact *contact,
-                                   GCancellable *cancellable,
-                                   GError **error)
+                                  EContact *contact,
+                                  guint32 opflags,
+                                  GCancellable *cancellable,
+                                  GError **error)
 {
        const gchar *uid;
 
@@ -2913,7 +2944,7 @@ e_book_client_remove_contact_sync (EBookClient *client,
        g_return_val_if_fail (uid != NULL, FALSE);
 
        return e_book_client_remove_contact_by_uid_sync (
-               client, uid, cancellable, error);
+               client, uid, opflags, cancellable, error);
 }
 
 /* Helper for e_book_client_remove_contact_by_uid() */
@@ -2930,6 +2961,7 @@ book_client_remove_contact_by_uid_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_remove_contact_by_uid_sync (
                E_BOOK_CLIENT (source_object),
                async_context->uid,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -2947,6 +2979,7 @@ book_client_remove_contact_by_uid_thread (GSimpleAsyncResult *simple,
  * e_book_client_remove_contact_by_uid:
  * @client: an #EBookClient
  * @uid: a UID of a contact to remove
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -2959,10 +2992,11 @@ book_client_remove_contact_by_uid_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_remove_contact_by_uid (EBookClient *client,
-                                     const gchar *uid,
-                                     GCancellable *cancellable,
-                                     GAsyncReadyCallback callback,
-                                     gpointer user_data)
+                                    const gchar *uid,
+                                    guint32 opflags,
+                                    GCancellable *cancellable,
+                                    GAsyncReadyCallback callback,
+                                    gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -2972,6 +3006,7 @@ e_book_client_remove_contact_by_uid (EBookClient *client,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->uid = g_strdup (uid);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -3023,6 +3058,7 @@ e_book_client_remove_contact_by_uid_finish (EBookClient *client,
  * e_book_client_remove_contact_by_uid_sync:
  * @client: an #EBookClient
  * @uid: a UID of a contact to remove
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -3034,9 +3070,10 @@ e_book_client_remove_contact_by_uid_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_remove_contact_by_uid_sync (EBookClient *client,
-                                          const gchar *uid,
-                                          GCancellable *cancellable,
-                                          GError **error)
+                                         const gchar *uid,
+                                         guint32 opflags,
+                                         GCancellable *cancellable,
+                                         GError **error)
 {
        GSList link = { (gpointer) uid, NULL };
 
@@ -3044,7 +3081,7 @@ e_book_client_remove_contact_by_uid_sync (EBookClient *client,
        g_return_val_if_fail (uid != NULL, FALSE);
 
        return e_book_client_remove_contacts_sync (
-               client, &link, cancellable, error);
+               client, &link, opflags, cancellable, error);
 }
 
 /* Helper for e_book_client_remove_contacts() */
@@ -3061,6 +3098,7 @@ book_client_remove_contacts_thread (GSimpleAsyncResult *simple,
        if (!e_book_client_remove_contacts_sync (
                E_BOOK_CLIENT (source_object),
                async_context->string_list,
+               async_context->opflags,
                cancellable, &local_error)) {
 
                if (!local_error)
@@ -3078,6 +3116,7 @@ book_client_remove_contacts_thread (GSimpleAsyncResult *simple,
  * e_book_client_remove_contacts:
  * @client: an #EBookClient
  * @uids: (element-type utf8): a #GSList of UIDs to remove
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @callback: callback to call when a result is ready
  * @user_data: user data for the @callback
@@ -3093,10 +3132,11 @@ book_client_remove_contacts_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_client_remove_contacts (EBookClient *client,
-                               const GSList *uids,
-                               GCancellable *cancellable,
-                               GAsyncReadyCallback callback,
-                               gpointer user_data)
+                              const GSList *uids,
+                              guint32 opflags,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback,
+                              gpointer user_data)
 {
        GSimpleAsyncResult *simple;
        AsyncContext *async_context;
@@ -3107,6 +3147,7 @@ e_book_client_remove_contacts (EBookClient *client,
        async_context = g_slice_new0 (AsyncContext);
        async_context->string_list = g_slist_copy_deep (
                (GSList *) uids, (GCopyFunc) g_strdup, NULL);
+       async_context->opflags = opflags;
 
        simple = g_simple_async_result_new (
                G_OBJECT (client), callback, user_data,
@@ -3158,6 +3199,7 @@ e_book_client_remove_contacts_finish (EBookClient *client,
  * e_book_client_remove_contacts_sync:
  * @client: an #EBookClient
  * @uids: (element-type utf8): a #GSList of UIDs to remove
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: a #GCancellable; can be %NULL
  * @error: (out): a #GError to set an error, if any
  *
@@ -3172,9 +3214,10 @@ e_book_client_remove_contacts_finish (EBookClient *client,
  **/
 gboolean
 e_book_client_remove_contacts_sync (EBookClient *client,
-                                    const GSList *uids,
-                                    GCancellable *cancellable,
-                                    GError **error)
+                                   const GSList *uids,
+                                   guint32 opflags,
+                                   GCancellable *cancellable,
+                                   GError **error)
 {
        gchar **strv;
        gint ii = 0;
@@ -3191,7 +3234,7 @@ e_book_client_remove_contacts_sync (EBookClient *client,
 
        e_dbus_address_book_call_remove_contacts_sync (
                client->priv->dbus_proxy,
-               (const gchar * const *) strv,
+               (const gchar * const *) strv, opflags,
                cancellable, &local_error);
 
        g_strfreev (strv);
diff --git a/src/addressbook/libebook/e-book-client.h b/src/addressbook/libebook/e-book-client.h
index 683c07aaa..eca77f109 100644
--- a/src/addressbook/libebook/e-book-client.h
+++ b/src/addressbook/libebook/e-book-client.h
@@ -118,6 +118,7 @@ gboolean    e_book_client_set_self          (EBookClient *client,
 gboolean       e_book_client_is_self           (EContact *contact);
 void           e_book_client_add_contact       (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -128,11 +129,13 @@ gboolean  e_book_client_add_contact_finish
                                                 GError **error);
 gboolean       e_book_client_add_contact_sync  (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 gchar **out_added_uid,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_add_contacts      (EBookClient *client,
                                                 GSList *contacts,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -143,11 +146,13 @@ gboolean  e_book_client_add_contacts_finish
                                                 GError **error);
 gboolean       e_book_client_add_contacts_sync (EBookClient *client,
                                                 GSList *contacts,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GSList **out_added_uids,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_modify_contact    (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -158,10 +163,12 @@ gboolean  e_book_client_modify_contact_finish
 gboolean       e_book_client_modify_contact_sync
                                                (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_modify_contacts   (EBookClient *client,
                                                 GSList *contacts,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -172,10 +179,12 @@ gboolean  e_book_client_modify_contacts_finish
 gboolean       e_book_client_modify_contacts_sync
                                                (EBookClient *client,
                                                 GSList *contacts,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_remove_contact    (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -186,11 +195,13 @@ gboolean  e_book_client_remove_contact_finish
 gboolean       e_book_client_remove_contact_sync
                                                (EBookClient *client,
                                                 EContact *contact,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_remove_contact_by_uid
                                                (EBookClient *client,
                                                 const gchar *uid,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -201,10 +212,12 @@ gboolean  e_book_client_remove_contact_by_uid_finish
 gboolean       e_book_client_remove_contact_by_uid_sync
                                                (EBookClient *client,
                                                 const gchar *uid,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_remove_contacts   (EBookClient *client,
                                                 const GSList *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -215,6 +228,7 @@ gboolean    e_book_client_remove_contacts_finish
 gboolean       e_book_client_remove_contacts_sync
                                                (EBookClient *client,
                                                 const GSList *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_client_get_contact       (EBookClient *client,
@@ -300,14 +314,6 @@ gboolean   e_book_client_get_cursor_sync   (EBookClient *client,
 const gchar *  e_book_client_get_locale        (EBookClient *client);
 
 #ifndef EDS_DISABLE_DEPRECATED
-/**
- * BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS: (value "supported-auth-methods")
- *
- * Since: 3.2
- *
- * Deprecated: 3.8: The property is no longer supported.
- **/
-#define BOOK_BACKEND_PROPERTY_SUPPORTED_AUTH_METHODS   "supported-auth-methods"
 
 EBookClient *  e_book_client_new               (ESource *source,
                                                 GError **error);
diff --git a/src/addressbook/libebook/e-book.c b/src/addressbook/libebook/e-book.c
index 3396b57c0..fd7260d4b 100644
--- a/src/addressbook/libebook/e-book.c
+++ b/src/addressbook/libebook/e-book.c
@@ -46,10 +46,6 @@
        (G_TYPE_INSTANCE_GET_PRIVATE \
        ((obj), E_TYPE_BOOK, EBookPrivate))
 
-#define CLIENT_BACKEND_PROPERTY_CAPABILITIES           "capabilities"
-#define BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS          "required-fields"
-#define BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS         "supported-fields"
-
 struct _EBookPrivate {
        EBookClient *client;
        gulong backend_died_handler_id;
@@ -324,7 +320,7 @@ e_book_add_contact (EBook *book,
        g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
 
        success = e_book_client_add_contact_sync (
-               book->priv->client, contact, &added_uid, NULL, error);
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, &added_uid, NULL, error);
 
        if (added_uid != NULL) {
                e_contact_set (contact, E_CONTACT_UID, added_uid);
@@ -394,7 +390,7 @@ e_book_async_add_contact (EBook *book,
        data->closure = closure;
 
        e_book_client_add_contact (
-               book->priv->client, contact, NULL,
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL,
                add_contact_reply, data);
 
        return TRUE;
@@ -433,7 +429,7 @@ e_book_add_contact_async (EBook *book,
        data->closure = closure;
 
        e_book_client_add_contact (
-               book->priv->client, contact, NULL,
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL,
                add_contact_reply, data);
 
        return TRUE;
@@ -461,7 +457,7 @@ e_book_commit_contact (EBook *book,
        g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
 
        return e_book_client_modify_contact_sync (
-               book->priv->client, contact, NULL, error);
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, error);
 }
 
 static void
@@ -522,7 +518,7 @@ e_book_async_commit_contact (EBook *book,
        data->closure = closure;
 
        e_book_client_modify_contact (
-               book->priv->client, contact, NULL,
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL,
                modify_contacts_reply, data);
 
        return TRUE;
@@ -562,7 +558,7 @@ e_book_commit_contact_async (EBook *book,
        data->closure = closure;
 
        e_book_client_modify_contact (
-               book->priv->client, contact, NULL,
+               book->priv->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL,
                modify_contacts_reply, data);
 
        return TRUE;
@@ -583,7 +579,7 @@ e_book_commit_contact_async (EBook *book,
  * Returns: %TRUE if successful, %FALSE otherwise.
  *
  * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
- * an #EBookClient object with #BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
+ * an #EBookClient object with #E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
  **/
 gboolean
 e_book_get_required_fields (EBook *book,
@@ -600,7 +596,7 @@ e_book_get_required_fields (EBook *book,
 
        success = e_client_get_backend_property_sync (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
                &prop_value, NULL, error);
 
        if (success && fields != NULL) {
@@ -707,7 +703,7 @@ e_book_async_get_required_fields (EBook *book,
 
        e_client_get_backend_property (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
                NULL, get_required_fields_reply, data);
 
        return TRUE;
@@ -729,7 +725,7 @@ e_book_async_get_required_fields (EBook *book,
  * Deprecated: 3.2: Use e_client_get_backend_property() and
  *                  e_client_get_backend_property_finish() on an
  *                  #EBookClient object with
- *                  #BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
+ *                  #E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS instead.
  **/
 gboolean
 e_book_get_required_fields_async (EBook *book,
@@ -747,7 +743,7 @@ e_book_get_required_fields_async (EBook *book,
 
        e_client_get_backend_property (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS,
                NULL, get_required_fields_reply, data);
 
        return TRUE;
@@ -768,7 +764,7 @@ e_book_get_required_fields_async (EBook *book,
  * Returns: %TRUE if successful, %FALSE otherwise
  *
  * Deprecated: 3.2: Use e_client_get_backend_property_sync() on
- * an #EBookClient object with #BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
+ * an #EBookClient object with #E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
  **/
 gboolean
 e_book_get_supported_fields (EBook *book,
@@ -785,7 +781,7 @@ e_book_get_supported_fields (EBook *book,
 
        success = e_client_get_backend_property_sync (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
                &prop_value, NULL, error);
 
        if (success && fields != NULL) {
@@ -893,7 +889,7 @@ e_book_async_get_supported_fields (EBook *book,
 
        e_client_get_backend_property (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
                NULL, get_supported_fields_reply, data);
 
        return TRUE;
@@ -916,7 +912,7 @@ e_book_async_get_supported_fields (EBook *book,
  * Deprecated: 3.2: Use e_client_get_backend_property() and
  *                  e_client_get_backend_property_finish() on an
  *                  #EBookClient object with
- *                  #BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
+ *                  #E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS instead.
  **/
 gboolean
 e_book_get_supported_fields_async (EBook *book,
@@ -934,7 +930,7 @@ e_book_get_supported_fields_async (EBook *book,
 
        e_client_get_backend_property (
                E_CLIENT (book->priv->client),
-               BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
+               E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS,
                NULL, get_supported_fields_reply, data);
 
        return TRUE;
@@ -1193,7 +1189,7 @@ e_book_remove_contact (EBook *book,
        g_return_val_if_fail (id != NULL, FALSE);
 
        return e_book_client_remove_contact_by_uid_sync (
-               book->priv->client, id, NULL, error);
+               book->priv->client, id, E_BOOK_OPERATION_FLAG_NONE, NULL, error);
 }
 
 static void
@@ -1257,7 +1253,7 @@ e_book_remove_contacts (EBook *book,
        slist = g_slist_reverse (slist);
 
        success = e_book_client_remove_contacts_sync (
-               book->priv->client, slist, NULL, error);
+               book->priv->client, slist, E_BOOK_OPERATION_FLAG_NONE, NULL, error);
 
        g_slist_free (slist);
 
@@ -1295,7 +1291,8 @@ e_book_async_remove_contact (EBook *book,
 
        e_book_client_remove_contact (
                E_BOOK_CLIENT (book->priv->client),
-               contact, NULL, remove_contact_reply, data);
+               contact, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contact_reply, data);
 
        return TRUE;
 }
@@ -1334,7 +1331,8 @@ e_book_remove_contact_async (EBook *book,
 
        e_book_client_remove_contact (
                E_BOOK_CLIENT (book->priv->client),
-               contact, NULL, remove_contact_reply, data);
+               contact, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contact_reply, data);
 
        return TRUE;
 }
@@ -1397,7 +1395,8 @@ e_book_async_remove_contact_by_id (EBook *book,
 
        e_book_client_remove_contact_by_uid (
                E_BOOK_CLIENT (book->priv->client),
-               id, NULL, remove_contact_by_id_reply, data);
+               id, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contact_by_id_reply, data);
 
        return TRUE;
 }
@@ -1436,7 +1435,8 @@ e_book_remove_contact_by_id_async (EBook *book,
 
        e_book_client_remove_contact_by_uid (
                E_BOOK_CLIENT (book->priv->client),
-               id, NULL, remove_contact_by_id_reply, data);
+               id, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contact_by_id_reply, data);
 
        return TRUE;
 }
@@ -1509,7 +1509,8 @@ e_book_async_remove_contacts (EBook *book,
 
        e_book_client_remove_contacts (
                E_BOOK_CLIENT (book->priv->client),
-               slist, NULL, remove_contacts_reply, data);
+               slist, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contacts_reply, data);
 
        g_slist_free (slist);
 
@@ -1560,7 +1561,8 @@ e_book_remove_contacts_async (EBook *book,
 
        e_book_client_remove_contacts (
                E_BOOK_CLIENT (book->priv->client),
-               slist, NULL, remove_contacts_reply, data);
+               slist, E_BOOK_OPERATION_FLAG_NONE,
+               NULL, remove_contacts_reply, data);
 
        g_slist_free (slist);
 
diff --git a/src/addressbook/libedata-book/e-book-backend-sync.c 
b/src/addressbook/libedata-book/e-book-backend-sync.c
index 3f3140146..21f293b2e 100644
--- a/src/addressbook/libedata-book/e-book-backend-sync.c
+++ b/src/addressbook/libedata-book/e-book-backend-sync.c
@@ -82,7 +82,8 @@ book_backend_sync_create_contacts (EBookBackend *backend,
                                   EDataBook *book,
                                   guint32 opid,
                                   GCancellable *cancellable,
-                                  const gchar * const *vcards)
+                                  const gchar * const *vcards,
+                                  guint32 opflags)
 {
        GSList *contacts = NULL;
        GError *error = NULL;
@@ -90,7 +91,7 @@ book_backend_sync_create_contacts (EBookBackend *backend,
        g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
        g_return_if_fail (E_IS_DATA_BOOK (book));
 
-       e_book_backend_sync_create_contacts (E_BOOK_BACKEND_SYNC (backend), vcards, &contacts, cancellable, 
&error);
+       e_book_backend_sync_create_contacts (E_BOOK_BACKEND_SYNC (backend), vcards, opflags, &contacts, 
cancellable, &error);
 
        e_data_book_respond_create_contacts (book, opid, error, contacts);
 
@@ -102,7 +103,8 @@ book_backend_sync_modify_contacts (EBookBackend *backend,
                                   EDataBook *book,
                                   guint32 opid,
                                   GCancellable *cancellable,
-                                  const gchar * const *vcards)
+                                  const gchar * const *vcards,
+                                  guint32 opflags)
 {
        GSList *contacts = NULL;
        GError *error = NULL;
@@ -110,7 +112,7 @@ book_backend_sync_modify_contacts (EBookBackend *backend,
        g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
        g_return_if_fail (E_IS_DATA_BOOK (book));
 
-       e_book_backend_sync_modify_contacts (E_BOOK_BACKEND_SYNC (backend), vcards, &contacts, cancellable, 
&error);
+       e_book_backend_sync_modify_contacts (E_BOOK_BACKEND_SYNC (backend), vcards, opflags, &contacts, 
cancellable, &error);
 
        e_data_book_respond_modify_contacts (book, opid, error, contacts);
 
@@ -122,7 +124,8 @@ book_backend_sync_remove_contacts (EBookBackend *backend,
                                   EDataBook *book,
                                   guint32 opid,
                                   GCancellable *cancellable,
-                                  const gchar * const *uids)
+                                  const gchar * const *uids,
+                                  guint32 opflags)
 {
        GSList *removed_uids = NULL;
        GError *error = NULL;
@@ -130,7 +133,7 @@ book_backend_sync_remove_contacts (EBookBackend *backend,
        g_return_if_fail (E_IS_BOOK_BACKEND_SYNC (backend));
        g_return_if_fail (E_IS_DATA_BOOK (book));
 
-       e_book_backend_sync_remove_contacts (E_BOOK_BACKEND_SYNC (backend), uids, &removed_uids, cancellable, 
&error);
+       e_book_backend_sync_remove_contacts (E_BOOK_BACKEND_SYNC (backend), uids, opflags, &removed_uids, 
cancellable, &error);
 
        e_data_book_respond_remove_contacts (book, opid, error, removed_uids);
 
@@ -337,6 +340,7 @@ e_book_backend_sync_refresh (EBookBackendSync *backend,
  * e_book_backend_sync_create_contacts:
  * @backend: an #EBookBackendSync
  * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @out_contacts: (out) (element-type EContact): a #GSList in which to deposit results
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -356,6 +360,7 @@ e_book_backend_sync_refresh (EBookBackendSync *backend,
 gboolean
 e_book_backend_sync_create_contacts (EBookBackendSync *backend,
                                     const gchar * const *vcards,
+                                    guint32 opflags,
                                     GSList **out_contacts,
                                     GCancellable *cancellable,
                                     GError **error)
@@ -368,7 +373,7 @@ e_book_backend_sync_create_contacts (EBookBackendSync *backend,
        g_return_val_if_fail (klass != NULL, FALSE);
 
        if (klass->create_contacts_sync)
-               return klass->create_contacts_sync (backend, vcards, out_contacts, cancellable, error);
+               return klass->create_contacts_sync (backend, vcards, opflags, out_contacts, cancellable, 
error);
 
        g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
 
@@ -379,6 +384,7 @@ e_book_backend_sync_create_contacts (EBookBackendSync *backend,
  * e_book_backend_sync_modify_contacts:
  * @backend: an #EBookBackendSync
  * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @out_contacts: (out) (element-type EContact): a #GSList to deposit the modified contacts to
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -394,6 +400,7 @@ e_book_backend_sync_create_contacts (EBookBackendSync *backend,
 gboolean
 e_book_backend_sync_modify_contacts (EBookBackendSync *backend,
                                     const gchar * const *vcards,
+                                    guint32 opflags,
                                     GSList **out_contacts,
                                     GCancellable *cancellable,
                                     GError **error)
@@ -406,7 +413,7 @@ e_book_backend_sync_modify_contacts (EBookBackendSync *backend,
        g_return_val_if_fail (klass != NULL, FALSE);
 
        if (klass->modify_contacts_sync)
-               return klass->modify_contacts_sync (backend, vcards, out_contacts, cancellable, error);
+               return klass->modify_contacts_sync (backend, vcards, opflags, out_contacts, cancellable, 
error);
 
        g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
 
@@ -417,6 +424,7 @@ e_book_backend_sync_modify_contacts (EBookBackendSync *backend,
  * e_book_backend_sync_remove_contacts:
  * @backend: an #EBookBackendSync
  * @uids: a %NULL-terminated array of contact ID strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @out_removed_uids: (out) (element-type utf8): a #GSList of removed UIDs
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -432,6 +440,7 @@ e_book_backend_sync_modify_contacts (EBookBackendSync *backend,
 gboolean
 e_book_backend_sync_remove_contacts (EBookBackendSync *backend,
                                     const gchar * const *uids,
+                                    guint32 opflags,
                                     GSList **out_removed_uids,
                                     GCancellable *cancellable,
                                     GError **error)
@@ -444,7 +453,7 @@ e_book_backend_sync_remove_contacts (EBookBackendSync *backend,
        g_return_val_if_fail (klass != NULL, FALSE);
 
        if (klass->remove_contacts_sync)
-               return klass->remove_contacts_sync (backend, uids, out_removed_uids, cancellable, error);
+               return klass->remove_contacts_sync (backend, uids, opflags, out_removed_uids, cancellable, 
error);
 
        g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_NOT_SUPPORTED, NULL));
 
diff --git a/src/addressbook/libedata-book/e-book-backend-sync.h 
b/src/addressbook/libedata-book/e-book-backend-sync.h
index 5a7e89519..51176c8be 100644
--- a/src/addressbook/libedata-book/e-book-backend-sync.h
+++ b/src/addressbook/libedata-book/e-book-backend-sync.h
@@ -101,17 +101,20 @@ struct _EBookBackendSyncClass {
                                                 GError **error);
        gboolean        (*create_contacts_sync) (EBookBackendSync *backend,
                                                 const gchar * const *vcards,
-                                                GSList **out_contacts,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
+                                                GSList **out_contacts, /* EContact * */
                                                 GCancellable *cancellable,
                                                 GError **error);
        gboolean        (*modify_contacts_sync) (EBookBackendSync *backend,
                                                 const gchar * const *vcards,
-                                                GSList **out_contacts,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
+                                                GSList **out_contacts, /* EContact * */
                                                 GCancellable *cancellable,
                                                 GError **error);
        gboolean        (*remove_contacts_sync) (EBookBackendSync *backend,
                                                 const gchar * const *uids,
-                                                GSList **out_removed_uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
+                                                GSList **out_removed_uids, /* gchar * */
                                                 GCancellable *cancellable,
                                                 GError **error);
        EContact *      (*get_contact_sync)     (EBookBackendSync *backend,
@@ -151,18 +154,21 @@ gboolean  e_book_backend_sync_refresh     (EBookBackendSync *backend,
 gboolean       e_book_backend_sync_create_contacts
                                                (EBookBackendSync *backend,
                                                 const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GSList **out_contacts, /* EContact * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_book_backend_sync_modify_contacts
                                                (EBookBackendSync *backend,
                                                 const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GSList **out_contacts, /* EContact * */
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_book_backend_sync_remove_contacts
                                                (EBookBackendSync *backend,
                                                 const gchar * const *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GSList **out_removed_uids, /* gchar * */
                                                 GCancellable *cancellable,
                                                 GError **error);
diff --git a/src/addressbook/libedata-book/e-book-backend.c b/src/addressbook/libedata-book/e-book-backend.c
index a769afc70..41865c3e8 100644
--- a/src/addressbook/libedata-book/e-book-backend.c
+++ b/src/addressbook/libedata-book/e-book-backend.c
@@ -84,6 +84,8 @@ struct _AsyncContext {
         * so any leftover resources can be released. */
        GQueue *object_queue;
        GQueue *string_queue;
+
+       guint32 opflags; /* bit-or of EBookOperationFlags */
 };
 
 struct _DispatchNode {
@@ -1384,6 +1386,7 @@ e_book_backend_refresh_finish (EBookBackend *backend,
  * e_book_backend_create_contacts_sync:
  * @backend: an #EBookBackend
  * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @out_contacts: a #GQueue in which to deposit results
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -1402,10 +1405,11 @@ e_book_backend_refresh_finish (EBookBackend *backend,
  **/
 gboolean
 e_book_backend_create_contacts_sync (EBookBackend *backend,
-                                     const gchar * const *vcards,
-                                     GQueue *out_contacts,
-                                     GCancellable *cancellable,
-                                     GError **error)
+                                    const gchar * const *vcards,
+                                    guint32 opflags,
+                                    GQueue *out_contacts,
+                                    GCancellable *cancellable,
+                                    GError **error)
 {
        EAsyncClosure *closure;
        GAsyncResult *result;
@@ -1418,7 +1422,7 @@ e_book_backend_create_contacts_sync (EBookBackend *backend,
        closure = e_async_closure_new ();
 
        e_book_backend_create_contacts (
-               backend, vcards, cancellable,
+               backend, vcards, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -1463,7 +1467,7 @@ book_backend_create_contacts_thread (GSimpleAsyncResult *simple,
                opid = book_backend_stash_operation (backend, simple);
 
                class->create_contacts (
-                       backend, data_book, opid, cancellable, (const gchar * const *) async_context->strv);
+                       backend, data_book, opid, cancellable, (const gchar * const *) async_context->strv, 
async_context->opflags);
        }
 
        g_object_unref (data_book);
@@ -1473,6 +1477,7 @@ book_backend_create_contacts_thread (GSimpleAsyncResult *simple,
  * e_book_backend_create_contacts:
  * @backend: an #EBookBackend
  * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -1487,10 +1492,11 @@ book_backend_create_contacts_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_backend_create_contacts (EBookBackend *backend,
-                                const gchar * const *vcards,
-                                GCancellable *cancellable,
-                                GAsyncReadyCallback callback,
-                                gpointer user_data)
+                               const gchar * const *vcards,
+                               guint32 opflags,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
 {
        EBookBackendClass *class;
        GSimpleAsyncResult *simple;
@@ -1504,6 +1510,7 @@ e_book_backend_create_contacts (EBookBackend *backend,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->strv = g_strdupv ((gchar **) vcards);
+       async_context->opflags = opflags;
        async_context->object_queue = &async_context->result_queue;
 
        simple = g_simple_async_result_new (
@@ -1590,6 +1597,7 @@ e_book_backend_create_contacts_finish (EBookBackend *backend,
  * e_book_backend_modify_contacts_sync:
  * @backend: an #EBookBackend
  * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -1603,9 +1611,10 @@ e_book_backend_create_contacts_finish (EBookBackend *backend,
  **/
 gboolean
 e_book_backend_modify_contacts_sync (EBookBackend *backend,
-                                     const gchar * const *vcards,
-                                     GCancellable *cancellable,
-                                     GError **error)
+                                    const gchar * const *vcards,
+                                    guint32 opflags,
+                                    GCancellable *cancellable,
+                                    GError **error)
 {
        EAsyncClosure *closure;
        GAsyncResult *result;
@@ -1614,7 +1623,7 @@ e_book_backend_modify_contacts_sync (EBookBackend *backend,
        closure = e_async_closure_new ();
 
        e_book_backend_modify_contacts (
-               backend, vcards, cancellable,
+               backend, vcards, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -1659,7 +1668,7 @@ book_backend_modify_contacts_thread (GSimpleAsyncResult *simple,
                opid = book_backend_stash_operation (backend, simple);
 
                class->modify_contacts (
-                       backend, data_book, opid, cancellable, (const gchar * const *) async_context->strv);
+                       backend, data_book, opid, cancellable, (const gchar * const *) async_context->strv, 
async_context->opflags);
        }
 
        g_object_unref (data_book);
@@ -1669,6 +1678,7 @@ book_backend_modify_contacts_thread (GSimpleAsyncResult *simple,
  * e_book_backend_modify_contacts:
  * @backend: an #EBookBackend
  * @vcards: a %NULL-terminated array of vCard strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -1683,10 +1693,11 @@ book_backend_modify_contacts_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_backend_modify_contacts (EBookBackend *backend,
-                                const gchar * const *vcards,
-                                GCancellable *cancellable,
-                                GAsyncReadyCallback callback,
-                                gpointer user_data)
+                               const gchar * const *vcards,
+                               guint32 opflags,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
 {
        EBookBackendClass *class;
        GSimpleAsyncResult *simple;
@@ -1700,6 +1711,7 @@ e_book_backend_modify_contacts (EBookBackend *backend,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->strv = g_strdupv ((gchar **) vcards);
+       async_context->opflags = opflags;
        async_context->object_queue = &async_context->result_queue;
 
        simple = g_simple_async_result_new (
@@ -1777,6 +1789,7 @@ e_book_backend_modify_contacts_finish (EBookBackend *backend,
  * e_book_backend_remove_contacts_sync:
  * @backend: an #EBookBackend
  * @uids: a %NULL-terminated array of contact ID strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -1790,9 +1803,10 @@ e_book_backend_modify_contacts_finish (EBookBackend *backend,
  **/
 gboolean
 e_book_backend_remove_contacts_sync (EBookBackend *backend,
-                                     const gchar * const *uids,
-                                     GCancellable *cancellable,
-                                     GError **error)
+                                    const gchar * const *uids,
+                                    guint32 opflags,
+                                    GCancellable *cancellable,
+                                    GError **error)
 {
        EAsyncClosure *closure;
        GAsyncResult *result;
@@ -1804,7 +1818,7 @@ e_book_backend_remove_contacts_sync (EBookBackend *backend,
        closure = e_async_closure_new ();
 
        e_book_backend_remove_contacts (
-               backend, uids, cancellable,
+               backend, uids, opflags, cancellable,
                e_async_closure_callback, closure);
 
        result = e_async_closure_wait (closure);
@@ -1849,7 +1863,7 @@ book_backend_remove_contacts_thread (GSimpleAsyncResult *simple,
                opid = book_backend_stash_operation (backend, simple);
 
                class->remove_contacts (
-                       backend, data_book, opid, cancellable, (const gchar * const *) async_context->strv);
+                       backend, data_book, opid, cancellable, (const gchar * const *) async_context->strv, 
async_context->opflags);
        }
 
        g_object_unref (data_book);
@@ -1859,6 +1873,7 @@ book_backend_remove_contacts_thread (GSimpleAsyncResult *simple,
  * e_book_backend_remove_contacts:
  * @backend: an #EBookBackend
  * @uids: (array zero-terminated=1): a %NULL-terminated array of contact ID strings
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
  * @user_data: data to pass to the callback function
@@ -1873,10 +1888,11 @@ book_backend_remove_contacts_thread (GSimpleAsyncResult *simple,
  **/
 void
 e_book_backend_remove_contacts (EBookBackend *backend,
-                                const gchar * const *uids,
-                                GCancellable *cancellable,
-                                GAsyncReadyCallback callback,
-                                gpointer user_data)
+                               const gchar * const *uids,
+                               guint32 opflags,
+                               GCancellable *cancellable,
+                               GAsyncReadyCallback callback,
+                               gpointer user_data)
 {
        EBookBackendClass *class;
        GSimpleAsyncResult *simple;
@@ -1890,6 +1906,7 @@ e_book_backend_remove_contacts (EBookBackend *backend,
 
        async_context = g_slice_new0 (AsyncContext);
        async_context->strv = g_strdupv ((gchar **) uids);
+       async_context->opflags = opflags;
        async_context->string_queue = &async_context->result_queue;
 
        simple = g_simple_async_result_new (
diff --git a/src/addressbook/libedata-book/e-book-backend.h b/src/addressbook/libedata-book/e-book-backend.h
index 0e6d07ca7..22d0963df 100644
--- a/src/addressbook/libedata-book/e-book-backend.h
+++ b/src/addressbook/libedata-book/e-book-backend.h
@@ -134,17 +134,20 @@ struct _EBookBackendClass {
                                                 EDataBook *book,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const gchar * const *vcards);
+                                                const gchar * const *vcards,
+                                                guint32 opflags); /* bit-or of EBookOperationFlags */
        void            (*modify_contacts)      (EBookBackend *backend,
                                                 EDataBook *book,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const gchar * const *vcards);
+                                                const gchar * const *vcards,
+                                                guint32 opflags); /* bit-or of EBookOperationFlags */
        void            (*remove_contacts)      (EBookBackend *backend,
                                                 EDataBook *book,
                                                 guint32 opid,
                                                 GCancellable *cancellable,
-                                                const gchar * const *id_list);
+                                                const gchar * const *uids,
+                                                guint32 opflags); /* bit-or of EBookOperationFlags */
        void            (*get_contact)          (EBookBackend *backend,
                                                 EDataBook *book,
                                                 guint32 opid,
@@ -246,11 +249,13 @@ gboolean  e_book_backend_refresh_finish   (EBookBackend *backend,
 gboolean       e_book_backend_create_contacts_sync
                                                (EBookBackend *backend,
                                                 const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GQueue *out_contacts,
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_backend_create_contacts  (EBookBackend *backend,
                                                 const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -262,10 +267,12 @@ gboolean  e_book_backend_create_contacts_finish
 gboolean       e_book_backend_modify_contacts_sync
                                                (EBookBackend *backend,
                                                 const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_backend_modify_contacts  (EBookBackend *backend,
                                                 const gchar * const *vcards,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
@@ -276,10 +283,12 @@ gboolean  e_book_backend_modify_contacts_finish
 gboolean       e_book_backend_remove_contacts_sync
                                                (EBookBackend *backend,
                                                 const gchar * const *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 void           e_book_backend_remove_contacts  (EBookBackend *backend,
                                                 const gchar * const *uids,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GAsyncReadyCallback callback,
                                                 gpointer user_data);
diff --git a/src/addressbook/libedata-book/e-book-cache.c b/src/addressbook/libedata-book/e-book-cache.c
index 694146b20..b10beb08c 100644
--- a/src/addressbook/libedata-book/e-book-cache.c
+++ b/src/addressbook/libedata-book/e-book-cache.c
@@ -96,6 +96,7 @@
 #define INDEX_FLAG(type)  (1 << E_BOOK_INDEX_##type)
 
 #define EBC_COLUMN_EXTRA       "bdata"
+#define EBC_COLUMN_CUSTOM_FLAGS        "custom_flags"
 
 typedef struct {
        EContactField field_id;         /* The EContact field */
@@ -3063,11 +3064,15 @@ ebc_generate_select (EBookCache *book_cache,
                g_string_append (string, "summary." E_CACHE_COLUMN_REVISION ",");
                g_string_append (string, "summary." E_CACHE_COLUMN_OBJECT ",");
                g_string_append (string, "summary." E_CACHE_COLUMN_STATE ",");
-               g_string_append (string, "summary." EBC_COLUMN_EXTRA " ");
+               g_string_append (string, "summary." EBC_COLUMN_EXTRA ",");
+               g_string_append (string, "summary." EBC_COLUMN_CUSTOM_FLAGS " ");
                break;
        case SEARCH_UID_AND_REV:
                callback = ebc_search_meta_contacts_cb;
-               g_string_append (string, "summary." E_CACHE_COLUMN_UID ", summary." E_CACHE_COLUMN_REVISION 
", summary." EBC_COLUMN_EXTRA " ");
+               g_string_append (string, "summary." E_CACHE_COLUMN_UID ",");
+               g_string_append (string, "summary." E_CACHE_COLUMN_REVISION ",");
+               g_string_append (string, "summary." EBC_COLUMN_EXTRA ",");
+               g_string_append (string, "summary." EBC_COLUMN_CUSTOM_FLAGS " ");
                break;
        case SEARCH_UID:
                callback = ebc_search_uids_cb;
@@ -3252,6 +3257,7 @@ struct EBCSearchData {
        gint revision_index;
        gint object_index;
        gint extra_index;
+       gint custom_flags_index;
        gint state_index;
 
        EBookCacheInternalSearchFunc func;
@@ -3270,6 +3276,7 @@ ebc_search_select_cb (ECache *cache,
 {
        struct EBCSearchData *sd = user_data;
        const gchar *object = NULL, *extra = NULL;
+       guint32 custom_flags = 0;
        EOfflineState offline_state = E_OFFLINE_STATE_UNKNOWN;
 
        g_return_val_if_fail (sd != NULL, FALSE);
@@ -3280,6 +3287,7 @@ ebc_search_select_cb (ECache *cache,
            sd->revision_index == -1 ||
            sd->object_index == -1 ||
            sd->extra_index == -1 ||
+           sd->custom_flags_index == -1 ||
            sd->state_index == -1) {
                gint ii;
 
@@ -3287,6 +3295,7 @@ ebc_search_select_cb (ECache *cache,
                     sd->revision_index == -1 ||
                     sd->object_index == -1 ||
                     sd->extra_index == -1 ||
+                    sd->custom_flags_index == -1 ||
                     sd->state_index == -1); ii++) {
                        const gchar *cname = column_names[ii];
 
@@ -3304,6 +3313,8 @@ ebc_search_select_cb (ECache *cache,
                                sd->object_index = ii;
                        } else if (sd->extra_index == -1 && g_ascii_strcasecmp (cname, EBC_COLUMN_EXTRA) == 
0) {
                                sd->extra_index = ii;
+                       } else if (sd->custom_flags_index == -1 && g_ascii_strcasecmp (cname, 
EBC_COLUMN_CUSTOM_FLAGS) == 0) {
+                               sd->custom_flags_index = ii;
                        } else if (sd->state_index == -1 && g_ascii_strcasecmp (cname, E_CACHE_COLUMN_STATE) 
== 0) {
                                sd->state_index = ii;
                        }
@@ -3323,6 +3334,12 @@ ebc_search_select_cb (ECache *cache,
                extra = column_values[sd->extra_index];
        }
 
+       if (sd->custom_flags_index != -2) {
+               g_return_val_if_fail (sd->custom_flags_index >= 0 && sd->custom_flags_index < ncols, FALSE);
+               if (column_values[sd->custom_flags_index])
+                       custom_flags = g_ascii_strtoull (column_values[sd->custom_flags_index], NULL, 10);
+       }
+
        if (sd->state_index != -2) {
                g_return_val_if_fail (sd->extra_index >= 0 && sd->extra_index < ncols, FALSE);
 
@@ -3334,7 +3351,7 @@ ebc_search_select_cb (ECache *cache,
 
        if (sd->user_func) {
                return sd->user_func (E_BOOK_CACHE (cache), column_values[sd->uid_index], 
column_values[sd->revision_index],
-                       object, extra, offline_state, sd->user_func_user_data);
+                       object, extra, custom_flags, offline_state, sd->user_func_user_data);
        }
 
        sd->func (cache, column_values[sd->uid_index], column_values[sd->revision_index], object, extra, 
sd->out_value);
@@ -3394,6 +3411,7 @@ ebc_do_search_query (EBookCache *book_cache,
                sd.revision_index = -1;
                sd.object_index = search_type == SEARCH_FULL ? -1 : -2;
                sd.extra_index = search_type == SEARCH_UID ? -2 : -1;
+               sd.custom_flags_index = search_type == SEARCH_UID ? -2 : -1;
                sd.state_index = search_type == SEARCH_FULL ? -1 : -2;
                sd.out_value = out_value;
                sd.user_func = func;
@@ -4196,6 +4214,26 @@ e_book_cache_get_strings (ECache *cache,
        return TRUE;
 }
 
+static gboolean
+e_book_cache_get_uint64_cb (ECache *cache,
+                           gint ncols,
+                           const gchar **column_names,
+                           const gchar **column_values,
+                           gpointer user_data)
+{
+       guint64 *pui64 = user_data;
+
+       g_return_val_if_fail (pui64 != NULL, FALSE);
+
+       if (ncols == 1) {
+               *pui64 = column_values[0] ? g_ascii_strtoull (column_values[0], NULL, 10) : 0;
+       } else {
+               *pui64 = 0;
+       }
+
+       return TRUE;
+}
+
 static gboolean
 e_book_cache_get_old_contacts_cb (ECache *cache,
                                  gint ncols,
@@ -4298,7 +4336,7 @@ e_book_cache_migrate (ECache *cache,
                                if (!contact)
                                        continue;
 
-                               success = e_book_cache_put_contact (book_cache, contact, data->extra, 
E_CACHE_IS_ONLINE, cancellable, error);
+                               success = e_book_cache_put_contact (book_cache, contact, data->extra, 0, 
E_CACHE_IS_ONLINE, cancellable, error);
                        }
                }
 
@@ -4366,6 +4404,7 @@ e_book_cache_populate_other_columns (EBookCache *book_cache,
                } G_STMT_END
 
        add_column (EBC_COLUMN_EXTRA, "TEXT", NULL);
+       add_column (EBC_COLUMN_CUSTOM_FLAGS, "INTEGER", NULL);
 
        use_default = !setup;
 
@@ -4796,7 +4835,8 @@ e_book_cache_ref_collator (EBookCache *book_cache)
  * e_book_cache_put_contact:
  * @book_cache: An #EBookCache
  * @contact: an #EContact to be added
- * @extra: extra data to store in association with this contact
+ * @extra: (nullable): extra data to store in association with this @contact
+ * @custom_flags: custom flags for the @contact, not interpreted by the @book_cache
  * @offline_flag: one of #ECacheOfflineFlag, whether putting this contact in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -4812,11 +4852,12 @@ gboolean
 e_book_cache_put_contact (EBookCache *book_cache,
                          EContact *contact,
                          const gchar *extra,
+                         guint32 custom_flags,
                          ECacheOfflineFlag offline_flag,
                          GCancellable *cancellable,
                          GError **error)
 {
-       GSList *contacts, *extras;
+       GSList *contacts, *extras, *custom_flags_lst;
        gboolean success;
 
        g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
@@ -4824,9 +4865,11 @@ e_book_cache_put_contact (EBookCache *book_cache,
 
        contacts = g_slist_append (NULL, contact);
        extras = g_slist_append (NULL, (gpointer) extra);
+       custom_flags_lst = g_slist_append (NULL, GUINT_TO_POINTER (custom_flags));
 
-       success = e_book_cache_put_contacts (book_cache, contacts, extras, offline_flag, cancellable, error);
+       success = e_book_cache_put_contacts (book_cache, contacts, extras, custom_flags_lst, offline_flag, 
cancellable, error);
 
+       g_slist_free (custom_flags_lst);
        g_slist_free (contacts);
        g_slist_free (extras);
 
@@ -4838,15 +4881,17 @@ e_book_cache_put_contact (EBookCache *book_cache,
  * @book_cache: An #EBookCache
  * @contacts: (element-type EContact): A list of contacts to add to @book_cache
  * @extras: (nullable) (element-type utf8): A list of extra data to store in association with the @contacts
+ * @custom_flags: (nullable) (element-type guint32): optional custom flags to use for the @contacts
  * @offline_flag: one of #ECacheOfflineFlag, whether putting these contacts in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Adds or replaces contacts in @book_cache.
  *
- * If @extras is specified, it must have an equal length as the @contacts list. Each element
- * from the @extras list will be stored in association with its corresponding contact
- * in the @contacts list.
+ * If @extras is specified, it must have an equal length as the @contacts list.
+ * Similarly the non-NULL @custom_flags length should be the same as the length of the @contacts.
+ * Each element from the @extras list and @custom_flags list will be stored in association
+ * with its corresponding contact in the @contacts list.
  *
  * Returns: %TRUE on success, otherwise %FALSE is returned and @error is set appropriately.
  *
@@ -4856,11 +4901,12 @@ gboolean
 e_book_cache_put_contacts (EBookCache *book_cache,
                           const GSList *contacts,
                           const GSList *extras,
+                          const GSList *custom_flags,
                           ECacheOfflineFlag offline_flag,
                           GCancellable *cancellable,
                           GError **error)
 {
-       const GSList *clink, *elink;
+       const GSList *clink, *elink, *flink;
        ECache *cache;
        ECacheColumnValues *other_columns;
        gboolean success;
@@ -4868,6 +4914,7 @@ e_book_cache_put_contacts (EBookCache *book_cache,
        g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
        g_return_val_if_fail (contacts != NULL, FALSE);
        g_return_val_if_fail (extras == NULL || g_slist_length ((GSList *) extras) == g_slist_length ((GSList 
*) contacts), FALSE);
+       g_return_val_if_fail (custom_flags == NULL || g_slist_length ((GSList *) contacts) == g_slist_length 
((GSList *) custom_flags), FALSE);
 
        cache = E_CACHE (book_cache);
        other_columns = e_cache_column_values_new ();
@@ -4875,9 +4922,12 @@ e_book_cache_put_contacts (EBookCache *book_cache,
        e_cache_lock (cache, E_CACHE_LOCK_WRITE);
        e_cache_freeze_revision_change (cache);
 
-       for (clink = contacts, elink = extras; clink; clink = g_slist_next (clink), elink = g_slist_next 
(elink)) {
+       for (clink = contacts, elink = extras, flink = custom_flags;
+            clink;
+            (clink = g_slist_next (clink)), (elink = g_slist_next (elink)), (flink = g_slist_next (flink))) {
                EContact *contact = clink->data;
                const gchar *extra = elink ? elink->data : NULL;
+               guint32 custom_flags_val = flink ? GPOINTER_TO_UINT (flink->data) : 0;
                gchar *uid, *rev, *vcard;
 
                g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
@@ -4889,6 +4939,7 @@ e_book_cache_put_contacts (EBookCache *book_cache,
 
                if (extra)
                        e_cache_column_values_take_value (other_columns, EBC_COLUMN_EXTRA, g_strdup (extra));
+               e_cache_column_values_take_value (other_columns, EBC_COLUMN_CUSTOM_FLAGS, g_strdup_printf 
("%u", custom_flags_val));
 
                uid = e_contact_get (contact, E_CONTACT_UID);
                rev = e_book_cache_dup_contact_revision (book_cache, contact);
@@ -4917,6 +4968,7 @@ e_book_cache_put_contacts (EBookCache *book_cache,
  * e_book_cache_remove_contact:
  * @book_cache: An #EBookCache
  * @uid: the uid of the contact to remove
+ * @custom_flags: custom flags for the contact with the given @uid, not interpreted by the @book_cache
  * @offline_flag: one of #ECacheOfflineFlag, whether removing this contact in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
@@ -4930,20 +4982,23 @@ e_book_cache_put_contacts (EBookCache *book_cache,
 gboolean
 e_book_cache_remove_contact (EBookCache *book_cache,
                             const gchar *uid,
+                            guint32 custom_flags,
                             ECacheOfflineFlag offline_flag,
                             GCancellable *cancellable,
                             GError **error)
 {
-       GSList *uids;
+       GSList *uids, *custom_flags_lst;
        gboolean success;
 
        g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
        g_return_val_if_fail (uid != NULL, FALSE);
 
        uids = g_slist_append (NULL, (gpointer) uid);
+       custom_flags_lst = g_slist_append (NULL, GUINT_TO_POINTER (custom_flags));
 
-       success = e_book_cache_remove_contacts (book_cache, uids, offline_flag, cancellable, error);
+       success = e_book_cache_remove_contacts (book_cache, uids, custom_flags_lst, offline_flag, 
cancellable, error);
 
+       g_slist_free (custom_flags_lst);
        g_slist_free (uids);
 
        return success;
@@ -4953,11 +5008,15 @@ e_book_cache_remove_contact (EBookCache *book_cache,
  * e_book_cache_remove_contacts:
  * @book_cache: An #EBookCache
  * @uids: (element-type utf8): a #GSList of uids indicating which contacts to remove
+ * @custom_flags: (element-type guint32) (nullable): an optional #GSList of custom flags for the @ids
  * @offline_flag: one of #ECacheOfflineFlag, whether removing these contacts in offline
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
  * Removes the contacts indicated by @uids from @book_cache.
+ * The @custom_flags is used, if not %NULL, only if the @offline_flag
+ * is %E_CACHE_IS_OFFLINE. Otherwise it's ignored. The length of
+ * the @custom_flags should match the length of @uids, when not %NULL.
  *
  * Returns: %TRUE on success, otherwise %FALSE is returned and @error is set appropriately.
  *
@@ -4966,24 +5025,34 @@ e_book_cache_remove_contact (EBookCache *book_cache,
 gboolean
 e_book_cache_remove_contacts (EBookCache *book_cache,
                              const GSList *uids,
+                             const GSList *custom_flags,
                              ECacheOfflineFlag offline_flag,
                              GCancellable *cancellable,
                              GError **error)
 {
        ECache *cache;
-       const GSList *link;
+       const GSList *link, *flink;
        gboolean success = TRUE;
 
        g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
        g_return_val_if_fail (uids != NULL, FALSE);
+       g_return_val_if_fail (custom_flags == NULL || g_slist_length ((GSList *) uids) == g_slist_length 
((GSList *) custom_flags), FALSE);
 
        cache = E_CACHE (book_cache);
 
        e_cache_lock (cache, E_CACHE_LOCK_WRITE);
        e_cache_freeze_revision_change (cache);
 
-       for (link = uids; success && link; link = g_slist_next (link)) {
+       for (link = uids, flink = custom_flags; success && link; (link = g_slist_next (link)), (flink = 
g_slist_next (flink))) {
                const gchar *uid = link->data;
+               guint32 custom_flags_val = flink ? GPOINTER_TO_UINT (flink->data) : 0;
+
+               if (offline_flag == E_CACHE_IS_OFFLINE && flink) {
+                       success = e_book_cache_set_contact_custom_flags (book_cache, uid, custom_flags_val, 
cancellable, error);
+
+                       if (!success)
+                               break;
+               }
 
                success = e_cache_remove (cache, uid, offline_flag, cancellable, error);
        }
@@ -5103,6 +5172,101 @@ e_book_cache_get_vcard (EBookCache *book_cache,
        return TRUE;
 }
 
+/**
+ * e_book_cache_set_contact_custom_flags:
+ * @book_cache: an #EBookCache
+ * @uid: The uid of the contact to set the extra data for
+ * @custom_flags: the custom flags to set for the contact
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Sets or replaces the custom flags associated with a contact
+ * identified by the @uid.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_cache_set_contact_custom_flags (EBookCache *book_cache,
+                                      const gchar *uid,
+                                      guint32 custom_flags,
+                                      GCancellable *cancellable,
+                                      GError **error)
+{
+       gchar *stmt;
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
+       g_return_val_if_fail (uid != NULL, FALSE);
+
+       if (!e_cache_contains (E_CACHE (book_cache), uid, E_CACHE_INCLUDE_DELETED)) {
+               g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Object “%s” not found"), uid);
+               return FALSE;
+       }
+
+       stmt = e_cache_sqlite_stmt_printf (
+               "UPDATE " E_CACHE_TABLE_OBJECTS " SET " EBC_COLUMN_CUSTOM_FLAGS "=%u"
+               " WHERE " E_CACHE_COLUMN_UID "=%Q",
+               custom_flags, uid);
+
+       success = e_cache_sqlite_exec (E_CACHE (book_cache), stmt, cancellable, error);
+
+       e_cache_sqlite_stmt_free (stmt);
+
+       return success;
+}
+
+/**
+ * e_book_cache_get_contact_custom_flags:
+ * @book_cache: an #EBookCache
+ * @uid: The uid of the contact to set the extra data for
+ * @out_custom_flags: (out): return location to store the custom flags
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets the custom flags previously set for the @uid, either with
+ * e_book_cache_set_contact_custom_flags(), when adding contacts or
+ * when removing contacts in offline.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.36
+ **/
+gboolean
+e_book_cache_get_contact_custom_flags (EBookCache *book_cache,
+                                      const gchar *uid,
+                                      guint32 *out_custom_flags,
+                                      GCancellable *cancellable,
+                                      GError **error)
+{
+       gchar *stmt;
+       guint64 value = 0;
+       gboolean success;
+
+       g_return_val_if_fail (E_IS_BOOK_CACHE (book_cache), FALSE);
+       g_return_val_if_fail (uid != NULL, FALSE);
+
+       if (!e_cache_contains (E_CACHE (book_cache), uid, E_CACHE_INCLUDE_DELETED)) {
+               g_set_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND, _("Object “%s” not found"), uid);
+               return FALSE;
+       }
+
+       stmt = e_cache_sqlite_stmt_printf (
+               "SELECT " EBC_COLUMN_CUSTOM_FLAGS " FROM " E_CACHE_TABLE_OBJECTS
+               " WHERE " E_CACHE_COLUMN_UID "=%Q",
+               uid);
+
+       success = e_cache_sqlite_select (E_CACHE (book_cache), stmt, e_book_cache_get_uint64_cb, &value, 
cancellable, error);
+
+       e_cache_sqlite_stmt_free (stmt);
+
+       if (out_custom_flags)
+               *out_custom_flags = (guint32) value;
+
+       return success;
+}
+
 /**
  * e_book_cache_set_contact_extra:
  * @book_cache: An #EBookCache
diff --git a/src/addressbook/libedata-book/e-book-cache.h b/src/addressbook/libedata-book/e-book-cache.h
index 1422437ab..37d060a12 100644
--- a/src/addressbook/libedata-book/e-book-cache.h
+++ b/src/addressbook/libedata-book/e-book-cache.h
@@ -95,7 +95,8 @@ void          e_book_cache_search_data_free   (/* EBookCacheSearchData * */ gpointer data)
  * @revision: the object revision
  * @object: the object itself
  * @extra: extra data stored with the object
- * @offline_state: objects offline state, one of #EOfflineState
+ * @custom_flags: object's custom flags
+ * @offline_state: object's offline state, one of #EOfflineState
  * @user_data: user data, as used in e_book_cache_search_with_callback()
  *
  * A callback called for each object row when using
@@ -110,6 +111,7 @@ typedef gboolean (* EBookCacheSearchFunc)   (EBookCache *book_cache,
                                                 const gchar *revision,
                                                 const gchar *object,
                                                 const gchar *extra,
+                                                guint32 custom_flags,
                                                 EOfflineState offline_state,
                                                 gpointer user_data);
 
@@ -221,22 +223,26 @@ ECollator *       e_book_cache_ref_collator       (EBookCache *book_cache);
 gboolean       e_book_cache_put_contact        (EBookCache *book_cache,
                                                 EContact *contact,
                                                 const gchar *extra,
+                                                guint32 custom_flags,
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_book_cache_put_contacts       (EBookCache *book_cache,
-                                                const GSList *contacts,
-                                                const GSList *extras,
+                                                const GSList *contacts, /* EContact * */
+                                                const GSList *extras, /* gchar * */
+                                                const GSList *custom_flags, /* guint32, through 
GUINT_TO_POINTER() */
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_book_cache_remove_contact     (EBookCache *book_cache,
                                                 const gchar *uid,
+                                                guint32 custom_flags,
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_book_cache_remove_contacts    (EBookCache *book_cache,
-                                                const GSList *uids,
+                                                const GSList *uids, /* gchar * */
+                                                const GSList *custom_flags, /* guint32, through 
GUINT_TO_POINTER() */
                                                 ECacheOfflineFlag offline_flag,
                                                 GCancellable *cancellable,
                                                 GError **error);
@@ -252,6 +258,18 @@ gboolean   e_book_cache_get_vcard          (EBookCache *book_cache,
                                                 gchar **out_vcard,
                                                 GCancellable *cancellable,
                                                 GError **error);
+gboolean       e_book_cache_set_contact_custom_flags
+                                               (EBookCache *book_cache,
+                                                const gchar *uid,
+                                                guint32 custom_flags,
+                                                GCancellable *cancellable,
+                                                GError **error);
+gboolean       e_book_cache_get_contact_custom_flags
+                                               (EBookCache *book_cache,
+                                                const gchar *uid,
+                                                guint32 *out_custom_flags,
+                                                GCancellable *cancellable,
+                                                GError **error);
 gboolean       e_book_cache_set_contact_extra  (EBookCache *book_cache,
                                                 const gchar *uid,
                                                 const gchar *extra,
diff --git a/src/addressbook/libedata-book/e-book-meta-backend.c 
b/src/addressbook/libedata-book/e-book-meta-backend.c
index f1e430d94..ffb1eafe3 100644
--- a/src/addressbook/libedata-book/e-book-meta-backend.c
+++ b/src/addressbook/libedata-book/e-book-meta-backend.c
@@ -119,6 +119,7 @@ static gboolean ebmb_save_contact_wrapper_sync (EBookMetaBackend *meta_backend,
                                                EConflictResolution conflict_resolution,
                                                /* const */ EContact *in_contact,
                                                const gchar *extra,
+                                               guint32 opflags,
                                                const gchar *orig_uid,
                                                gboolean *out_requires_put,
                                                gchar **out_new_uid,
@@ -295,6 +296,7 @@ ebmb_gather_locally_cached_objects_cb (EBookCache *book_cache,
                                       const gchar *revision,
                                       const gchar *object,
                                       const gchar *extra,
+                                      guint32 custom_flags,
                                       EOfflineState offline_state,
                                       gpointer user_data)
 {
@@ -627,6 +629,7 @@ ebmb_upload_local_changes_sync (EBookMetaBackend *meta_backend,
        for (link = offline_changes; link && success; link = g_slist_next (link)) {
                ECacheOfflineChange *change = link->data;
                gchar *extra = NULL;
+               guint32 opflags = 0;
 
                success = !g_cancellable_set_error_if_cancelled (cancellable, error);
                if (!success)
@@ -640,6 +643,9 @@ ebmb_upload_local_changes_sync (EBookMetaBackend *meta_backend,
                if (!e_book_cache_get_contact_extra (book_cache, change->uid, &extra, cancellable, NULL))
                        extra = NULL;
 
+               if (!e_book_cache_get_contact_custom_flags (book_cache, change->uid, &opflags, cancellable, 
NULL))
+                       opflags = 0;
+
                if (change->state == E_OFFLINE_STATE_LOCALLY_CREATED ||
                    change->state == E_OFFLINE_STATE_LOCALLY_MODIFIED) {
                        EContact *contact = NULL;
@@ -648,7 +654,7 @@ ebmb_upload_local_changes_sync (EBookMetaBackend *meta_backend,
                        if (success) {
                                success = ebmb_save_contact_wrapper_sync (meta_backend, book_cache,
                                        change->state == E_OFFLINE_STATE_LOCALLY_MODIFIED,
-                                       conflict_resolution, contact, extra, change->uid, NULL, NULL, NULL, 
cancellable, error);
+                                       conflict_resolution, contact, extra, opflags, change->uid, NULL, 
NULL, NULL, cancellable, error);
                        }
 
                        g_clear_object (&contact);
@@ -656,7 +662,7 @@ ebmb_upload_local_changes_sync (EBookMetaBackend *meta_backend,
                        GError *local_error = NULL;
 
                        success = e_book_meta_backend_remove_contact_sync (meta_backend, conflict_resolution,
-                               change->uid, extra, change->object, cancellable, &local_error);
+                               change->uid, extra, change->object, opflags, cancellable, &local_error);
 
                        if (!success) {
                                if (g_error_matches (local_error, E_DATA_BOOK_ERROR, 
E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND)) {
@@ -708,6 +714,7 @@ ebmb_maybe_remove_from_cache (EBookMetaBackend *meta_backend,
                              EBookCache *book_cache,
                              ECacheOfflineFlag offline_flag,
                              const gchar *uid,
+                             guint32 opflags,
                              GCancellable *cancellable,
                              GError **error)
 {
@@ -730,7 +737,7 @@ ebmb_maybe_remove_from_cache (EBookMetaBackend *meta_backend,
 
        book_backend = E_BOOK_BACKEND (meta_backend);
 
-       if (!e_book_cache_remove_contact (book_cache, uid, offline_flag, cancellable, error)) {
+       if (!e_book_cache_remove_contact (book_cache, uid, opflags, offline_flag, cancellable, error)) {
                g_object_unref (contact);
                return FALSE;
        }
@@ -975,6 +982,7 @@ ebmb_put_contact (EBookMetaBackend *meta_backend,
                  ECacheOfflineFlag offline_flag,
                  EContact *contact,
                  const gchar *extra,
+                 guint32 opflags,
                  GCancellable *cancellable,
                  GError **error)
 {
@@ -1020,7 +1028,7 @@ ebmb_put_contact (EBookMetaBackend *meta_backend,
                }
        }
 
-       success = success && e_book_cache_put_contact (book_cache, contact, extra, offline_flag, cancellable, 
error);
+       success = success && e_book_cache_put_contact (book_cache, contact, extra, opflags, offline_flag, 
cancellable, error);
 
        if (success)
                e_book_backend_notify_update (E_BOOK_BACKEND (meta_backend), contact);
@@ -1063,7 +1071,7 @@ ebmb_load_contact_wrapper_sync (EBookMetaBackend *meta_backend,
        }
 
        success = ebmb_put_contact (meta_backend, book_cache, offline_flag,
-               contact, extra ? extra : preloaded_extra, cancellable, &local_error);
+               contact, extra ? extra : preloaded_extra, 0, cancellable, &local_error);
 
        if (success && out_new_uid)
                *out_new_uid = e_contact_get (contact, E_CONTACT_UID);
@@ -1089,6 +1097,7 @@ ebmb_save_contact_wrapper_sync (EBookMetaBackend *meta_backend,
                                EConflictResolution conflict_resolution,
                                /* const */ EContact *in_contact,
                                const gchar *extra,
+                               guint32 opflags,
                                const gchar *orig_uid,
                                gboolean *out_requires_put,
                                gchar **out_new_uid,
@@ -1112,7 +1121,7 @@ ebmb_save_contact_wrapper_sync (EBookMetaBackend *meta_backend,
        success = e_book_meta_backend_inline_local_photos_sync (meta_backend, contact, cancellable, error);
 
        success = success && e_book_meta_backend_save_contact_sync (meta_backend, overwrite_existing, 
conflict_resolution,
-               contact, extra, &new_uid, &new_extra, cancellable, &local_error);
+               contact, extra, opflags, &new_uid, &new_extra, cancellable, &local_error);
 
        if (success && new_uid && *new_uid) {
                gchar *loaded_uid = NULL;
@@ -1121,7 +1130,7 @@ ebmb_save_contact_wrapper_sync (EBookMetaBackend *meta_backend,
                        new_extra ? new_extra : extra, &loaded_uid, cancellable, error);
 
                if (success && g_strcmp0 (loaded_uid, orig_uid) != 0)
-                       success = ebmb_maybe_remove_from_cache (meta_backend, book_cache, E_CACHE_IS_ONLINE, 
orig_uid, cancellable, error);
+                       success = ebmb_maybe_remove_from_cache (meta_backend, book_cache, E_CACHE_IS_ONLINE, 
orig_uid, opflags, cancellable, error);
 
                if (success && out_new_uid)
                        *out_new_uid = loaded_uid;
@@ -1158,7 +1167,7 @@ ebmb_get_backend_property (EBookBackend *book_backend,
        g_return_val_if_fail (E_IS_BOOK_META_BACKEND (book_backend), NULL);
        g_return_val_if_fail (prop_name != NULL, NULL);
 
-       if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REVISION)) {
+       if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REVISION)) {
                EBookCache *book_cache;
                gchar *revision = NULL;
 
@@ -1173,9 +1182,9 @@ ebmb_get_backend_property (EBookBackend *book_backend,
                return revision;
        } else if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
                return g_strdup (e_book_meta_backend_get_capabilities (E_BOOK_META_BACKEND (book_backend)));
-       } else  if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       } else  if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                return g_strdup (e_contact_field_name (E_CONTACT_FILE_AS));
-       } else if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                GString *fields;
                gint ii;
 
@@ -1281,6 +1290,7 @@ ebmb_create_contact_sync (EBookMetaBackend *meta_backend,
                          EBookCache *book_cache,
                          ECacheOfflineFlag *offline_flag,
                          EConflictResolution conflict_resolution,
+                         guint32 opflags,
                          EContact *contact,
                          gchar **out_new_uid,
                          EContact **out_new_contact,
@@ -1324,14 +1334,14 @@ ebmb_create_contact_sync (EBookMetaBackend *meta_backend,
        }
 
        if (*offline_flag == E_CACHE_IS_ONLINE) {
-               if (!ebmb_save_contact_wrapper_sync (meta_backend, book_cache, FALSE, conflict_resolution, 
contact, NULL, uid,
+               if (!ebmb_save_contact_wrapper_sync (meta_backend, book_cache, FALSE, conflict_resolution, 
contact, NULL, opflags, uid,
                        &requires_put, &new_uid, &new_extra, cancellable, error)) {
                        return FALSE;
                }
        }
 
        if (requires_put) {
-               success = e_book_cache_put_contact (book_cache, contact, new_extra, *offline_flag, 
cancellable, error);
+               success = e_book_cache_put_contact (book_cache, contact, new_extra, opflags, *offline_flag, 
cancellable, error);
                if (success)
                        e_book_backend_notify_update (E_BOOK_BACKEND (meta_backend), contact);
        } else {
@@ -1360,6 +1370,7 @@ ebmb_create_contact_sync (EBookMetaBackend *meta_backend,
 static gboolean
 ebmb_create_contacts_sync (EBookBackendSync *book_backend,
                           const gchar * const *vcards,
+                          guint32 opflags,
                           GSList **out_contacts,
                           GCancellable *cancellable,
                           GError **error)
@@ -1367,7 +1378,7 @@ ebmb_create_contacts_sync (EBookBackendSync *book_backend,
        EBookMetaBackend *meta_backend;
        EBookCache *book_cache;
        ECacheOfflineFlag offline_flag = E_CACHE_OFFLINE_UNKNOWN;
-       EConflictResolution conflict_resolution = E_CONFLICT_RESOLUTION_FAIL;
+       EConflictResolution conflict_resolution = e_book_util_operation_flags_to_conflict_resolution 
(opflags);
        gint ii;
        gboolean success = TRUE;
 
@@ -1402,7 +1413,7 @@ ebmb_create_contacts_sync (EBookBackendSync *book_backend,
                }
 
                success = ebmb_create_contact_sync (meta_backend, book_cache, &offline_flag, 
conflict_resolution,
-                       contact, NULL, &new_contact, cancellable, error);
+                       opflags, contact, NULL, &new_contact, cancellable, error);
 
                if (success) {
                        ebmb_foreach_cursor (meta_backend, new_contact, e_data_book_cursor_contact_added);
@@ -1430,6 +1441,7 @@ ebmb_modify_contact_sync (EBookMetaBackend *meta_backend,
                          EBookCache *book_cache,
                          ECacheOfflineFlag *offline_flag,
                          EConflictResolution conflict_resolution,
+                         guint32 opflags,
                          EContact *contact,
                          EContact **out_new_contact,
                          GCancellable *cancellable,
@@ -1474,11 +1486,11 @@ ebmb_modify_contact_sync (EBookMetaBackend *meta_backend,
 
        if (success && *offline_flag == E_CACHE_IS_ONLINE) {
                success = ebmb_save_contact_wrapper_sync (meta_backend, book_cache, TRUE, conflict_resolution,
-                       contact, extra, uid, &requires_put, &new_uid, &new_extra, cancellable, error);
+                       contact, extra, opflags, uid, &requires_put, &new_uid, &new_extra, cancellable, 
error);
        }
 
        if (success && requires_put)
-               success = ebmb_put_contact (meta_backend, book_cache, *offline_flag, contact, new_extra ? 
new_extra : extra, cancellable, error);
+               success = ebmb_put_contact (meta_backend, book_cache, *offline_flag, contact, new_extra ? 
new_extra : extra, opflags, cancellable, error);
 
        if (success && out_new_contact) {
                if (new_uid) {
@@ -1500,6 +1512,7 @@ ebmb_modify_contact_sync (EBookMetaBackend *meta_backend,
 static gboolean
 ebmb_modify_contacts_sync (EBookBackendSync *book_backend,
                           const gchar * const *vcards,
+                          guint32 opflags,
                           GSList **out_contacts,
                           GCancellable *cancellable,
                           GError **error)
@@ -1507,7 +1520,7 @@ ebmb_modify_contacts_sync (EBookBackendSync *book_backend,
        EBookMetaBackend *meta_backend;
        EBookCache *book_cache;
        ECacheOfflineFlag offline_flag = E_CACHE_OFFLINE_UNKNOWN;
-       EConflictResolution conflict_resolution = E_CONFLICT_RESOLUTION_FAIL;
+       EConflictResolution conflict_resolution = e_book_util_operation_flags_to_conflict_resolution 
(opflags);
        gint ii;
        gboolean success = TRUE;
 
@@ -1541,7 +1554,7 @@ ebmb_modify_contacts_sync (EBookBackendSync *book_backend,
                        break;
                }
 
-               success = ebmb_modify_contact_sync (meta_backend, book_cache, &offline_flag, 
conflict_resolution,
+               success = ebmb_modify_contact_sync (meta_backend, book_cache, &offline_flag, 
conflict_resolution, opflags,
                        contact, &new_contact, cancellable, error);
 
                if (success && new_contact) {
@@ -1572,6 +1585,7 @@ ebmb_remove_contact_sync (EBookMetaBackend *meta_backend,
                          EBookCache *book_cache,
                          ECacheOfflineFlag *offline_flag,
                          EConflictResolution conflict_resolution,
+                         guint32 opflags,
                          const gchar *uid,
                          GCancellable *cancellable,
                          GError **error)
@@ -1611,7 +1625,7 @@ ebmb_remove_contact_sync (EBookMetaBackend *meta_backend,
 
                g_warn_if_fail (e_book_cache_get_vcard (book_cache, uid, FALSE, &vcard_string, cancellable, 
NULL));
 
-               success = e_book_meta_backend_remove_contact_sync (meta_backend, conflict_resolution, uid, 
extra, vcard_string, cancellable, &local_error);
+               success = e_book_meta_backend_remove_contact_sync (meta_backend, conflict_resolution, uid, 
extra, vcard_string, opflags, cancellable, &local_error);
 
                g_free (vcard_string);
 
@@ -1624,7 +1638,7 @@ ebmb_remove_contact_sync (EBookMetaBackend *meta_backend,
                }
        }
 
-       success = success && ebmb_maybe_remove_from_cache (meta_backend, book_cache, *offline_flag, uid, 
cancellable, error);
+       success = success && ebmb_maybe_remove_from_cache (meta_backend, book_cache, *offline_flag, uid, 
opflags, cancellable, error);
 
        g_clear_object (&existing_contact);
        g_free (extra);
@@ -1635,6 +1649,7 @@ ebmb_remove_contact_sync (EBookMetaBackend *meta_backend,
 static gboolean
 ebmb_remove_contacts_sync (EBookBackendSync *book_backend,
                           const gchar * const *uids,
+                          guint32 opflags,
                           GSList **out_removed_uids,
                           GCancellable *cancellable,
                           GError **error)
@@ -1642,7 +1657,7 @@ ebmb_remove_contacts_sync (EBookBackendSync *book_backend,
        EBookMetaBackend *meta_backend;
        EBookCache *book_cache;
        ECacheOfflineFlag offline_flag = E_CACHE_OFFLINE_UNKNOWN;
-       EConflictResolution conflict_resolution = E_CONFLICT_RESOLUTION_FAIL;
+       EConflictResolution conflict_resolution = e_book_util_operation_flags_to_conflict_resolution 
(opflags);
        gint ii;
        gboolean success = TRUE;
 
@@ -1675,7 +1690,7 @@ ebmb_remove_contacts_sync (EBookBackendSync *book_backend,
                        break;
                }
 
-               success = ebmb_remove_contact_sync (meta_backend, book_cache, &offline_flag, 
conflict_resolution, uid, cancellable, error);
+               success = ebmb_remove_contact_sync (meta_backend, book_cache, &offline_flag, 
conflict_resolution, opflags, uid, cancellable, error);
                if (success)
                        *out_removed_uids = g_slist_prepend (*out_removed_uids, g_strdup (uid));
        }
@@ -2732,7 +2747,7 @@ ebmb_cache_revision_changed_cb (ECache *cache,
        revision = e_cache_dup_revision (cache);
        if (revision) {
                e_book_backend_notify_property_changed (E_BOOK_BACKEND (meta_backend),
-                       BOOK_BACKEND_PROPERTY_REVISION, revision);
+                       E_BOOK_BACKEND_PROPERTY_REVISION, revision);
                g_free (revision);
        }
 }
@@ -3509,7 +3524,7 @@ e_book_meta_backend_process_changes_sync (EBookMetaBackend *meta_backend,
                        continue;
                }
 
-               success = ebmb_maybe_remove_from_cache (meta_backend, book_cache, E_CACHE_IS_ONLINE, 
nfo->uid, cancellable, error);
+               success = ebmb_maybe_remove_from_cache (meta_backend, book_cache, E_CACHE_IS_ONLINE, 
nfo->uid, 0, cancellable, error);
        }
 
        /* Then modified objects */
@@ -3939,6 +3954,7 @@ e_book_meta_backend_load_contact_sync (EBookMetaBackend *meta_backend,
  * @conflict_resolution: one of #EConflictResolution, what to do on conflicts
  * @contact: an #EContact to save
  * @extra: (nullable): extra data saved with the contacts in an #EBookCache
+ * @opflags: bit-or of EBookOperationFlags
  * @out_new_uid: (out) (transfer full): return location for the UID of the saved contact
  * @out_new_extra: (out) (transfer full): return location for the extra data to store with the contact
  * @cancellable: optional #GCancellable object, or %NULL
@@ -3978,6 +3994,7 @@ e_book_meta_backend_save_contact_sync (EBookMetaBackend *meta_backend,
                                       EConflictResolution conflict_resolution,
                                       /* const */ EContact *contact,
                                       const gchar *extra,
+                                      guint32 opflags,
                                       gchar **out_new_uid,
                                       gchar **out_new_extra,
                                       GCancellable *cancellable,
@@ -4017,6 +4034,7 @@ e_book_meta_backend_save_contact_sync (EBookMetaBackend *meta_backend,
                        conflict_resolution,
                        contact,
                        extra,
+                       opflags,
                        out_new_uid,
                        out_new_extra,
                        cancellable,
@@ -4039,6 +4057,7 @@ e_book_meta_backend_save_contact_sync (EBookMetaBackend *meta_backend,
  * @uid: a contact UID
  * @extra: (nullable): extra data being saved with the contact in the local cache, or %NULL
  * @object: (nullable): corresponding vCard object, as stored in the local cache, or %NULL
+ * @opflags: bit-or of #EBookOperationFlags
  * @cancellable: optional #GCancellable object, or %NULL
  * @error: return location for a #GError, or %NULL
  *
@@ -4058,6 +4077,7 @@ e_book_meta_backend_remove_contact_sync (EBookMetaBackend *meta_backend,
                                         const gchar *uid,
                                         const gchar *extra,
                                         const gchar *object,
+                                        guint32 opflags,
                                         GCancellable *cancellable,
                                         GError **error)
 {
@@ -4088,7 +4108,7 @@ e_book_meta_backend_remove_contact_sync (EBookMetaBackend *meta_backend,
                g_clear_error (&local_error);
                repeat_count++;
 
-               success = klass->remove_contact_sync (meta_backend, conflict_resolution, uid, extra, object, 
cancellable, &local_error);
+               success = klass->remove_contact_sync (meta_backend, conflict_resolution, uid, extra, object, 
opflags, cancellable, &local_error);
 
                if (!success && repeat_count <= MAX_REPEAT_COUNT && !ebmb_maybe_wait_for_credentials 
(meta_backend, wait_credentials_stamp, local_error, cancellable))
                        break;
diff --git a/src/addressbook/libedata-book/e-book-meta-backend.h 
b/src/addressbook/libedata-book/e-book-meta-backend.h
index cc9d9a3bd..23f80eb1a 100644
--- a/src/addressbook/libedata-book/e-book-meta-backend.h
+++ b/src/addressbook/libedata-book/e-book-meta-backend.h
@@ -140,6 +140,7 @@ struct _EBookMetaBackendClass {
                                                 EConflictResolution conflict_resolution,
                                                 /* const */ EContact *contact,
                                                 const gchar *extra,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 gchar **out_new_uid,
                                                 gchar **out_new_extra,
                                                 GCancellable *cancellable,
@@ -149,6 +150,7 @@ struct _EBookMetaBackendClass {
                                                 const gchar *uid,
                                                 const gchar *extra,
                                                 const gchar *object,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
        gboolean        (* search_sync)         (EBookMetaBackend *meta_backend,
@@ -275,6 +277,7 @@ gboolean    e_book_meta_backend_save_contact_sync
                                                 EConflictResolution conflict_resolution,
                                                 /* const */ EContact *contact,
                                                 const gchar *extra,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 gchar **out_new_uid,
                                                 gchar **out_new_extra,
                                                 GCancellable *cancellable,
@@ -285,6 +288,7 @@ gboolean    e_book_meta_backend_remove_contact_sync
                                                 const gchar *uid,
                                                 const gchar *extra,
                                                 const gchar *object,
+                                                guint32 opflags, /* bit-or of EBookOperationFlags */
                                                 GCancellable *cancellable,
                                                 GError **error);
 gboolean       e_book_meta_backend_search_sync (EBookMetaBackend *meta_backend,
diff --git a/src/addressbook/libedata-book/e-data-book.c b/src/addressbook/libedata-book/e-data-book.c
index 81199a81b..06729a0d1 100644
--- a/src/addressbook/libedata-book/e-data-book.c
+++ b/src/addressbook/libedata-book/e-data-book.c
@@ -998,9 +998,10 @@ data_book_complete_create_contacts_cb (GObject *source_object,
 
 static gboolean
 data_book_handle_create_contacts_cb (EDBusAddressBook *dbus_interface,
-                                     GDBusMethodInvocation *invocation,
-                                     const gchar * const *in_vcards,
-                                     EDataBook *data_book)
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar * const *in_vcards,
+                                    guint32 in_opflags,
+                                    EDataBook *data_book)
 {
        EBookBackend *backend;
        AsyncContext *async_context;
@@ -1011,7 +1012,7 @@ data_book_handle_create_contacts_cb (EDBusAddressBook *dbus_interface,
        async_context = async_context_new (data_book, invocation);
 
        e_book_backend_create_contacts (
-               backend, in_vcards,
+               backend, in_vcards, in_opflags,
                async_context->cancellable,
                data_book_complete_create_contacts_cb,
                async_context);
@@ -1047,9 +1048,10 @@ data_book_complete_modify_contacts_cb (GObject *source_object,
 
 static gboolean
 data_book_handle_modify_contacts_cb (EDBusAddressBook *dbus_interface,
-                                     GDBusMethodInvocation *invocation,
-                                     const gchar * const *in_vcards,
-                                     EDataBook *data_book)
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar * const *in_vcards,
+                                    guint32 in_opflags,
+                                    EDataBook *data_book)
 {
        EBookBackend *backend;
        AsyncContext *async_context;
@@ -1060,7 +1062,7 @@ data_book_handle_modify_contacts_cb (EDBusAddressBook *dbus_interface,
        async_context = async_context_new (data_book, invocation);
 
        e_book_backend_modify_contacts (
-               backend, in_vcards,
+               backend, in_vcards, in_opflags,
                async_context->cancellable,
                data_book_complete_modify_contacts_cb,
                async_context);
@@ -1096,9 +1098,10 @@ data_book_complete_remove_contacts_cb (GObject *source_object,
 
 static gboolean
 data_book_handle_remove_contacts_cb (EDBusAddressBook *dbus_interface,
-                                     GDBusMethodInvocation *invocation,
-                                     const gchar * const *in_uids,
-                                     EDataBook *data_book)
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar * const *in_uids,
+                                    guint32 in_opflags,
+                                    EDataBook *data_book)
 {
        EBookBackend *backend;
        AsyncContext *async_context;
@@ -1109,7 +1112,7 @@ data_book_handle_remove_contacts_cb (EDBusAddressBook *dbus_interface,
        async_context = async_context_new (data_book, invocation);
 
        e_book_backend_remove_contacts (
-               backend, in_uids,
+               backend, in_uids, in_opflags,
                async_context->cancellable,
                data_book_complete_remove_contacts_cb,
                async_context);
@@ -1829,14 +1832,14 @@ e_data_book_report_backend_property_changed (EDataBook *book,
        if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_REVISION))
                e_dbus_address_book_set_revision (dbus_interface, prop_value);
 
-       if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
+       if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) {
                strv = g_strsplit (prop_value, ",", -1);
                e_dbus_address_book_set_required_fields (
                        dbus_interface, (const gchar * const *) strv);
                g_strfreev (strv);
        }
 
-       if (g_str_equal (prop_name, BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
+       if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) {
                strv = g_strsplit (prop_value, ",", -1);
                e_dbus_address_book_set_supported_fields (
                        dbus_interface, (const gchar * const *) strv);
@@ -2035,13 +2038,13 @@ data_book_constructed (GObject *object)
                book, prop_name, prop_value);
        g_free (prop_value);
 
-       prop_name = BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
+       prop_name = E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS;
        prop_value = e_book_backend_get_backend_property (backend, prop_name);
        e_data_book_report_backend_property_changed (
                book, prop_name, prop_value);
        g_free (prop_value);
 
-       prop_name = BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
+       prop_name = E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS;
        prop_value = e_book_backend_get_backend_property (backend, prop_name);
        e_data_book_report_backend_property_changed (
                book, prop_name, prop_value);
diff --git a/src/examples/cursor/cursor-data.c b/src/examples/cursor/cursor-data.c
index 57bc51c07..9d19b5805 100644
--- a/src/examples/cursor/cursor-data.c
+++ b/src/examples/cursor/cursor-data.c
@@ -113,7 +113,7 @@ load_contacts (EBookClient *client,
 
        if (contacts != NULL) {
 
-               if (!e_book_client_add_contacts_sync (client, contacts, NULL, NULL, &error)) {
+               if (!e_book_client_add_contacts_sync (client, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, 
NULL, &error)) {
 
                        /* If they were already added, ignore the error */
                        if (g_error_matches (error, E_BOOK_CLIENT_ERROR,
diff --git a/src/private/org.gnome.evolution.dataserver.AddressBook.xml 
b/src/private/org.gnome.evolution.dataserver.AddressBook.xml
index b91f82bbe..61c645ba0 100644
--- a/src/private/org.gnome.evolution.dataserver.AddressBook.xml
+++ b/src/private/org.gnome.evolution.dataserver.AddressBook.xml
@@ -42,15 +42,18 @@
 
   <method name="CreateContacts">
     <arg name="vcards" direction="in" type="as"/>
+    <arg name="opflags" direction="in" type="u"/>
     <arg name="uids" direction="out" type="as"/>
   </method>
 
   <method name="ModifyContacts">
     <arg name="vcards" direction="in" type="as"/>
+    <arg name="opflags" direction="in" type="u"/>
   </method>
 
   <method name="RemoveContacts">
     <arg name="uids" direction="in" type="as"/>
+    <arg name="opflags" direction="in" type="u"/>
   </method>
 
   <method name="GetContact">
diff --git a/tests/book-migration/setup-migration-test.c b/tests/book-migration/setup-migration-test.c
index 9021f5d62..dbc830c97 100644
--- a/tests/book-migration/setup-migration-test.c
+++ b/tests/book-migration/setup-migration-test.c
@@ -238,7 +238,7 @@ add_contacts (Book *book,
 {
        GError *error = NULL;
 
-       if (!e_book_client_add_contacts_sync (book, contacts, NULL, NULL, &error))
+       if (!e_book_client_add_contacts_sync (book, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, &error))
                g_error ("Failed to add contacts: %s", error->message);
 }
 
diff --git a/tests/book-migration/test-migration.c b/tests/book-migration/test-migration.c
index 172efa618..b7b40e2a1 100644
--- a/tests/book-migration/test-migration.c
+++ b/tests/book-migration/test-migration.c
@@ -174,10 +174,10 @@ test_add_remove_contact (MigrationFixture *fixture,
 
        contact = e_contact_new_from_vcard (arbitrary_vcard);
 
-       if (!e_book_client_add_contact_sync (book_client, contact, NULL, NULL, &error))
+       if (!e_book_client_add_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, 
&error))
                g_error ("Failed to add contact: %s", error->message);
 
-       if (!e_book_client_remove_contact_sync (book_client, contact, NULL, &error))
+       if (!e_book_client_remove_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, 
&error))
                g_error ("Failed to remove contact: %s", error->message);
 
        g_object_unref (contact);
diff --git a/tests/libebook/client/client-test-utils.c b/tests/libebook/client/client-test-utils.c
index 33db04422..f6ff5363d 100644
--- a/tests/libebook/client/client-test-utils.c
+++ b/tests/libebook/client/client-test-utils.c
@@ -115,7 +115,7 @@ add_contact_from_test_case_verify (EBookClient *book_client,
        vcard = new_vcard_from_test_case (case_name);
        contact_orig = e_contact_new_from_vcard (vcard);
        g_free (vcard);
-       if (!e_book_client_add_contact_sync (book_client, contact_orig, &uid, NULL, &error))
+       if (!e_book_client_add_contact_sync (book_client, contact_orig, E_BOOK_OPERATION_FLAG_NONE, &uid, 
NULL, &error))
                g_error ("add contact sync: %s", error->message);
 
        e_contact_set (contact_orig, E_CONTACT_UID, uid);
@@ -144,7 +144,7 @@ add_contact_verify (EBookClient *book_client,
        gchar *uid;
        GError *error = NULL;
 
-       if (!e_book_client_add_contact_sync (book_client, contact, &uid, NULL, &error))
+       if (!e_book_client_add_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("add contact sync: %s", error->message);
 
        e_contact_set (contact, E_CONTACT_UID, uid);
diff --git a/tests/libebook/client/test-book-client-add-and-get-async.c 
b/tests/libebook/client/test-book-client-add-and-get-async.c
index a88f55550..3267aadcc 100644
--- a/tests/libebook/client/test-book-client-add-and-get-async.c
+++ b/tests/libebook/client/test-book-client-add-and-get-async.c
@@ -186,7 +186,7 @@ add_contacts (EBookClient *book_client,
        g_free (vcard);
        contacts = g_slist_prepend (contacts, contact);
 
-       e_book_client_add_contacts (book_client, contacts, NULL, contacts_added_cb, loop);
+       e_book_client_add_contacts (book_client, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, 
contacts_added_cb, loop);
 
        e_util_free_object_slist (contacts);
 }
diff --git a/tests/libebook/client/test-book-client-add-contact.c 
b/tests/libebook/client/test-book-client-add-contact.c
index d618894a9..6ce86f721 100644
--- a/tests/libebook/client/test-book-client-add-contact.c
+++ b/tests/libebook/client/test-book-client-add-contact.c
@@ -70,7 +70,7 @@ test_add_contact_async (ETestServerFixture *fixture,
        contact = e_contact_new_from_vcard (vcard);
        g_free (vcard);
 
-       e_book_client_add_contact (book_client, contact, NULL, add_contact_cb, fixture->loop);
+       e_book_client_add_contact (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, add_contact_cb, 
fixture->loop);
        g_object_unref (contact);
 
        g_main_loop_run (fixture->loop);
diff --git a/tests/libebook/client/test-book-client-cursor-operations.c 
b/tests/libebook/client/test-book-client-cursor-operations.c
index b57add1af..9063d3dc6 100644
--- a/tests/libebook/client/test-book-client-cursor-operations.c
+++ b/tests/libebook/client/test-book-client-cursor-operations.c
@@ -309,7 +309,7 @@ cursor_fixture_add_contacts (CursorFixture *fixture,
                fixture->contacts[i] = contact;
        }
 
-       if (!e_book_client_add_contacts_sync (book_client, contacts, NULL, NULL, &error)) {
+       if (!e_book_client_add_contacts_sync (book_client, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, 
&error)) {
 
                /* Dont complain here, we re-use the same addressbook for multiple tests
                 * and we can't add the same contacts twice
@@ -1312,11 +1312,11 @@ cursor_test_add_remove (CursorFixture *fixture,
 
                if (modify->add)
                        e_book_client_add_contact (
-                               book_client, contact,
+                               book_client, contact, E_BOOK_OPERATION_FLAG_NONE,
                                NULL, cursor_test_add_remove_ready_cb, &data);
                else
                        e_book_client_remove_contact (
-                               book_client, contact,
+                               book_client, contact, E_BOOK_OPERATION_FLAG_NONE,
                                NULL, cursor_test_add_remove_ready_cb, &data);
 
                /* Wait for result with an error timeout */
@@ -1331,14 +1331,11 @@ cursor_test_add_remove (CursorFixture *fixture,
 
                if (modify->add)
                        success = e_book_client_add_contact_sync (
-                               book_client,
-                               contact,
-                               &new_uid,
-                               NULL, &error);
+                               book_client, contact, E_BOOK_OPERATION_FLAG_NONE,
+                               &new_uid, NULL, &error);
                else
                        success = e_book_client_remove_contact_sync (
-                               book_client,
-                               contact,
+                               book_client, contact, E_BOOK_OPERATION_FLAG_NONE,
                                NULL, &error);
 
                if (!success)
diff --git a/tests/libebook/client/test-book-client-custom-summary.c 
b/tests/libebook/client/test-book-client-custom-summary.c
index 80f0cfc1c..c9e75948c 100644
--- a/tests/libebook/client/test-book-client-custom-summary.c
+++ b/tests/libebook/client/test-book-client-custom-summary.c
@@ -114,7 +114,7 @@ setup_book (ClientTestFixture *fixture)
                g_free (case_name);
        }
 
-       if (!e_book_client_add_contacts_sync (book_client, contacts, NULL, NULL, &error)) {
+       if (!e_book_client_add_contacts_sync (book_client, contacts, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, 
&error)) {
 
                /* Dont complain here, we may re-use the same addressbook for multiple tests
                 * and we can't add the same contacts twice
diff --git a/tests/libebook/client/test-book-client-e164-param.c 
b/tests/libebook/client/test-book-client-e164-param.c
index 3d2ea5476..f254bfeed 100644
--- a/tests/libebook/client/test-book-client-e164-param.c
+++ b/tests/libebook/client/test-book-client-e164-param.c
@@ -98,7 +98,7 @@ test_add_e164_param (ETestServerFixture *fixture,
        values = e_vcard_attribute_get_param (tel, EVC_X_E164);
        g_assert (values == NULL);
 
-       if (!e_book_client_add_contact_sync (book_client, contact, &uid, NULL, &error))
+       if (!e_book_client_add_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("Failed to add contact: %s", error->message);
 
        g_object_unref (contact);
diff --git a/tests/libebook/client/test-book-client-get-revision.c 
b/tests/libebook/client/test-book-client-get-revision.c
index 8995f0659..cd7c41395 100644
--- a/tests/libebook/client/test-book-client-get-revision.c
+++ b/tests/libebook/client/test-book-client-get-revision.c
@@ -40,7 +40,7 @@ get_revision_compare_cycle (EBookClient *client)
                exit (1);
        }
 
-       if (!e_book_client_remove_contact_sync (client, contact, NULL, &error))
+       if (!e_book_client_remove_contact_sync (client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("Unable to remove contact: %s", error->message);
 
        g_object_unref (contact);
diff --git a/tests/libebook/client/test-book-client-modify-contact.c 
b/tests/libebook/client/test-book-client-modify-contact.c
index ac50c1f80..11a48b93f 100644
--- a/tests/libebook/client/test-book-client-modify-contact.c
+++ b/tests/libebook/client/test-book-client-modify-contact.c
@@ -65,7 +65,7 @@ test_modify_contact_sync (ETestServerFixture *fixture,
 
        verify_premodify_and_prepare_contact (contact);
 
-       if (!e_book_client_modify_contact_sync (book_client, contact, NULL, &error))
+       if (!e_book_client_modify_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, 
&error))
                g_error ("modify contact sync: %s", error->message);
 
        if (!e_book_client_get_contact_sync (book_client, e_contact_get_const (contact, E_CONTACT_UID),
@@ -134,7 +134,7 @@ test_modify_contact_async (ETestServerFixture *fixture,
 
        data.contact = contact;
        data.loop = fixture->loop;
-       e_book_client_modify_contact (book_client, contact, NULL, contact_modified_cb, &data);
+       e_book_client_modify_contact (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, 
contact_modified_cb, &data);
 
        g_main_loop_run (fixture->loop);
 
diff --git a/tests/libebook/client/test-book-client-photo-is-uri.c 
b/tests/libebook/client/test-book-client-photo-is-uri.c
index e698597ed..1f33c1a09 100644
--- a/tests/libebook/client/test-book-client-photo-is-uri.c
+++ b/tests/libebook/client/test-book-client-photo-is-uri.c
@@ -137,7 +137,7 @@ give_james_brown_micheal_jacksons_face (EBookClient *book)
        e_contact_photo_free (micheal_face);
        e_contact_photo_free (james_face);
 
-       if (!e_book_client_modify_contact_sync (book, james, NULL, &error))
+       if (!e_book_client_modify_contact_sync (book, james, E_BOOK_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("Failed to modify contact with cross referenced photo: %s", error->message);
 }
 
@@ -169,7 +169,7 @@ update_contact_inline (EBookClient *book,
 
        e_contact_photo_free (photo);
 
-       if (!e_book_client_modify_contact_sync (book, contact, NULL, &error))
+       if (!e_book_client_modify_contact_sync (book, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("Failed to modify contact with inline photo data: %s", error->message);
 }
 
@@ -218,7 +218,7 @@ complete (EBookClientView *view,
        case ITERATION_DELETE_JAMES:
                assert_uri_exists (book, james_brown_uid);
 
-               if (!e_book_client_remove_contact_by_uid_sync (book, james_brown_uid, NULL, &local_error))
+               if (!e_book_client_remove_contact_by_uid_sync (book, james_brown_uid, 
E_BOOK_OPERATION_FLAG_NONE, NULL, &local_error))
                        g_error ("Error removing contact: %s", local_error->message);
 
                g_free (james_brown_uid);
@@ -232,7 +232,7 @@ complete (EBookClientView *view,
        case ITERATION_DELETE_MICHEAL:
                assert_uri_exists (book, micheal_jackson_uid);
 
-               if (!e_book_client_remove_contact_by_uid_sync (book, micheal_jackson_uid, NULL, &local_error))
+               if (!e_book_client_remove_contact_by_uid_sync (book, micheal_jackson_uid, 
E_BOOK_OPERATION_FLAG_NONE, NULL, &local_error))
                        g_error ("Error removing contact: %s", local_error->message);
 
                g_free (micheal_jackson_uid);
diff --git a/tests/libebook/client/test-book-client-preserve-uid.c 
b/tests/libebook/client/test-book-client-preserve-uid.c
index 2afcbdf74..fa0aa4dc7 100644
--- a/tests/libebook/client/test-book-client-preserve-uid.c
+++ b/tests/libebook/client/test-book-client-preserve-uid.c
@@ -45,7 +45,7 @@ test_preserve_uid (ETestServerFixture *fixture,
 
        e_contact_set (contact, E_CONTACT_UID, TEST_CONTACT_UID);
 
-       if (!e_book_client_add_contact_sync (book_client, contact, &uid, NULL, &error))
+       if (!e_book_client_add_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, &uid, NULL, 
&error))
                g_error ("Failed to add contact: %s", error->message);
 
        g_assert_cmpstr (uid, ==, TEST_CONTACT_UID);
@@ -73,7 +73,7 @@ test_uid_conflict (ETestServerFixture *fixture,
 
        e_contact_set (contact, E_CONTACT_UID, TEST_CONTACT_UID);
 
-       if (!e_book_client_add_contact_sync (book_client, contact, NULL, NULL, &error)) {
+       if (!e_book_client_add_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, NULL, 
&error)) {
                g_assert (g_error_matches (error, E_BOOK_CLIENT_ERROR, 
E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS));
                g_error_free (error);
        } else
diff --git a/tests/libebook/client/test-book-client-remove-contact-by-uid.c 
b/tests/libebook/client/test-book-client-remove-contact-by-uid.c
index 7bbcc4712..b333a8d93 100644
--- a/tests/libebook/client/test-book-client-remove-contact-by-uid.c
+++ b/tests/libebook/client/test-book-client-remove-contact-by-uid.c
@@ -38,7 +38,7 @@ test_remove_contact_by_uid_sync (ETestServerFixture *fixture,
 
        uid = e_contact_get (contact, E_CONTACT_UID);
 
-       if (!e_book_client_remove_contact_by_uid_sync (book_client, uid, NULL, &error))
+       if (!e_book_client_remove_contact_by_uid_sync (book_client, uid, E_BOOK_OPERATION_FLAG_NONE, NULL, 
&error))
                g_error ("remove contact sync: %s", error->message);
 
        if (!e_book_client_get_contact_sync (book_client, uid, &contact, NULL, &error) &&
@@ -94,7 +94,7 @@ test_remove_contact_by_uid_async (ETestServerFixture *fixture,
 
        data.uid = uid;
        data.loop = fixture->loop;
-       e_book_client_remove_contact_by_uid (book_client, uid, NULL, remove_contact_by_uid_cb, &data);
+       e_book_client_remove_contact_by_uid (book_client, uid, E_BOOK_OPERATION_FLAG_NONE, NULL, 
remove_contact_by_uid_cb, &data);
 
        g_object_unref (contact);
 
diff --git a/tests/libebook/client/test-book-client-remove-contact.c 
b/tests/libebook/client/test-book-client-remove-contact.c
index 4fc04e065..850be973f 100644
--- a/tests/libebook/client/test-book-client-remove-contact.c
+++ b/tests/libebook/client/test-book-client-remove-contact.c
@@ -41,7 +41,7 @@ check_removed_contact (EBookClient *book_client,
        else
                g_clear_error (&error);
 
-       if (e_book_client_remove_contact_by_uid_sync (book_client, uid, NULL, &error))
+       if (e_book_client_remove_contact_by_uid_sync (book_client, uid, E_BOOK_OPERATION_FLAG_NONE, NULL, 
&error))
                g_error ("succeeded to remove the already removed contact");
        else if (!g_error_matches (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND))
                g_error (
@@ -67,7 +67,7 @@ test_remove_contact_sync (ETestServerFixture *fixture,
 
        uid = e_contact_get (contact, E_CONTACT_UID);
 
-       if (!e_book_client_remove_contact_sync (book_client, contact, NULL, &error))
+       if (!e_book_client_remove_contact_sync (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, 
&error))
                g_error ("remove contact sync: %s", error->message);
 
        g_object_unref (contact);
@@ -116,7 +116,7 @@ test_remove_contact_async (ETestServerFixture *fixture,
 
        data.uid = uid;
        data.loop = fixture->loop;
-       e_book_client_remove_contact (book_client, contact, NULL, remove_contact_cb, &data);
+       e_book_client_remove_contact (book_client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL, 
remove_contact_cb, &data);
 
        g_object_unref (contact);
 
diff --git a/tests/libebook/client/test-book-client-remove-contacts.c 
b/tests/libebook/client/test-book-client-remove-contacts.c
index a51517bfa..d7ca10583 100644
--- a/tests/libebook/client/test-book-client-remove-contacts.c
+++ b/tests/libebook/client/test-book-client-remove-contacts.c
@@ -82,7 +82,7 @@ test_remove_contacts_sync (ETestServerFixture *fixture,
        if (!fill_book_client (book_client, &uids))
                g_error ("Failed to add contacts");
 
-       if (!e_book_client_remove_contacts_sync (book_client, uids, NULL, &error))
+       if (!e_book_client_remove_contacts_sync (book_client, uids, E_BOOK_OPERATION_FLAG_NONE, NULL, &error))
                g_error ("remove contact sync: %s", error->message);
 
        /* This will assert they are actually removed */
@@ -126,7 +126,7 @@ test_remove_contacts_async (ETestServerFixture *fixture,
 
        data.uids = uids;
        data.loop = fixture->loop;
-       e_book_client_remove_contacts (book_client, uids, NULL, remove_contacts_cb, &data);
+       e_book_client_remove_contacts (book_client, uids, E_BOOK_OPERATION_FLAG_NONE, NULL, 
remove_contacts_cb, &data);
 
        g_main_loop_run (fixture->loop);
 
diff --git a/tests/libebook/client/test-book-client-self.c b/tests/libebook/client/test-book-client-self.c
index a1537b97d..b146bbf47 100644
--- a/tests/libebook/client/test-book-client-self.c
+++ b/tests/libebook/client/test-book-client-self.c
@@ -65,7 +65,7 @@ test_set_self (ETestServerFixture *fixture,
        if (e_book_client_get_contact_sync (client, "simple-1", &loaded_contact, NULL, NULL)) {
                g_clear_object (&loaded_contact);
 
-               e_book_client_remove_contact_by_uid_sync (client, "simple-1", NULL, &error);
+               e_book_client_remove_contact_by_uid_sync (client, "simple-1", E_BOOK_OPERATION_FLAG_NONE, 
NULL, &error);
                g_assert_no_error (error);
        }
 
diff --git a/tests/libebook/client/test-book-client-write-write.c 
b/tests/libebook/client/test-book-client-write-write.c
index 00e6caed4..e31f52d11 100644
--- a/tests/libebook/client/test-book-client-write-write.c
+++ b/tests/libebook/client/test-book-client-write-write.c
@@ -133,7 +133,7 @@ test_write_thread_contact_fetched (GObject *source_object,
        e_contact_set (contact, data->field, data->value);
 
        e_book_client_modify_contact (
-               data->client, contact, NULL,
+               data->client, contact, E_BOOK_OPERATION_FLAG_NONE, NULL,
                (GAsyncReadyCallback) test_write_thread_contact_modified, data);
 
        g_object_unref (contact);
diff --git a/tests/libedata-book/test-book-cache-cursor-calculate.c 
b/tests/libedata-book/test-book-cache-cursor-calculate.c
index 7eb21b7a3..8d32229c5 100644
--- a/tests/libedata-book/test-book-cache-cursor-calculate.c
+++ b/tests/libedata-book/test-book-cache-cursor-calculate.c
@@ -260,7 +260,7 @@ test_cursor_calculate_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[19 - 1],
                                        e_contact_get_const (fixture->contacts[19 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* Rename Müller -> Sade Adu */
@@ -269,7 +269,7 @@ test_cursor_calculate_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[20 - 1],
                                        e_contact_get_const (fixture->contacts[20 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* Check new position */
@@ -410,7 +410,7 @@ test_cursor_calculate_filtered_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[18 - 1],
                                        e_contact_get_const (fixture->contacts[18 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* 'black-birds' -> Sade Adu */
@@ -419,7 +419,7 @@ test_cursor_calculate_filtered_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[17 - 1],
                                        e_contact_get_const (fixture->contacts[17 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* Check new position */
@@ -573,7 +573,7 @@ test_cursor_calculate_descending_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[19 - 1],
                                        e_contact_get_const (fixture->contacts[19 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* Rename Müller -> Sade Adu */
@@ -582,7 +582,7 @@ test_cursor_calculate_descending_after_modification (TCUCursorFixture *fixture,
        if (!e_book_cache_put_contact (((TCUFixture *) fixture)->book_cache,
                                        fixture->contacts[20 - 1],
                                        e_contact_get_const (fixture->contacts[20 - 1], E_CONTACT_UID),
-                                       E_CACHE_IS_ONLINE, NULL, &error))
+                                       0, E_CACHE_IS_ONLINE, NULL, &error))
                g_error ("Failed to modify contact: %s", error->message);
 
        /* Check new position */
diff --git a/tests/libedata-book/test-book-cache-offline.c b/tests/libedata-book/test-book-cache-offline.c
index b0fdc770b..745aa8e3b 100644
--- a/tests/libedata-book/test-book-cache-offline.c
+++ b/tests/libedata-book/test-book-cache-offline.c
@@ -435,6 +435,7 @@ test_offline_basics (TCUFixture *fixture,
        gint ii;
        const gchar *uid;
        gchar *saved_extra = NULL, *tmp;
+       guint32 custom_flags;
        GSList *uids = NULL;
        GError *error = NULL;
 
@@ -523,6 +524,14 @@ test_offline_basics (TCUFixture *fixture,
                        g_free (saved_extra);
                        saved_extra = NULL;
 
+                       g_assert (e_book_cache_set_contact_custom_flags (fixture->book_cache, uid, 123, NULL, 
&error));
+                       g_assert_no_error (error);
+
+                       custom_flags = 0;
+                       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, 
&custom_flags, NULL, &error));
+                       g_assert_no_error (error);
+                       g_assert_cmpint (custom_flags, ==, 123);
+
                        /* Search when locally deleted */
                        test_basic_search (fixture, EXPECT_DEFAULT);
                } else {
@@ -546,7 +555,7 @@ test_offline_basics (TCUFixture *fixture,
        /* Edit in online */
        e_contact_set (contact, E_CONTACT_REV, "rev-1");
 
-       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, E_CACHE_IS_ONLINE, NULL, 
&error));
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, E_CACHE_IS_ONLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        test_verify_storage (fixture, uid, "rev-1", NULL, E_OFFLINE_STATE_SYNCED);
@@ -554,7 +563,7 @@ test_offline_basics (TCUFixture *fixture,
 
        e_contact_set (contact, E_CONTACT_REV, "rev-2");
 
-       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, "extra-2", E_CACHE_IS_ONLINE, NULL, 
&error));
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, "extra-2", 0, E_CACHE_IS_ONLINE, 
NULL, &error));
        g_assert_no_error (error);
 
        test_verify_storage (fixture, uid, "rev-2", "extra-2", E_OFFLINE_STATE_SYNCED);
@@ -571,11 +580,19 @@ test_offline_basics (TCUFixture *fixture,
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
        g_assert_no_error (error);
 
+       g_assert (e_book_cache_set_contact_custom_flags (fixture->book_cache, uid, 234, NULL, &error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 234);
+
        /* Search before delete */
        test_basic_search (fixture, EXPECT_CUSTOM_1);
 
        /* Delete in online */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_ONLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_ONLINE, NULL, &error));
        g_assert_no_error (error);
 
        g_assert (!e_cache_set_offline_state (E_CACHE (fixture->book_cache), uid, 
E_OFFLINE_STATE_LOCALLY_MODIFIED, NULL, &error));
@@ -603,6 +620,14 @@ test_offline_basics (TCUFixture *fixture,
        g_assert_null (uids);
        g_clear_error (&error);
 
+       g_assert (!e_book_cache_set_contact_custom_flags (fixture->book_cache, uid, 456, NULL, &error));
+       g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
+       g_clear_error (&error);
+
+       g_assert (!e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
+       g_clear_error (&error);
+
        g_clear_object (&contact);
 
        /* Search after delete */
@@ -630,7 +655,7 @@ test_offline_add_one (TCUFixture *fixture,
                test_check_offline_state (fixture, uid, E_OFFLINE_STATE_UNKNOWN);
 
                /* Add a contact in offline */
-               g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, E_CACHE_IS_OFFLINE, 
NULL, &error));
+               g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, 
E_CACHE_IS_OFFLINE, NULL, &error));
                g_assert_no_error (error);
        } else {
                uid = case_name;
@@ -709,7 +734,7 @@ test_offline_add_edit (TCUFixture *fixture,
        /* Modify added in offline */
        e_contact_set (contact, E_CONTACT_REV, "rev-2");
 
-       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1 | SKIP_CONTACT_PUT, 
NULL);
@@ -728,6 +753,7 @@ test_offline_add_delete (TCUFixture *fixture,
                         gconstpointer user_data)
 {
        EContact *contact = NULL;
+       guint32 custom_flags = 0;
        const gchar *uid;
        GError *error = NULL;
 
@@ -752,13 +778,37 @@ test_offline_add_delete (TCUFixture *fixture,
 
        /* Delete added in offline */
 
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 1, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
+       g_assert (!e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_error (error, E_CACHE_ERROR, E_CACHE_ERROR_NOT_FOUND);
+       g_clear_error (&error);
+
        test_offline_add_one (fixture, "simple-1", 3, EXPECT_CUSTOM_1 | SKIP_CONTACT_PUT, NULL);
 
        test_check_offline_changes (fixture, NULL);
 
+       /* Add in online */
+
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 333, E_CACHE_IS_ONLINE, NULL, 
&error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 333);
+
+       /* Delete in offline */
+
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 246, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 246);
+
        g_clear_object (&contact);
 }
 
@@ -790,7 +840,7 @@ test_offline_add_delete_add (TCUFixture *fixture,
        g_assert_nonnull (uid);
 
        /* Delete added in offline */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        test_offline_add_one (fixture, "simple-1", 3, EXPECT_CUSTOM_1 | SKIP_CONTACT_PUT, NULL);
@@ -845,6 +895,7 @@ test_offline_edit_common (TCUFixture *fixture,
                          gchar **out_uid)
 {
        EContact *contact = NULL;
+       guint32 custom_flags = 0;
        const gchar *uid;
        GError *error = NULL;
 
@@ -861,11 +912,21 @@ test_offline_edit_common (TCUFixture *fixture,
        test_check_offline_changes (fixture, NULL);
        test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
 
+       custom_flags = 0;
+       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
+       g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 0);
+
        /* Modify in offline */
        e_contact_set (contact, E_CONTACT_REV, "rev-2");
 
-       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 369, E_CACHE_IS_OFFLINE, 
NULL, &error));
+       g_assert_no_error (error);
+
+       custom_flags = 0;
+       g_assert (e_book_cache_get_contact_custom_flags (fixture->book_cache, uid, &custom_flags, NULL, 
&error));
        g_assert_no_error (error);
+       g_assert_cmpint (custom_flags, ==, 369);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
        g_assert_no_error (error);
@@ -902,7 +963,7 @@ test_offline_edit_delete (TCUFixture *fixture,
        test_offline_edit_common (fixture, &uid);
 
        /* Delete the modified contact in offline */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
@@ -968,7 +1029,7 @@ test_offline_delete (TCUFixture *fixture,
        test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
 
        /* Delete in offline */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
@@ -1007,7 +1068,7 @@ test_offline_delete_add (TCUFixture *fixture,
 
        /* Delete locally created in offline */
        test_offline_add_one (fixture, "simple-1", 4, EXPECT_SIMPLE_1 | EXPECT_CUSTOM_1, NULL);
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, "simple-1", E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, "simple-1", 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 3);
@@ -1020,7 +1081,7 @@ test_offline_delete_add (TCUFixture *fixture,
        test_check_offline_state (fixture, "simple-1", E_OFFLINE_STATE_UNKNOWN);
 
        /* Delete synced in offline */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
@@ -1047,7 +1108,7 @@ test_offline_delete_add (TCUFixture *fixture,
        /* Modify the previous contact and add it again */
        e_contact_set (contact, E_CONTACT_REV, "rev-3");
 
-       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, E_CACHE_IS_OFFLINE, NULL, 
&error));
+       g_assert (e_book_cache_put_contact (fixture->book_cache, contact, NULL, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 4);
@@ -1089,7 +1150,7 @@ test_offline_delete_resync (TCUFixture *fixture,
        test_check_offline_state (fixture, uid, E_OFFLINE_STATE_SYNCED);
 
        /* Delete in offline */
-       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, E_CACHE_IS_OFFLINE, NULL, &error));
+       g_assert (e_book_cache_remove_contact (fixture->book_cache, uid, 0, E_CACHE_IS_OFFLINE, NULL, 
&error));
        g_assert_no_error (error);
 
        g_assert_cmpint (e_cache_get_count (E_CACHE (fixture->book_cache), E_CACHE_EXCLUDE_DELETED, NULL, 
&error), ==, 2);
diff --git a/tests/libedata-book/test-book-cache-utils.c b/tests/libedata-book/test-book-cache-utils.c
index 34a92a1d5..b2589bcc0 100644
--- a/tests/libedata-book/test-book-cache-utils.c
+++ b/tests/libedata-book/test-book-cache-utils.c
@@ -91,7 +91,7 @@ tcu_add_contact_from_test_case (TCUFixture *fixture,
 
        contact = tcu_new_contact_from_test_case (case_name);
 
-       if (!e_book_cache_put_contact (fixture->book_cache, contact, case_name, E_CACHE_IS_ONLINE, NULL, 
&error))
+       if (!e_book_cache_put_contact (fixture->book_cache, contact, case_name, 0, E_CACHE_IS_ONLINE, NULL, 
&error))
                g_error ("Failed to add contact: %s", error->message);
 
        if (ret_contact)
@@ -249,7 +249,7 @@ tcu_cursor_fixture_setup (TCUCursorFixture *fixture,
                fixture->contacts[ii] = g_object_ref (contact);
        }
 
-       if (!e_book_cache_put_contacts (base_fixture->book_cache, contacts, extra_list, E_CACHE_IS_ONLINE, 
NULL, &error)) {
+       if (!e_book_cache_put_contacts (base_fixture->book_cache, contacts, extra_list, NULL, 
E_CACHE_IS_ONLINE, NULL, &error)) {
                /* Dont complain here, we re-use the same addressbook for multiple tests
                 * and we can't add the same contacts twice
                 */
diff --git a/tests/libedata-book/test-book-meta-backend.c b/tests/libedata-book/test-book-meta-backend.c
index 2ea280ada..6045ab8d1 100644
--- a/tests/libedata-book/test-book-meta-backend.c
+++ b/tests/libedata-book/test-book-meta-backend.c
@@ -360,6 +360,7 @@ e_book_meta_backend_test_save_contact_sync (EBookMetaBackend *meta_backend,
                                            EConflictResolution conflict_resolution,
                                            EContact *contact,
                                            const gchar *extra,
+                                           guint32 opflags,
                                            gchar **out_new_uid,
                                            gchar **out_new_extra,
                                            GCancellable *cancellable,
@@ -438,6 +439,7 @@ e_book_meta_backend_test_remove_contact_sync (EBookMetaBackend *meta_backend,
                                              const gchar *uid,
                                              const gchar *extra,
                                              const gchar *object,
+                                             guint32 opflags,
                                              GCancellable *cancellable,
                                              GError **error)
 {
@@ -591,7 +593,7 @@ e_book_meta_backend_test_new (EBookCache *cache)
                gchar *extra;
 
                extra = g_strconcat ("extra for ", e_contact_get_const (contact, E_CONTACT_UID), NULL);
-               success = e_book_cache_put_contact (cache, contact, extra, E_CACHE_IS_ONLINE, NULL, &error);
+               success = e_book_cache_put_contact (cache, contact, extra, 0, E_CACHE_IS_ONLINE, NULL, 
&error);
                g_free (extra);
 
                g_assert_no_error (error);
@@ -861,7 +863,7 @@ test_create_contacts (EBookMetaBackend *meta_backend)
        vcards[0] = tcu_new_vcard_from_test_case ("custom-1");
 
        success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS);
        g_assert (!success);
        g_assert_cmpint (g_slist_length (new_contacts), ==, 0);
@@ -874,7 +876,7 @@ test_create_contacts (EBookMetaBackend *meta_backend)
        vcards[0] = tcu_new_vcard_from_test_case ("custom-7");
 
        success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
@@ -899,7 +901,7 @@ test_create_contacts (EBookMetaBackend *meta_backend)
        vcards[0] = tcu_new_vcard_from_test_case ("custom-7");
 
        success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS);
        g_assert (!success);
        g_assert_cmpint (g_slist_length (new_contacts), ==, 0);
@@ -912,7 +914,7 @@ test_create_contacts (EBookMetaBackend *meta_backend)
        vcards[0] = tcu_new_vcard_from_test_case ("custom-8");
 
        success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
@@ -951,7 +953,7 @@ test_create_contacts (EBookMetaBackend *meta_backend)
        memcpy (tmp, "X-TEST:*007*", 12);
 
        success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
@@ -1036,7 +1038,7 @@ test_modify_contacts (EBookMetaBackend *meta_backend)
        memcpy (tmp + 4, "unknown", 7);
 
        success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND);
        g_assert (!success);
        g_assert_cmpint (g_slist_length (new_contacts), ==, 0);
@@ -1047,7 +1049,7 @@ test_modify_contacts (EBookMetaBackend *meta_backend)
        vcards[0] = ebmb_test_modify_case ("custom-1");
 
        success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
@@ -1088,7 +1090,7 @@ test_modify_contacts (EBookMetaBackend *meta_backend)
        vcards[0] = ebmb_test_modify_case ("custom-2");
 
        success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) vcards, &new_contacts, NULL, &error);
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &new_contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (g_slist_length (new_contacts), ==, 1);
@@ -1161,7 +1163,7 @@ test_remove_contacts (EBookMetaBackend *meta_backend)
        uids[0] = "unknown-contact";
 
        success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) uids, &removed_uids, NULL, &error);
+               (const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
        g_assert_error (error, E_DATA_BOOK_ERROR, E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND);
        g_assert (!success);
        g_assert_null (removed_uids);
@@ -1171,7 +1173,7 @@ test_remove_contacts (EBookMetaBackend *meta_backend)
        uids[0] = "custom-1";
 
        success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) uids, &removed_uids, NULL, &error);
+               (const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (test_backend->load_count, ==, 0);
@@ -1195,7 +1197,7 @@ test_remove_contacts (EBookMetaBackend *meta_backend)
        uids[0] = "custom-3";
 
        success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) uids, &removed_uids, NULL, &error);
+               (const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (test_backend->load_count, ==, 0);
@@ -1255,9 +1257,9 @@ test_get_contact (EBookMetaBackend *meta_backend)
        book_cache = e_book_meta_backend_ref_cache (meta_backend);
        g_assert_nonnull (book_cache);
 
-       e_book_cache_remove_contact (book_cache, "custom-5", E_CACHE_IS_ONLINE, NULL, &error);
+       e_book_cache_remove_contact (book_cache, "custom-5", 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
-       e_book_cache_remove_contact (book_cache, "custom-6", E_CACHE_IS_ONLINE, NULL, &error);
+       e_book_cache_remove_contact (book_cache, "custom-6", 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
 
        /* Non-existing */
@@ -1294,7 +1296,7 @@ test_get_contact (EBookMetaBackend *meta_backend)
        g_assert (e_cache_contains (E_CACHE (book_cache), "custom-5", E_CACHE_EXCLUDE_DELETED));
 
        /* Remove it from the cache, thus it's loaded from the "server" on demand */
-       e_book_cache_remove_contact (book_cache, "custom-5", E_CACHE_IS_ONLINE, NULL, &error);
+       e_book_cache_remove_contact (book_cache, "custom-5", 0, E_CACHE_IS_ONLINE, NULL, &error);
        g_assert_no_error (error);
 
        g_assert_cmpint (test_backend->connect_count, ==, 1);
@@ -1587,7 +1589,7 @@ test_cursor (EBookMetaBackend *meta_backend)
        /* Create */
        vcards[0] = tcu_new_vcard_from_test_case ("custom-7");
        success = backend_sync_class->create_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) vcards, &contacts, NULL, &error);
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (g_slist_length (contacts), ==, 1);
@@ -1601,7 +1603,7 @@ test_cursor (EBookMetaBackend *meta_backend)
        /* Modify */
        vcards[0] = ebmb_test_modify_case ("custom-2");
        success = backend_sync_class->modify_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) vcards, &contacts, NULL, &error);
+               (const gchar * const *) vcards, E_BOOK_OPERATION_FLAG_NONE, &contacts, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (g_slist_length (contacts), ==, 1);
@@ -1615,7 +1617,7 @@ test_cursor (EBookMetaBackend *meta_backend)
        /* Remove */
        uids[0] = "custom-3";
        success = backend_sync_class->remove_contacts_sync (E_BOOK_BACKEND_SYNC (meta_backend),
-               (const gchar * const *) uids, &removed_uids, NULL, &error);
+               (const gchar * const *) uids, E_BOOK_OPERATION_FLAG_NONE, &removed_uids, NULL, &error);
        g_assert_no_error (error);
        g_assert (success);
        g_assert_cmpint (g_slist_length (removed_uids), ==, 1);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]