[evolution-data-server/openismus-work: 107/122] sqlitedb: Store E.164 param in vcards
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/openismus-work: 107/122] sqlitedb: Store E.164 param in vcards
- Date: Mon, 17 Dec 2012 09:12:17 +0000 (UTC)
commit 399e0a93b1ef5b464d807fe72c59508d2ec97769
Author: Mathias Hasselmann <mathias openismus com>
Date: Mon Dec 10 15:24:57 2012 +0100
sqlitedb: Store E.164 param in vcards
addressbook/libebook-contacts/e-vcard.h | 1 +
.../libedata-book/e-book-backend-sqlitedb.c | 88 ++++++-
tests/libebook/client/Makefile.am | 4 +
tests/libebook/client/client-test-utils.c | 19 ++
tests/libebook/client/client-test-utils.h | 1 +
.../client/test-client-change-country-code.c | 287 ++++++++++++++++++++
6 files changed, 395 insertions(+), 5 deletions(-)
---
diff --git a/addressbook/libebook-contacts/e-vcard.h b/addressbook/libebook-contacts/e-vcard.h
index 9a39c0f..6bf72c7 100644
--- a/addressbook/libebook-contacts/e-vcard.h
+++ b/addressbook/libebook-contacts/e-vcard.h
@@ -81,6 +81,7 @@ G_BEGIN_DECLS
#define EVC_X_DEST_EMAIL_NUM "X-EVOLUTION-DEST-EMAIL-NUM"
#define EVC_X_DEST_HTML_MAIL "X-EVOLUTION-DEST-HTML-MAIL"
#define EVC_X_DEST_SOURCE_UID "X-EVOLUTION-DEST-SOURCE-UID"
+#define EVC_X_E164 "X-EVOLUTION-E164"
#define EVC_X_FILE_AS "X-EVOLUTION-FILE-AS"
#define EVC_X_GADUGADU "X-GADUGADU"
#define EVC_X_GROUPWISE "X-GROUPWISE"
diff --git a/addressbook/libedata-book/e-book-backend-sqlitedb.c b/addressbook/libedata-book/e-book-backend-sqlitedb.c
index 4f4761d..3fddbf4 100644
--- a/addressbook/libedata-book/e-book-backend-sqlitedb.c
+++ b/addressbook/libedata-book/e-book-backend-sqlitedb.c
@@ -1481,6 +1481,77 @@ mprintf_phone (const gchar *normal,
return stmt;
}
+static EVCardAttributeParam *
+find_param (EVCardAttribute *attr,
+ const gchar *name)
+{
+ GList *l;
+
+ for (l = e_vcard_attribute_get_params (attr); l; l = l->next) {
+ EVCardAttributeParam *const param = l->data;
+
+ if (strcmp (e_vcard_attribute_param_get_name (param), name) == 0)
+ return param;
+ }
+
+ return NULL;
+}
+
+static gboolean
+update_e164_params (EVCard *vcard,
+ const gchar *country_code)
+{
+ const GList *attr_list = e_vcard_get_attributes (vcard);
+ gboolean modified = FALSE;
+
+ if (!e_phone_number_is_supported ())
+ return FALSE;
+
+ for (; attr_list; attr_list = attr_list->next) {
+ EVCardAttribute *const attr = attr_list->data;
+ char *normalized_number = NULL;
+ char *formatted_number = NULL;
+ EVCardAttributeParam *param = NULL;
+
+ /* Skip all attributes but phone numbers. */
+ if (strcmp (e_vcard_attribute_get_name (attr), EVC_TEL) != 0)
+ continue;
+
+ /* Compute normalized phone number. */
+ param = find_param (attr, EVC_X_E164);
+ formatted_number = e_vcard_attribute_get_value (attr);
+
+ if (formatted_number)
+ normalized_number = convert_phone (formatted_number, country_code);
+
+ /* Update the phone number attribute. */
+ if (normalized_number) {
+ if (param == NULL) {
+ param = e_vcard_attribute_param_new (EVC_X_E164);
+ e_vcard_attribute_add_param_with_value (attr, param, normalized_number);
+ modified = TRUE;
+ } else {
+ GList *values = e_vcard_attribute_param_get_values (param);
+
+ if (values == NULL
+ || g_strcmp0 (values->data, normalized_number)
+ || values->next) {
+ e_vcard_attribute_param_remove_values (param);
+ e_vcard_attribute_param_add_value (param, normalized_number);
+ modified = TRUE;
+ }
+ }
+
+ g_free (normalized_number);
+ } else if (param) {
+ e_vcard_attribute_remove_param (attr, EVC_X_E164);
+ modified = TRUE;
+ }
+ }
+
+ return modified;
+}
+
/* Add Contact (free the result with g_free() ) */
static gchar *
insert_stmt_from_contact (EBookBackendSqliteDB *ebsdb,
@@ -1548,8 +1619,14 @@ insert_stmt_from_contact (EBookBackendSqliteDB *ebsdb,
g_warn_if_reached ();
}
- vcard_str = store_vcard ? e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30) : NULL;
- str = sqlite3_mprintf (", %Q, %Q)", vcard_str, NULL);
+ if (store_vcard) {
+ update_e164_params (E_VCARD (contact), ebsdb->priv->country_code);
+ vcard_str = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
+ } else {
+ vcard_str = NULL;
+ }
+
+ str = sqlite3_mprintf (", %Q, %Q)", vcard_str, NULL);
g_string_append (string, str);
@@ -4012,8 +4089,8 @@ validate_county_code (EBookBackendSqliteDB *ebsdb,
if (vcard_data) {
g_print ("The country code has changed to \"%s\". "
- "Must rebuild phone number indexes for stored vCards.\n",
- ebsdb->priv->country_code);
+ "Must rebuild %s parameters and indexes for stored vCards.\n",
+ ebsdb->priv->country_code, EVC_X_E164);
}
for (l = vcard_data; success && l; l = l->next) {
@@ -4023,7 +4100,8 @@ validate_county_code (EBookBackendSqliteDB *ebsdb,
if (contact == NULL)
continue;
- success = insert_contact (ebsdb, contact, folderid, error);
+ if (update_e164_params (E_VCARD (contact), ebsdb->priv->country_code))
+ success = insert_contact (ebsdb, contact, folderid, error);
g_object_unref (contact);
}
diff --git a/tests/libebook/client/Makefile.am b/tests/libebook/client/Makefile.am
index 3972b86..b8f6a10 100644
--- a/tests/libebook/client/Makefile.am
+++ b/tests/libebook/client/Makefile.am
@@ -17,6 +17,7 @@ libclient_test_utils_la_CPPFLAGS = \
-DBACKENDDIR=\"$(ebook_backenddir)\" \
-DDATADIR=\"$(datadir)\" \
-DSRCDIR=\""$(abs_srcdir)"\" \
+ -DBUILDDIR=\""$(abs_topbuilddir)"\" \
$(EVOLUTION_ADDRESSBOOK_CFLAGS) \
$(CAMEL_CFLAGS) \
$(NULL)
@@ -48,6 +49,7 @@ TESTS = \
test-client-remove-contact-by-uid \
test-client-remove-contacts \
test-client-photo-is-uri \
+ test-client-change-country-code \
test-client-write-write \
test-client-stress-factory--serial \
test-client-stress-factory--fifo \
@@ -116,6 +118,8 @@ test_client_remove_contacts_LDADD=$(TEST_LIBS)
test_client_remove_contacts_CPPFLAGS=$(TEST_CPPFLAGS)
test_client_photo_is_uri_LDADD=$(TEST_LIBS)
test_client_photo_is_uri_CPPFLAGS=$(TEST_CPPFLAGS)
+test_client_change_country_code_LDADD=$(TEST_LIBS)
+test_client_change_country_code_CPPFLAGS=$(TEST_CPPFLAGS)
test_client_write_write_LDADD=$(TEST_LIBS) $(top_builddir)/addressbook/libedata-book/libedata-book-1.2.la
test_client_write_write_CPPFLAGS=$(TEST_CPPFLAGS)
test_client_stress_factory__fifo_LDADD=$(TEST_LIBS)
diff --git a/tests/libebook/client/client-test-utils.c b/tests/libebook/client/client-test-utils.c
index a67a94b..ba6fc42 100644
--- a/tests/libebook/client/client-test-utils.c
+++ b/tests/libebook/client/client-test-utils.c
@@ -22,6 +22,7 @@
* Tristan Van Berkom <tristanvb openismus com>
*/
+#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
@@ -104,6 +105,8 @@ main_initialize (void)
if (initialized)
return;
+ setlocale (LC_ALL, "en_US.UTF-8");
+
g_type_init ();
e_gdbus_templates_init_main_thread ();
@@ -244,6 +247,22 @@ stop_main_loop (gint stop_result)
g_main_loop_quit (loop);
}
+static gboolean
+sleep_in_main_loop_cb (gpointer data)
+{
+ g_main_loop_quit (data);
+ return FALSE;
+}
+
+void
+sleep_in_main_loop (guint msec)
+{
+ GMainLoop *loop = g_main_loop_new (NULL, FALSE);
+ g_timeout_add (msec, sleep_in_main_loop_cb, loop);
+ g_main_loop_run (loop);
+ g_main_loop_unref (loop);
+}
+
/* returns value used in stop_main_loop() */
gint
get_main_loop_stop_result (void)
diff --git a/tests/libebook/client/client-test-utils.h b/tests/libebook/client/client-test-utils.h
index 59d9632..0b201ee 100644
--- a/tests/libebook/client/client-test-utils.h
+++ b/tests/libebook/client/client-test-utils.h
@@ -37,6 +37,7 @@ void main_initialize (void);
void start_main_loop (GThreadFunc func, gpointer data);
void start_in_thread_with_main_loop (GThreadFunc func, gpointer data);
void start_in_idle_with_main_loop (GThreadFunc func, gpointer data);
+void sleep_in_main_loop (guint msec);
void stop_main_loop (gint stop_result);
gint get_main_loop_stop_result (void);
diff --git a/tests/libebook/client/test-client-change-country-code.c b/tests/libebook/client/test-client-change-country-code.c
new file mode 100644
index 0000000..b4c8c67
--- /dev/null
+++ b/tests/libebook/client/test-client-change-country-code.c
@@ -0,0 +1,287 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright Copyright (C) 2012 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Mathias Hasselmann <mathias openismus com>
+ */
+
+#include "config.h"
+
+#include <errno.h>
+#include <locale.h>
+#include <langinfo.h>
+
+#include <libebook/libebook.h>
+
+#include "client-test-utils.h"
+
+
+/* This forces the GType to be registered in a way that
+ * avoids a "statement with no effect" compiler warning.
+ * FIXME Use g_type_ensure() once we require GLib 2.34. */
+#define REGISTER_TYPE(type) \
+ (g_type_class_unref (g_type_class_ref (type)))
+
+static void
+setup_custom_summary (ESource *scratch)
+{
+ ESourceBackendSummarySetup *setup;
+
+ REGISTER_TYPE (E_TYPE_SOURCE_BACKEND_SUMMARY_SETUP);
+ setup = e_source_get_extension (scratch, E_SOURCE_EXTENSION_BACKEND_SUMMARY_SETUP);
+ e_source_backend_summary_setup_set_summary_fields (setup,
+ E_CONTACT_TEL,
+ 0);
+ e_source_backend_summary_setup_set_indexed_fields (setup,
+ E_CONTACT_TEL, E_BOOK_INDEX_PHONE,
+ 0);
+}
+
+static gboolean
+query_service_pid (const char *name,
+ GPid *pid,
+ GError **error)
+{
+ GDBusConnection *connection;
+ GVariant *rv;
+
+ connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
+
+ if (connection == NULL)
+ return FALSE;
+
+ rv = g_dbus_connection_call_sync (connection,
+ "org.freedesktop.DBus",
+ "/org/freedesktop/DBus",
+ "org.freedesktop.DBus",
+ "GetConnectionUnixProcessID",
+ g_variant_new ("(s)", name),
+ NULL, G_DBUS_CALL_FLAGS_NONE, -1,
+ NULL, error);
+
+ g_object_unref (connection);
+
+ if (rv == NULL)
+ return FALSE;
+
+ g_variant_get (rv, "(u)", pid);
+ g_variant_unref (rv);
+
+ return TRUE;
+}
+
+static gboolean
+spawn_addressbook_factory (GPid *pid, GError **error)
+{
+ int i;
+ GPid child_pid = 0;
+ GPid service_pid = 0;
+
+ char *argv[] = {
+ g_build_filename (BUILDDIR, "services/evolution-addressbook-factory/evolution-addressbook-factory", NULL),
+ NULL
+ };
+
+ gboolean success = g_spawn_async (NULL, argv, NULL,
+ G_SPAWN_LEAVE_DESCRIPTORS_OPEN,
+ NULL, NULL, &child_pid, error);
+
+ g_free (argv[0]);
+
+ /* Waiting a bit for the addressbook factory starting up so that it can claim its D-Bus name */
+ for (i = 0; success && service_pid == 0 && i < 10; ++i) {
+ sleep_in_main_loop (150);
+ success = query_service_pid (ADDRESS_BOOK_DBUS_SERVICE_NAME, &service_pid, error);
+ }
+
+ if (success) {
+ g_assert_cmpuint (service_pid, ==, child_pid);
+
+ if (pid)
+ *pid = child_pid;
+ }
+
+ return success;
+}
+
+gint
+main (gint argc,
+ gchar **argv)
+{
+ EBookClient *client;
+ GError *error = NULL;
+ EContact *contact;
+ gchar *source_uid;
+ gchar *contact_uid;
+ EVCardAttribute *attr;
+ GList *e164_values;
+ gboolean success;
+ ESource *source;
+ GPid factory_pid = 0;
+ GSList *fetched_uids;
+
+ g_test_init (&argc, &argv, NULL);
+
+ /*** Setup ****/
+
+ /* Initializing fake D-Bus and event loop machinery */
+ main_initialize ();
+ sleep_in_main_loop (500);
+
+ /* Setting with U.S. locale for addresses */
+ g_setenv ("LC_ADDRESS", "en_US.UTF-8", TRUE);
+ setlocale (LC_ADDRESS, "");
+ g_assert_cmpstr (nl_langinfo (_NL_ADDRESS_COUNTRY_AB2), ==, "US");
+
+ /* Launching addressbook factory on fake-dbus */
+ success = spawn_addressbook_factory (&factory_pid, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert_cmpuint (factory_pid, !=, 0);
+ g_assert (success);
+
+ /* Creating the test addressbook */
+ client = new_custom_temp_client (&source_uid, setup_custom_summary);
+ g_assert (client != NULL);
+
+ success = e_client_open_sync (E_CLIENT (client), FALSE, NULL, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (success);
+
+ /* Add test contact */
+ contact = e_contact_new_from_vcard ("BEGIN:VCARD\nTEL:221.542.3789\nEND:VCARD");
+ success = e_book_client_add_contact_sync (client, contact, &contact_uid, NULL, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (success);
+ g_object_unref (contact);
+
+ /*** Verification of U.S. context */
+
+ /* Fetch the contact by UID and check EVC_TEL attribute and its EVC_X_E164 parameter */
+ success = e_book_client_get_contact_sync (client, contact_uid, &contact, NULL, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (success);
+
+ attr = e_vcard_get_attribute (E_VCARD (contact), EVC_TEL);
+
+ g_assert (attr != NULL);
+ g_assert_cmpstr (e_vcard_attribute_get_value (attr), ==, "221.542.3789");
+
+ e164_values = e_vcard_attribute_get_param (attr, EVC_X_E164);
+
+ g_assert (e164_values != NULL);
+ g_assert_cmpstr (e164_values->data, ==, "+12215423789");
+
+ /* Now resolve the contact via its phone number, assuming indexes are used */
+ success = e_book_client_get_contacts_uids_sync (
+ client, "(eqphone \"phone\" \"+1/221/5423789\")",
+ &fetched_uids, NULL, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (success);
+
+ g_assert_cmpuint (g_slist_length (fetched_uids), ==, 1);
+ g_assert_cmpstr (fetched_uids->data, ==, contact_uid);
+ g_slist_free_full (fetched_uids, g_free);
+
+ success = e_book_client_get_contacts_uids_sync (
+ client, "(eqphone \"phone\" \"+49 (221) 5423789\")",
+ &fetched_uids, NULL, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (success);
+
+ g_assert_cmpuint (g_slist_length (fetched_uids), ==, 0);
+ g_slist_free_full (fetched_uids, g_free);
+
+ /*** Switch to German locale */
+
+ /* Shutdown address book factory on fake D-Bus */
+ g_object_unref (client);
+
+ success = (kill (factory_pid, SIGTERM) == 0);
+ g_assert (success);
+ factory_pid = 0;
+
+ /* Wait a bit to let GDBus notice what happened... */
+ sleep_in_main_loop (1500);
+
+ /* Switch to German locale */
+ g_setenv ("LC_ADDRESS", "de_DE.UTF-8", TRUE);
+ setlocale (LC_ADDRESS, "");
+
+ g_assert_cmpstr (nl_langinfo (_NL_ADDRESS_COUNTRY_AB2), ==, "DE");
+
+ /* Respawn the addressbook factory */
+ success = spawn_addressbook_factory (&factory_pid, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert_cmpuint (factory_pid, !=, 0);
+ g_assert (success);
+
+ /* Reopen the book */
+ source = e_source_new_with_uid (source_uid, NULL, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (source != NULL);
+
+ client = e_book_client_new (source, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (client != NULL);
+
+ success = e_client_open_sync (E_CLIENT (client), FALSE, NULL, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (success);
+
+ /*** Verification of German context */
+
+ /* Fetch the contact by UID and check EVC_TEL attribute and its EVC_X_E164 parameter */
+ success = e_book_client_get_contact_sync (client, contact_uid, &contact, NULL, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (success);
+
+ attr = e_vcard_get_attribute (E_VCARD (contact), EVC_TEL);
+
+ g_assert (attr != NULL);
+ g_assert_cmpstr (e_vcard_attribute_get_value (attr), ==, "221.542.3789");
+
+ e164_values = e_vcard_attribute_get_param (attr, EVC_X_E164);
+
+ g_assert (e164_values != NULL);
+ g_assert_cmpstr (e164_values->data, ==, "+492215423789");
+
+ /* Now resolve the contact via its phone number, assuming indexes are used */
+ success = e_book_client_get_contacts_uids_sync (
+ client, "(eqphone \"phone\" \"+1/221/5423789\")",
+ &fetched_uids, NULL, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (success);
+
+ g_assert_cmpuint (g_slist_length (fetched_uids), ==, 0);
+ g_slist_free_full (fetched_uids, g_free);
+
+ success = e_book_client_get_contacts_uids_sync (
+ client, "(eqphone \"phone\" \"+49 (221) 5423789\")",
+ &fetched_uids, NULL, &error);
+ g_assert_cmpstr (error ? error->message : NULL, ==, NULL);
+ g_assert (success);
+
+ g_assert_cmpuint (g_slist_length (fetched_uids), ==, 1);
+ g_assert_cmpstr (fetched_uids->data, ==, contact_uid);
+ g_slist_free_full (fetched_uids, g_free);
+
+ /* Cleanup */
+ g_object_unref (source);
+ g_object_unref (client);
+
+ return g_test_run ();
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]