gboolean add_contact_from_test_case_verify (EBookClient *book_client, const gchar *case_name, EContact **contact) { gchar *vcard; EContact *contact_orig; EContact *contact_final; gchar *uid; GError *error = NULL; 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)) g_error ("add contact sync: %s", error->message); e_contact_set (contact_orig, E_CONTACT_UID, uid); if (!e_book_client_get_contact_sync (book_client, uid, &contact_final, NULL, &error)) g_error ("get contact sync: %s", error->message); /* verify the contact was added "successfully" (not thorough) */ g_assert (contacts_are_equal_shallow (contact_orig, contact_final)); if (contact) *contact = contact_final; else g_object_unref (contact_final); g_object_unref (contact_orig); g_free (uid); return TRUE; }
static void e_book_backend_vcf_modify_contact (EBookBackendSync *backend, EDataBook *book, guint32 opid, const gchar *vcard, EContact **contact, GError **perror) { EBookBackendVCF *bvcf = E_BOOK_BACKEND_VCF (backend); GList *elem; const gchar *id; /* create a new ecard from the request data */ *contact = e_contact_new_from_vcard (vcard); id = e_contact_get_const (*contact, E_CONTACT_UID); g_mutex_lock (bvcf->priv->mutex); elem = g_hash_table_lookup (bvcf->priv->contacts, id); if (!elem) { g_mutex_unlock (bvcf->priv->mutex); g_propagate_error (perror, EDB_ERROR (CONTACT_NOT_FOUND)); return; } g_free (elem->data); elem->data = g_strdup (vcard); bvcf->priv->dirty = TRUE; if (!bvcf->priv->flush_timeout_tag) bvcf->priv->flush_timeout_tag = g_timeout_add (FILE_FLUSH_TIMEOUT, vcf_flush_file, bvcf); g_mutex_unlock (bvcf->priv->mutex); }
static gboolean test_bulk_add_remove (EBookClient *client, const gchar *vcard_str, gint batch_size) { gint i; GSList *contacts = NULL; GSList *added_uids = NULL; GSList *book_uids = NULL; EBookQuery *query = NULL; gchar *sexp = NULL; const GSList *l; query = e_book_query_any_field_contains (""); sexp = e_book_query_to_string (query); e_book_query_unref (query); for (i = 0; i < batch_size; ++i) { EContact *contact = e_contact_new_from_vcard (vcard_str); contacts = g_slist_append (contacts, contact); } g_print (" * Bulk addition of %d contacts...\n", batch_size); /* Bulk addition */ g_return_val_if_fail (e_book_client_add_contacts_sync (client, contacts, &added_uids, NULL, NULL), FALSE); g_return_val_if_fail (added_uids != NULL, FALSE); g_return_val_if_fail (added_uids->data != NULL, FALSE); g_return_val_if_fail (g_slist_length (added_uids) == batch_size, FALSE); /* Make sure the uids are in the address book */ g_return_val_if_fail (e_book_client_get_contacts_uids_sync (client, sexp, &book_uids, NULL, NULL), FALSE); for (l = added_uids; l != NULL; l = l->next) { g_return_val_if_fail (check_string_in_slist (book_uids, (const gchar *) l->data), FALSE); } g_slist_free_full (book_uids, g_free); g_print (" * Bulk removal of %d contacts...\n", batch_size); /* Bulk removal */ g_return_val_if_fail (e_book_client_remove_contacts_sync (client, added_uids, NULL, NULL), FALSE); /* Make sure the uids are no longer in the address book */ book_uids = NULL; g_return_val_if_fail (e_book_client_get_contacts_uids_sync (client, sexp, &book_uids, NULL, NULL), FALSE); for (l = added_uids; l != NULL; l = l->next) { g_return_val_if_fail (!check_string_in_slist (book_uids, (const gchar *) l->data), FALSE); } g_slist_free_full (book_uids, g_free); g_free (sexp); g_slist_free_full (added_uids, g_free); g_slist_free_full (contacts, g_object_unref); return TRUE; }
gint main (gint argc, gchar **argv) { EBook *book; EContact *contact; GList *changes; GError *error = NULL; EBookChange *change; gchar *uri; g_type_init (); book = ebook_test_utils_book_new_temp (&uri); ebook_test_utils_book_open (book, FALSE); /* get an initial change set */ if (!e_book_get_changes (book, "changeidtest", &changes, &error)) { printf ("failed to get changes: %s\n", error->message); exit (0); } /* make a change to the book */ contact = e_contact_new_from_vcard (NEW_VCARD); ebook_test_utils_book_add_contact (book, contact); /* get another change set */ if (!e_book_get_changes (book, "changeidtest", &changes, &error)) { printf ("failed to get second set of changes: %s\n", error->message); exit (0); } /* make sure that 1 change has occurred */ if (g_list_length (changes) != 1) { printf ("got back %d changes, was expecting 1\n", g_list_length (changes)); exit (0); } change = changes->data; if (change->change_type != E_BOOK_CHANGE_CARD_ADDED) { printf ("was expecting a CARD_ADDED change, but didn't get it.\n"); exit (0); } printf ("got changed vcard back: %s\n", (gchar *) e_contact_get_const (change->contact, E_CONTACT_UID)); e_book_free_change_list (changes); g_object_unref (contact); return 0; }
/** * e_book_backend_db_cache_get_contacts: * @db: DB Handle * @query: an s-expression * * Returns a list of #EContact elements from @cache matching @query. * When done with the list, the caller must unref the contacts and * free the list. * * Returns: A #GList of pointers to #EContact. **/ GList * e_book_backend_db_cache_get_contacts (DB *db, const gchar *query) { DBC *dbc; DBT uid_dbt, vcard_dbt; gint db_error; GList *list = NULL; EBookBackendSExp *sexp = NULL; EContact *contact; if (query) { sexp = e_book_backend_sexp_new (query); if (!sexp) return NULL; } db_error = db->cursor (db, NULL, &dbc, 0); if (db_error != 0) { g_warning ("db->cursor failed with %d", db_error); if (sexp) g_object_unref (sexp); return NULL; } memset (&vcard_dbt, 0 , sizeof (vcard_dbt)); memset (&uid_dbt, 0, sizeof (uid_dbt)); db_error = dbc->c_get (dbc, &uid_dbt, &vcard_dbt, DB_FIRST); while (db_error == 0) { if (vcard_dbt.data && !strncmp (vcard_dbt.data, "BEGIN:VCARD", 11)) { contact = e_contact_new_from_vcard (vcard_dbt.data); if (!sexp || e_book_backend_sexp_match_contact (sexp, contact)) list = g_list_prepend (list, contact); else g_object_unref (contact); } db_error = dbc->c_get (dbc, &uid_dbt, &vcard_dbt, DB_NEXT); } db_error = dbc->c_close (dbc); if (db_error != 0) g_warning ("db->c_close failed with %d", db_error); if (sexp) g_object_unref (sexp); return g_list_reverse (list); }
static EBookBackendSyncStatus e_book_backend_scalix_create_contact (EBookBackendSync * backend, EDataBook * book, guint32 opid, const char *vcard, EContact ** contact) { EBookBackendScalix *bs; EBookBackendScalixPrivate *priv; ScalixObject *object; EContact *econtact; gboolean res; char *uid; bs = E_BOOK_BACKEND_SCALIX (backend); priv = E_BOOK_BACKEND_SCALIX_GET_PRIVATE (bs); econtact = e_contact_new_from_vcard (vcard); gboolean is_list = GPOINTER_TO_INT (e_contact_get (econtact, E_CONTACT_IS_LIST)); if (is_list == TRUE) { object = SCALIX_OBJECT (scalix_contact_list_new (vcard)); } else { object = SCALIX_OBJECT (scalix_contact_new (vcard)); } if (object == NULL) { return GNOME_Evolution_Addressbook_OtherError; } res = scalix_container_add_object (priv->container, object); if (res == FALSE) { g_object_unref (object); return GNOME_Evolution_Addressbook_OtherError; } g_object_get (object, "uid", &uid, NULL); g_object_unref (object); object = scalix_container_refresh_object (priv->container, uid); if (object == NULL) { return GNOME_Evolution_Addressbook_OtherError; } *contact = E_CONTACT (object); return GNOME_Evolution_Addressbook_Success; }
static void add_contacts (EwsBookBackendSqliteDB *ebsdb) { GSList *contacts = NULL; EContact *con; g_print ("Adding contact \n"); op = "add contact"; con = e_contact_new_from_vcard (vcard_str); contacts = g_slist_append (contacts, con); ews_book_backend_sqlitedb_add_contacts (ebsdb, folderid, contacts, FALSE, &error); g_object_unref (con); }
/* * Helper function to load a contact from a vcard file. */ static EContact * contact_from_file (const gchar *vcard_file) { EContact *contact; GError *error; gchar *vcard = NULL; if (!g_file_get_contents (vcard_file, &vcard, NULL, &error)) g_error ("Failed to load vcard: %s", error->message); contact = e_contact_new_from_vcard (vcard); g_free (vcard); return contact; }
/** * e_book_backend_sexp_match_vcard: * @sexp: an #EBookBackendSExp * @vcard: a VCard string * * Checks if @vcard matches @sexp. * * Returns: %TRUE if the VCard matches, %FALSE otherwise. **/ gboolean e_book_backend_sexp_match_vcard (EBookBackendSExp *sexp, const gchar *vcard) { EContact *contact; gboolean retval; contact = e_contact_new_from_vcard (vcard); retval = e_book_backend_sexp_match_contact (sexp, contact); g_object_unref (contact); return retval; }
static void insert_contact (EBookBackendVCF *vcf, gchar *vcard) { EContact *contact = e_contact_new_from_vcard (vcard); gchar *id; id = e_contact_get (contact, E_CONTACT_UID); if (id) { gchar *vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); vcf->priv->contact_list = g_list_prepend (vcf->priv->contact_list, vcard); g_hash_table_insert (vcf->priv->contacts, id, vcf->priv->contact_list); } }
static EBookBackendSyncStatus e_book_backend_scalix_modify_contact (EBookBackendSync * backend, EDataBook * book, guint32 opid, const char *vcard, EContact ** contact) { EBookBackendScalix *bs; EBookBackendScalixPrivate *priv; ScalixObject *object; gboolean res; EContact *econtact; bs = E_BOOK_BACKEND_SCALIX (backend); priv = E_BOOK_BACKEND_SCALIX_GET_PRIVATE (bs); econtact = e_contact_new_from_vcard (vcard); gboolean is_list = GPOINTER_TO_INT (e_contact_get (econtact, E_CONTACT_IS_LIST)); if (is_list == TRUE) { object = SCALIX_OBJECT (scalix_contact_list_new (vcard)); } else { object = SCALIX_OBJECT (scalix_contact_new (vcard)); } if (object == NULL) { return GNOME_Evolution_Addressbook_OtherError; } /* REVIEW: do we have to ask the cache for the object here first? * (to "save" the mapi stuff?) */ res = scalix_container_update_object (priv->container, object, TRUE); if (res == FALSE) { g_object_unref (object); return GNOME_Evolution_Addressbook_OtherError; } *contact = E_CONTACT (object); return GNOME_Evolution_Addressbook_Success; }
static gpointer book_view_thread (gpointer data) { EDataBookView *book_view = data; VCFBackendSearchClosure *closure = get_closure (book_view); const gchar *query; GList *l; /* ref the book view because it'll be removed and unrefed when/if it's stopped */ e_data_book_view_ref (book_view); query = e_data_book_view_get_card_query (book_view); if ( !strcmp (query, "(contains \"x-evolution-any-field\" \"\")")) e_data_book_view_notify_status_message (book_view, _("Loading...")); else e_data_book_view_notify_status_message (book_view, _("Searching...")); d(printf ("signalling parent thread\n")); e_flag_set (closure->running); for (l = closure->bvcf->priv->contact_list; l; l = l->next) { gchar *vcard_string = l->data; EContact *contact = e_contact_new_from_vcard (vcard_string); e_data_book_view_notify_update (closure->view, contact); g_object_unref (contact); if (!e_flag_is_set (closure->running)) break; } if (e_flag_is_set (closure->running)) e_data_book_view_notify_complete (closure->view, NULL /* Success */); /* unref the book view */ e_data_book_view_unref (book_view); d(printf ("finished initial population of book view\n")); return NULL; }
static EContact * do_create (EBookBackendVCF *bvcf, const gchar *vcard_req, gboolean dirty_the_file) { gchar *id; EContact *contact; gchar *vcard; const gchar *rev; /* at the very least we need the unique_id generation to be protected by the lock, even if the actual vcard parsing isn't. */ g_mutex_lock (bvcf->priv->mutex); id = e_book_backend_vcf_create_unique_id (); contact = e_contact_new_from_vcard (vcard_req); e_contact_set (contact, E_CONTACT_UID, id); g_free (id); rev = e_contact_get_const (contact, E_CONTACT_REV); if (!(rev && *rev)) set_revision (contact); vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); insert_contact (bvcf, vcard); if (dirty_the_file) { bvcf->priv->dirty = TRUE; if (!bvcf->priv->flush_timeout_tag) bvcf->priv->flush_timeout_tag = g_timeout_add (FILE_FLUSH_TIMEOUT, vcf_flush_file, bvcf); } g_mutex_unlock (bvcf->priv->mutex); return contact; }
/** * e_book_backend_db_cache_get_contact: * @db: DB Handle * @uid: a unique contact ID * * Get a cached contact. Note that the returned #EContact will be * newly created, and must be unreffed by the caller when no longer * needed. * * Returns: A cached #EContact, or %NULL if @uid is not cached. **/ EContact * e_book_backend_db_cache_get_contact (DB *db, const gchar *uid) { DBT uid_dbt, vcard_dbt; gint db_error; EContact *contact = NULL; g_return_val_if_fail (uid != NULL, NULL); string_to_dbt (uid, &uid_dbt); memset (&vcard_dbt, 0 , sizeof (vcard_dbt)); vcard_dbt.flags = DB_DBT_MALLOC; db_error = db->get (db, NULL, &uid_dbt, &vcard_dbt,0); if (db_error != 0) { g_warning ("db->get failed with %d", db_error); return NULL; } contact = e_contact_new_from_vcard ((const gchar *)vcard_dbt.data); g_free (vcard_dbt.data); return contact; }
/** * e_data_book_view_notify_update_vcard: * @book_view: an #EDataBookView * @vcard: a plain vCard * * Notify listeners that @vcard has changed. This can * trigger an add, change or removal event depending on * whether the change causes the contact to start matching, * no longer match, or stay matching the query specified * by @book_view. This method should be preferred over * #e_data_book_view_notify_update when the native * representation of a contact is a vCard. **/ void e_data_book_view_notify_update_vcard (EDataBookView *book_view, gchar *vcard) { EDataBookViewPrivate *priv = book_view->priv; gboolean currently_in_view, want_in_view; const gchar *id; EContact *contact; if (!priv->running) { g_free (vcard); return; } g_mutex_lock (priv->pending_mutex); contact = e_contact_new_from_vcard (vcard); id = e_contact_get_const (contact, E_CONTACT_UID); currently_in_view = id_is_in_view (book_view, id); want_in_view = e_book_backend_sexp_match_contact (priv->card_sexp, contact); if (want_in_view) { if (currently_in_view) notify_change (book_view, vcard); else notify_add (book_view, id, vcard); } else { if (currently_in_view) notify_remove (book_view, id); } /* Do this last so that id is still valid when notify_ is called */ g_object_unref (contact); g_free (vcard); g_mutex_unlock (priv->pending_mutex); }
static gboolean test_econtact (const gchar *vcard_str) { EContact *c1, *c2; gchar *str; /* do not parse */ c1 = e_contact_new_from_vcard (vcard_str); str = e_vcard_to_string (E_VCARD (c1), EVC_FORMAT_VCARD_30); g_return_val_if_fail (str != NULL, FALSE); g_return_val_if_fail (g_ascii_strcasecmp (str, vcard_str) == 0, FALSE); g_return_val_if_fail (e_vcard_is_parsed (E_VCARD (c1)) == FALSE, FALSE); g_free (str); /* parse */ e_contact_get_const (c1, E_CONTACT_UID); g_return_val_if_fail (e_vcard_is_parsed (E_VCARD (c1)) == TRUE, FALSE); str = e_vcard_to_string (E_VCARD (c1), EVC_FORMAT_VCARD_30); g_return_val_if_fail (str != NULL, FALSE); g_return_val_if_fail (g_ascii_strcasecmp (str, vcard_str) == 0, FALSE); g_free (str); /* parse */ e_contact_get_const (c1, E_CONTACT_FULL_NAME); str = e_vcard_to_string (E_VCARD (c1), EVC_FORMAT_VCARD_30); g_return_val_if_fail (str != NULL, FALSE); g_return_val_if_fail (g_ascii_strcasecmp (str, vcard_str) == 0, FALSE); g_free (str); g_object_unref (c1); /* not parsed again */ c1 = e_contact_new_from_vcard (vcard_str); e_contact_set (c1, E_CONTACT_UID, "other-uid"); g_return_val_if_fail (e_vcard_is_parsed (E_VCARD (c1)) == FALSE, FALSE); g_return_val_if_fail (compare_single_value (E_VCARD (c1), "UID", "other-uid"), FALSE); g_return_val_if_fail (e_vcard_is_parsed (E_VCARD (c1)) == FALSE, FALSE); str = e_vcard_to_string (E_VCARD (c1), EVC_FORMAT_VCARD_30); c2 = e_contact_new_from_vcard (str); g_return_val_if_fail (e_vcard_is_parsed (E_VCARD (c2)) == FALSE, FALSE); g_free (str); g_return_val_if_fail (compare_single_value (E_VCARD (c2), "UID", "other-uid"), FALSE); g_object_unref (c2); /* parse */ e_contact_get_const (c1, E_CONTACT_FULL_NAME); g_return_val_if_fail (e_vcard_is_parsed (E_VCARD (c1)) == TRUE, FALSE); g_return_val_if_fail (compare_single_value (E_VCARD (c1), "UID", "other-uid"), FALSE); str = e_vcard_to_string (E_VCARD (c1), EVC_FORMAT_VCARD_30); c2 = e_contact_new_from_vcard (str); g_free (str); g_return_val_if_fail (compare_single_value (E_VCARD (c2), "UID", "other-uid"), FALSE); g_return_val_if_fail (has_only_one (E_VCARD (c1), "UID"), FALSE); g_return_val_if_fail (has_only_one (E_VCARD (c2), "UID"), FALSE); g_object_unref (c2); g_object_unref (c1); /* do not parse */ c1 = e_contact_new_from_vcard_with_uid (vcard_str, "other-uid"); g_return_val_if_fail (e_vcard_is_parsed (E_VCARD (c1)) == FALSE, FALSE); g_return_val_if_fail (compare_single_value (E_VCARD (c1), "UID", "other-uid"), FALSE); g_return_val_if_fail (e_vcard_is_parsed (E_VCARD (c1)) == FALSE, FALSE); str = e_vcard_to_string (E_VCARD (c1), EVC_FORMAT_VCARD_30); c2 = e_contact_new_from_vcard (str); g_free (str); g_return_val_if_fail (compare_single_value (E_VCARD (c2), "UID", "other-uid"), FALSE); g_object_unref (c2); /* parse */ e_contact_get_const (c1, E_CONTACT_FULL_NAME); g_return_val_if_fail (compare_single_value (E_VCARD (c1), "UID", "other-uid"), FALSE); g_return_val_if_fail (e_vcard_is_parsed (E_VCARD (c1)) == TRUE, FALSE); str = e_vcard_to_string (E_VCARD (c1), EVC_FORMAT_VCARD_30); c2 = e_contact_new_from_vcard (str); g_free (str); g_return_val_if_fail (compare_single_value (E_VCARD (c2), "UID", "other-uid"), FALSE); g_return_val_if_fail (has_only_one (E_VCARD (c1), "UID"), FALSE); g_return_val_if_fail (has_only_one (E_VCARD (c2), "UID"), FALSE); g_object_unref (c2); g_object_unref (c1); return TRUE; }
static void e_book_backend_webdav_modify_contacts (EBookBackend *backend, EDataBook *book, guint32 opid, GCancellable *cancellable, const GSList *vcards) { EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (backend); EBookBackendWebdavPrivate *priv = webdav->priv; EContact *contact; GSList modified_contacts = {NULL,}; const gchar *uid; const gchar *etag; guint status; gchar *status_reason = NULL; const gchar *vcard = vcards->data; if (!e_backend_get_online (E_BACKEND (backend))) { e_data_book_respond_create_contacts ( book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL); return; } /* We make the assumption that the vCard list we're passed is always exactly one element long, since we haven't specified "bulk-modifies" * in our static capability list. This is because there is no clean way to roll back changes in case of an error. */ if (vcards->next != NULL) { e_data_book_respond_modify_contacts ( book, opid, EDB_ERROR_EX ( NOT_SUPPORTED, _("The backend does not support bulk modifications")), NULL); return; } /* modify contact */ contact = e_contact_new_from_vcard (vcard); status = upload_contact (webdav, contact, &status_reason, cancellable); if (status != 201 && status != 204) { g_object_unref (contact); if (status == 401 || status == 407) { e_data_book_respond_modify_contacts (book, opid, webdav_handle_auth_request (webdav), NULL); g_free (status_reason); return; } /* data changed on server while we were editing */ if (status == 412) { /* too bad no special error code in evolution for this... */ e_data_book_respond_modify_contacts (book, opid, e_data_book_create_error_fmt ( E_DATA_BOOK_STATUS_OTHER_ERROR, _("Contact on server changed -> not modifying")), NULL); g_free (status_reason); return; } e_data_book_respond_modify_contacts (book, opid, e_data_book_create_error_fmt ( E_DATA_BOOK_STATUS_OTHER_ERROR, _("Modify contact failed with HTTP status: %d (%s)"), status, status_reason), NULL); g_free (status_reason); return; } g_free (status_reason); uid = e_contact_get_const (contact, E_CONTACT_UID); g_mutex_lock (&priv->cache_lock); e_book_backend_cache_remove_contact (priv->cache, uid); etag = e_contact_get_const (contact, E_CONTACT_REV); /* PUT request didn't return an etag? try downloading to get one */ if (etag == NULL || (etag[0] == 'W' && etag[1] == '/')) { EContact *new_contact; g_warning ("Server didn't return etag for modified address resource"); new_contact = download_contact (webdav, uid, cancellable); if (new_contact != NULL) { contact = new_contact; } } e_book_backend_cache_add_contact (priv->cache, contact); g_mutex_unlock (&priv->cache_lock); modified_contacts.data = contact; e_data_book_respond_modify_contacts (book, opid, EDB_ERROR (SUCCESS), &modified_contacts); g_object_unref (contact); }
GSList * eab_contact_list_from_string (const gchar *str) { GSList *contacts = NULL; GString *gstr = g_string_new (NULL); gchar *str_stripped; gchar *p = (gchar *) str; gchar *q; if (!p) return NULL; if (!strncmp (p, "Book: ", 6)) { p = strchr (p, '\n'); if (!p) { g_warning (G_STRLOC ": Got book but no newline!"); return NULL; } p++; } while (*p) { if (*p != '\r') g_string_append_c (gstr, *p); p++; } p = str_stripped = g_string_free (gstr, FALSE); /* Note: The vCard standard says * * vcard = "BEGIN" [ws] ":" [ws] "VCARD" [ws] 1*CRLF * items *CRLF "END" [ws] ":" [ws] "VCARD" * * which means we can have whitespace (e.g. "BEGIN : VCARD"). So we're not being * fully compliant here, although I'm not sure it matters. The ideal solution * would be to have a vcard parsing function that returned the end of the vcard * parsed. Arguably, contact list parsing should all be in libebook's e-vcard.c, * where we can do proper parsing and validation without code duplication. */ for (p = eab_strstrcase (p, "BEGIN:VCARD"); p; p = eab_strstrcase (q, "\nBEGIN:VCARD")) { gchar *card_str; if (*p == '\n') p++; for (q = eab_strstrcase (p, "END:VCARD"); q; q = eab_strstrcase (q, "END:VCARD")) { gchar *temp; q += 9; temp = q; if (*temp) temp += strspn (temp, "\r\n\t "); if (*temp == '\0' || !g_ascii_strncasecmp (temp, "BEGIN:VCARD", 11)) break; /* Found the outer END:VCARD */ } if (!q) break; card_str = g_strndup (p, q - p); contacts = g_slist_prepend (contacts, e_contact_new_from_vcard (card_str)); g_free (card_str); } g_free (str_stripped); return g_slist_reverse (contacts); }
gint main (gint argc, gchar **argv) { EBookClient *book_client; GError *error = NULL; EContact *contact; gchar *vcard; main_initialize (); /* * Setup */ book_client = new_temp_client (NULL); g_return_val_if_fail (book_client != NULL, 1); if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) { report_error ("client open sync", &error); g_object_unref (book_client); return 1; } /* * Sync version */ if (!add_contact_from_test_case_verify (book_client, "simple-1", &contact)) { g_object_unref (book_client); return 1; } g_object_unref (contact); if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) { report_error ("client remove sync", &error); g_object_unref (book_client); return 1; } g_object_unref (book_client); /* * Async version */ book_client = new_temp_client (NULL); g_return_val_if_fail (book_client != NULL, 1); if (!e_client_open_sync (E_CLIENT (book_client), FALSE, NULL, &error)) { report_error ("client open sync", &error); g_object_unref (book_client); return 1; } vcard = new_vcard_from_test_case ("simple-1"); contact = e_contact_new_from_vcard (vcard); g_free (vcard); e_book_client_add_contact (book_client, contact, NULL, add_contact_cb, NULL); g_object_unref (contact); start_main_loop (NULL, NULL); if (!e_client_remove_sync (E_CLIENT (book_client), NULL, &error)) { report_error ("client remove sync", &error); g_object_unref (book_client); return 1; } g_object_unref (book_client); return get_main_loop_stop_result (); }
static void ebbm_contacts_modify_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *vcards, GSList **modified_contacts, GError **error) { EBookBackendMAPIContacts *ebmac; EBookBackendMAPIContactsPrivate *priv; EMapiConnection *conn; EMapiCreateitemData mcd; EContact *contact; GError *mapi_error = NULL; mapi_id_t mid; e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG); e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma), E_DATA_BOOK_STATUS_INVALID_ARG); e_mapi_return_data_book_error_if_fail (vcards != NULL, E_DATA_BOOK_STATUS_INVALID_ARG); e_mapi_return_data_book_error_if_fail (modified_contacts != NULL, E_DATA_BOOK_STATUS_INVALID_ARG); ebmac = E_BOOK_BACKEND_MAPI_CONTACTS (ebma); e_mapi_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG); priv = ebmac->priv; e_mapi_return_data_book_error_if_fail (priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG); if (vcards->next != NULL) { g_propagate_error (error, EDB_ERROR_EX (NOT_SUPPORTED, _("The backend does not support bulk modifications"))); return; } e_book_backend_mapi_lock_connection (ebma); conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error); if (!conn) { e_book_backend_mapi_unlock_connection (ebma); if (!mapi_error) g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE)); else mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL); g_clear_error (&mapi_error); return; } contact = e_contact_new_from_vcard (vcards->data); if (!contact) { g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE)); e_book_backend_mapi_unlock_connection (ebma); return; } e_book_backend_mapi_get_db (ebma, &mcd.db); mcd.contact = contact; if (e_mapi_util_mapi_id_from_string (e_contact_get_const (contact, E_CONTACT_UID), &mid)) { mapi_object_t obj_folder; gboolean status; status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error); if (status) { status = e_mapi_connection_modify_object (conn, &obj_folder, mid, ebbm_contact_to_object, &mcd, cancellable, &mapi_error); e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error); } e_book_backend_mapi_maybe_disconnect (ebma, mapi_error); if (!status) { mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to modify item on a server")); if (mapi_error) g_error_free (mapi_error); g_object_unref (contact); } else { *modified_contacts = g_slist_append (NULL, contact); } } else { g_debug ("%s: Failed to decode MID from '%s'", G_STRFUNC, (const gchar *) e_contact_get_const (contact, E_CONTACT_UID)); } e_book_backend_mapi_unlock_connection (ebma); }
static gboolean test_bulk_modify (EBookClient *client, const gchar *vcard_str, gint batch_size) { gint i; EContact *contact; GSList *contacts = NULL; GSList *added_uids = NULL; const GSList *l, *ll; const gchar *old_first_name = "xyz mix"; const gchar *new_first_name = "abc mix"; for (i = 0; i < batch_size; ++i) { EContact *contact = e_contact_new_from_vcard (vcard_str); contacts = g_slist_append (contacts, contact); } g_print (" * Bulk addition of %d contacts...\n", batch_size); /* Bulk addition */ g_return_val_if_fail (e_book_client_add_contacts_sync (client, contacts, &added_uids, NULL, NULL), FALSE); g_return_val_if_fail (added_uids != NULL, FALSE); g_return_val_if_fail (added_uids->data != NULL, FALSE); g_return_val_if_fail (g_slist_length (added_uids) == batch_size, FALSE); g_print (" * Bulk modification of %d contacts...\n", batch_size); ll = added_uids; for (l = contacts; l != NULL; l = l->next) { const gchar * uid = ll->data; contact = E_CONTACT (l->data); /* Set contact UID */ e_contact_set (contact, E_CONTACT_UID, uid); /* Change contact first name */ e_contact_set (contact, E_CONTACT_GIVEN_NAME, new_first_name); ll = ll->next; } g_return_val_if_fail (e_book_client_modify_contacts_sync (client, contacts, NULL, NULL), FALSE); /* Validate */ for (ll = added_uids; ll != NULL; ll = ll->next) { const gchar *first_name; const gchar *uid = ll->data; contact = NULL; g_return_val_if_fail (e_book_client_get_contact_sync (client, uid, &contact, NULL, NULL), FALSE); /* Check contact first name */ first_name = e_contact_get_const (contact, E_CONTACT_GIVEN_NAME); g_return_val_if_fail (g_strcmp0 (first_name, new_first_name) == 0, FALSE); g_object_unref (contact); } /* Test failure case */ g_print (" * Bulk modification of %d contacts (expected failure)...\n", batch_size); contact = E_CONTACT (g_slist_nth_data (contacts, g_slist_length (contacts) - 2)); g_return_val_if_fail (e_book_client_remove_contact_sync (client, contact, NULL, NULL), FALSE); for (l = contacts; l != NULL; l = l->next) { contact = E_CONTACT (l->data); /* Change contact first name */ e_contact_set (contact, E_CONTACT_GIVEN_NAME, old_first_name); } g_return_val_if_fail (!e_book_client_modify_contacts_sync (client, contacts, NULL, NULL), FALSE); /* Remove the UID that no longer exists from the added_uid list */ added_uids = g_slist_delete_link (added_uids, g_slist_nth (added_uids, g_slist_length (added_uids) - 2)); /* Validate */ for (ll = added_uids; ll != NULL; ll = ll->next) { const gchar *first_name; const gchar *uid = ll->data; contact = NULL; g_return_val_if_fail (e_book_client_get_contact_sync (client, uid, &contact, NULL, NULL), FALSE); /* Check contact first name */ first_name = e_contact_get_const (contact, E_CONTACT_GIVEN_NAME); g_return_val_if_fail (g_strcmp0 (first_name, new_first_name) == 0, FALSE); g_object_unref (contact); } g_print (" * Bulk removal of %d contacts...\n", batch_size); /* Bulk removal */ g_return_val_if_fail (e_book_client_remove_contacts_sync (client, added_uids, NULL, NULL), FALSE); g_slist_free_full (added_uids, g_free); g_slist_free_full (contacts, g_object_unref); return TRUE; }
static void ebbm_contacts_create_contacts (EBookBackendMAPI *ebma, GCancellable *cancellable, const GSList *vcards, GSList **added_contacts, GError **error) { EBookBackendMAPIContacts *ebmac; EBookBackendMAPIContactsPrivate *priv; EMapiConnection *conn; EMapiCreateitemData mcd; GError *mapi_error = NULL; mapi_id_t mid = 0; mapi_object_t obj_folder; gboolean status; gchar *id; EContact *contact; e_mapi_return_data_book_error_if_fail (ebma != NULL, E_DATA_BOOK_STATUS_INVALID_ARG); e_mapi_return_data_book_error_if_fail (E_IS_BOOK_BACKEND_MAPI_CONTACTS (ebma), E_DATA_BOOK_STATUS_INVALID_ARG); e_mapi_return_data_book_error_if_fail (vcards != NULL, E_DATA_BOOK_STATUS_INVALID_ARG); e_mapi_return_data_book_error_if_fail (added_contacts != NULL, E_DATA_BOOK_STATUS_INVALID_ARG); ebmac = E_BOOK_BACKEND_MAPI_CONTACTS (ebma); e_mapi_return_data_book_error_if_fail (ebmac != NULL, E_DATA_BOOK_STATUS_INVALID_ARG); priv = ebmac->priv; e_mapi_return_data_book_error_if_fail (priv != NULL, E_DATA_BOOK_STATUS_INVALID_ARG); if (vcards->next) { g_propagate_error (error, EDB_ERROR_EX (NOT_SUPPORTED, _("The backend does not support bulk additions"))); return; } e_book_backend_mapi_lock_connection (ebma); conn = e_book_backend_mapi_get_connection (ebma, cancellable, &mapi_error); if (!conn) { e_book_backend_mapi_unlock_connection (ebma); if (!mapi_error) g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE)); else mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE, NULL); g_clear_error (&mapi_error); return; } contact = e_contact_new_from_vcard (vcards->data); if (!contact) { g_propagate_error (error, EDB_ERROR (REPOSITORY_OFFLINE)); e_book_backend_mapi_unlock_connection (ebma); return; } e_book_backend_mapi_get_db (ebma, &mcd.db); mcd.contact = contact; status = ebbm_contacts_open_folder (ebmac, conn, &obj_folder, cancellable, &mapi_error); if (status) { e_mapi_connection_create_object (conn, &obj_folder, E_MAPI_CREATE_FLAG_NONE, ebbm_contact_to_object, &mcd, &mid, cancellable, &mapi_error); e_mapi_connection_close_folder (conn, &obj_folder, cancellable, &mapi_error); } e_book_backend_mapi_maybe_disconnect (ebma, mapi_error); e_book_backend_mapi_unlock_connection (ebma); if (!mid) { mapi_error_to_edb_error (error, mapi_error, E_DATA_BOOK_STATUS_OTHER_ERROR, _("Failed to create item on a server")); if (mapi_error) g_error_free (mapi_error); g_object_unref (contact); return; } id = e_mapi_util_mapi_id_to_string (mid); /* UID of the contact is nothing but the concatenated string of hex id of folder and the message.*/ e_contact_set (contact, E_CONTACT_UID, id); e_contact_set (contact, E_CONTACT_BOOK_UID, e_book_backend_mapi_get_book_uid (ebma)); g_free (id); *added_contacts = g_slist_append (NULL, contact); }