[PATCH 2/2] Add handling for more than one address in vCard

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

 



From f3d85a8a94fd2d44e16b64c486c29e642c7da192 Mon Sep 17 00:00:00 2001
From: Rafal Michalski <michalski.raf@xxxxxxxxx>
Date: Wed, 1 Sep 2010 11:50:31 +0200
Subject: [PATCH 2/2] Add handling for more than one address in vCard

After pulling contacts only fields (pobox, extended, street, locality,
region, postal, country) of one address were present in downloaded vCard
structure (under ADR tag) in spite of that there can be more adresses
stored on phonebook. To solve this problem extending number of columns and
queries of database was needed especially. Distinguish between two types
of address (HOME and WORK) is supported.
---
 plugins/phonebook-tracker.c |  112 +++++++++++++++++++++++++++++++++++++-----
 plugins/vcard.c             |   78 ++++++++++++++++++++++++++----
 plugins/vcard.h             |   13 +++++-
 3 files changed, 179 insertions(+), 24 deletions(-)

diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index bff85b8..2fbcc6f 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -43,16 +43,17 @@
 #define TRACKER_RESOURCES_INTERFACE "org.freedesktop.Tracker1.Resources"
 
 #define TRACKER_DEFAULT_CONTACT_ME "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#default-contact-me";
-#define CONTACTS_ID_COL 28
-#define PULL_QUERY_COL_AMOUNT 29
+#define CONTACTS_ID_COL 35
+#define PULL_QUERY_COL_AMOUNT 36
 #define COL_HOME_NUMBER 0
 #define COL_HOME_EMAIL 7
 #define COL_WORK_NUMBER 8
 #define COL_FAX_NUMBER 16
 #define COL_WORK_EMAIL 17
-#define COL_DATE 25
-#define COL_SENT 26
-#define COL_ANSWERED 27
+#define COL_DATE 32
+#define COL_SENT 33
+#define COL_ANSWERED 34
+#define ADDR_FIELD_AMOUNT 7
 
 #define CONTACTS_QUERY_ALL						\
 	"SELECT ?v nco:fullname(?c) "					\
@@ -64,7 +65,9 @@
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
 	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
 	"nco:photo(?c) nco:fullname(?o) nco:department(?a) "		\
-	"nco:role(?a) "							\
+	"nco:role(?a) nco:pobox(?pw) nco:extendedAddress(?pw) "		\
+	"nco:streetAddress(?pw) nco:locality(?pw) nco:region(?pw) "	\
+	"nco:postalcode(?pw) nco:country(?pw) "				\
 	"\"NOTACALL\" \"false\" \"false\" ?c "				\
 	"WHERE { "							\
 		"?c a nco:PersonContact . "				\
@@ -84,6 +87,7 @@
 		"?c nco:hasAffiliation ?a . "				\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:hasPostalAddress ?pw . } "		\
 		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"}"
@@ -112,7 +116,9 @@
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
 	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
 	"nco:photo(?c) nco:fullname(?o) nco:department(?a) "		\
-	"nco:role(?a) "							\
+	"nco:role(?a) nco:pobox(?pw) nco:extendedAddress(?pw) "		\
+	"nco:streetAddress(?pw) nco:locality(?pw) nco:region(?pw) "	\
+	"nco:postalcode(?pw) nco:country(?pw) "				\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -133,6 +139,7 @@
 		"?c nco:hasAffiliation ?a . "				\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:hasPostalAddress ?pw . } "		\
 		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"} ORDER BY DESC(nmo:receivedDate(?call))"
@@ -161,7 +168,9 @@
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
 	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
 	"nco:photo(?c) nco:fullname(?o) nco:department(?a) "		\
-	"nco:role(?a) "							\
+	"nco:role(?a) nco:pobox(?pw) nco:extendedAddress(?pw) "		\
+	"nco:streetAddress(?pw) nco:locality(?pw) nco:region(?pw) "	\
+	"nco:postalcode(?pw) nco:country(?pw) "				\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -182,6 +191,7 @@
 		"?c nco:hasAffiliation ?a . "				\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:hasPostalAddress ?pw . } "		\
 		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"} ORDER BY DESC(nmo:receivedDate(?call))"
@@ -210,7 +220,9 @@
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew)"	\
 	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
 	"nco:photo(?c) nco:fullname(?o) nco:department(?a) "		\
-	"nco:role(?a) "							\
+	"nco:role(?a) nco:pobox(?pw) nco:extendedAddress(?pw) "		\
+	"nco:streetAddress(?pw) nco:locality(?pw) nco:region(?pw) "	\
+	"nco:postalcode(?pw) nco:country(?pw) "				\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -230,6 +242,7 @@
 		"?c nco:hasAffiliation ?a . "				\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:hasPostalAddress ?pw . } "		\
 		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"} ORDER BY DESC(nmo:sentDate(?call))"
@@ -257,7 +270,9 @@
 	"nco:postalcode(?p) nco:country(?p) ?f nco:emailAddress(?ew) "	\
 	"nco:birthDate(?c) nco:nickname(?c) nco:websiteUrl(?c) "	\
 	"nco:photo(?c) nco:fullname(?o) nco:department(?a) "		\
-	"nco:role(?a) "							\
+	"nco:role(?a) nco:pobox(?pw) nco:extendedAddress(?pw) "		\
+	"nco:streetAddress(?pw) nco:locality(?pw) nco:region(?pw) "	\
+	"nco:postalcode(?pw) nco:country(?pw) "				\
 	"nmo:receivedDate(?call) "					\
 	"nmo:isSent(?call) nmo:isAnswered(?call) ?c "			\
 	"WHERE { "							\
@@ -277,6 +292,7 @@
 	"OPTIONAL { ?c nco:hasAffiliation ?a . "			\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:hasPostalAddress ?pw . } "		\
 		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"} UNION { "							\
@@ -295,6 +311,7 @@
 	"OPTIONAL { ?c nco:hasAffiliation ?a . "			\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . } " 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . } "		\
+		"OPTIONAL { ?a nco:hasPostalAddress ?pw . } "		\
 		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"} } ORDER BY DESC(nmo:receivedDate(?call))"
@@ -329,7 +346,9 @@
 	"nco:postalcode(?p) nco:country(?p) ?f  nco:emailAddress(?ew)"	\
 	"nco:birthDate(<%s>) nco:nickname(<%s>) nco:websiteUrl(<%s>) "	\
 	"nco:photo(<%s>) nco:fullname(?o) nco:department(?a) "		\
-	"nco:role(?a) "							\
+	"nco:role(?a) nco:pobox(?pw) nco:extendedAddress(?pw) "		\
+	"nco:streetAddress(?pw) nco:locality(?pw) nco:region(?pw) "	\
+	"nco:postalcode(?pw) nco:country(?pw) "				\
 	"\"NOTACALL\" \"false\" \"false\" <%s> "			\
 	"WHERE { "							\
 		"<%s> a nco:Contact . "					\
@@ -349,6 +368,7 @@
 		"<%s> nco:hasAffiliation ?a . "				\
 		"OPTIONAL { ?a nco:hasPhoneNumber ?w . }" 		\
 		"OPTIONAL { ?a nco:hasEmailAddress ?ew . }"		\
+		"OPTIONAL { ?a nco:hasPostalAddress ?pw . } "		\
 		"OPTIONAL { ?a nco:org ?o . } "				\
 	"} "								\
 	"}"
@@ -721,6 +741,60 @@ static void add_email(struct phonebook_contact *contact, const char *address,
 	contact->emails = g_slist_append(contact->emails, email);
 }
 
+static struct phonebook_address *find_address(GSList *addresses,
+					const char *address, int type)
+{
+	GSList *l = addresses;
+
+	for (; l; l = l->next) {
+		struct phonebook_address *addr = l->data;
+		if (g_strcmp0(addr->addr, address) == 0 &&
+						addr->type == type)
+			return addr;
+	}
+
+	return NULL;
+}
+
+static gboolean address_fields_present(const char *address)
+{
+	gchar **address_fields = g_strsplit(address, ";",
+							ADDR_FIELD_AMOUNT);
+	int i = 0;
+
+	for (; i < ADDR_FIELD_AMOUNT; ++i) {
+
+		if (strlen(address_fields[i]) != 0) {
+			g_strfreev(address_fields);
+			return TRUE;
+		}
+	}
+
+	g_strfreev(address_fields);
+
+	return FALSE;
+}
+
+static void add_address(struct phonebook_contact *contact,
+					const char *address, int type)
+{
+	struct phonebook_address *addr;
+
+	if (address == NULL || address_fields_present(address) == FALSE)
+		return;
+
+	/* Not adding address if there is already added with the same value */
+	if (find_address(contact->addresses, address, type))
+		return;
+
+	addr = g_new0(struct phonebook_address, 1);
+
+	addr->addr = g_strdup(address);
+	addr->type = type;
+
+	contact->addresses = g_slist_append(contact->addresses, addr);
+}
+
 static GString *gen_vcards(GSList *contacts,
 					const struct apparam_field *params)
 {
@@ -753,6 +827,7 @@ static void pull_contacts(char **reply, int num_fields, void *user_data)
 	GString *vcards;
 	int last_index, i;
 	gboolean cdata_present = FALSE;
+	char *home_addr, *work_addr;
 
 	DBG("reply %p", reply);
 
@@ -803,9 +878,6 @@ add_entry:
 	contact->additional = g_strdup(reply[4]);
 	contact->prefix = g_strdup(reply[5]);
 	contact->suffix = g_strdup(reply[6]);
-	contact->address = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s",
-				reply[9], reply[10], reply[11], reply[12],
-				reply[13], reply[14], reply[15]);
 	contact->birthday = g_strdup(reply[18]);
 	contact->nickname = g_strdup(reply[19]);
 	contact->website = g_strdup(reply[20]);
@@ -827,6 +899,18 @@ add_numbers:
 	add_email(contact, reply[COL_HOME_EMAIL], EMAIL_TYPE_HOME);
 	add_email(contact, reply[COL_WORK_EMAIL], EMAIL_TYPE_WORK);
 
+	/* Adding addresses */
+	home_addr = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s",
+				reply[9], reply[10], reply[11], reply[12],
+				reply[13], reply[14], reply[15]);
+
+	work_addr = g_strdup_printf("%s;%s;%s;%s;%s;%s;%s",
+				reply[25], reply[26], reply[27], reply[28],
+				reply[29], reply[30], reply[31]);
+
+	add_address(contact, home_addr, ADDR_TYPE_HOME);
+	add_address(contact, work_addr, ADDR_TYPE_WORK);
+
 	DBG("contact %p", contact);
 
 	/* Adding contacts data to wrapper struct - this data will be used to
diff --git a/plugins/vcard.c b/plugins/vcard.c
index 33a1ede..19ecdd3 100644
--- a/plugins/vcard.c
+++ b/plugins/vcard.c
@@ -156,9 +156,9 @@ static gboolean contact_fields_present(struct phonebook_contact * contact)
 	return FALSE;
 }
 
-static gboolean address_fields_present(struct phonebook_contact *contact)
+static gboolean address_fields_present(const char *address)
 {
-	gchar **address_fields = g_strsplit(contact->address, ";",
+	gchar **address_fields = g_strsplit(address, ";",
 							ADDR_FIELD_AMOUNT);
 	int i = 0;
 
@@ -376,15 +376,54 @@ static void vcard_printf_org(GString *vcards,
 				contact->department, contact->title);
 }
 
-static void vcard_printf_adr(GString *vcards,
-					struct phonebook_contact *contact)
+static void vcard_printf_address(GString *vcards, uint8_t format,
+					const char *address,
+					enum phonebook_address_type category)
 {
-	if (address_fields_present(contact) == FALSE) {
+	char buf[LEN_MAX];
+	char field[ADDR_FIELD_AMOUNT][LEN_MAX];
+	const char *category_string = "";
+	int len, i;
+	gchar **address_fields;
+
+	if (!address || address_fields_present(address) == FALSE) {
 		vcard_printf(vcards, "ADR:");
 		return;
 	}
 
-	vcard_printf(vcards, "ADR:%s", contact->address);
+	switch (category) {
+	case ADDR_TYPE_HOME:
+		if (format == FORMAT_VCARD21)
+			category_string = "HOME";
+		else if (format == FORMAT_VCARD30)
+			category_string = "TYPE=HOME";
+		break;
+	case ADDR_TYPE_WORK:
+		if (format == FORMAT_VCARD21)
+			category_string = "WORK";
+		else if (format == FORMAT_VCARD30)
+			category_string = "TYPE=WORK";
+		break;
+	default:
+		if (format == FORMAT_VCARD21)
+			category_string = "OTHER";
+		else if (format == FORMAT_VCARD30)
+			category_string = "TYPE=OTHER";
+		break;
+	}
+
+	address_fields = g_strsplit(address, ";", ADDR_FIELD_AMOUNT);
+
+	for (i = 0; i < ADDR_FIELD_AMOUNT; ++i) {
+		len = strlen(address_fields[i]);
+		add_slash(field[i], address_fields[i], LEN_MAX, len);
+	}
+
+	snprintf(buf, LEN_MAX, "%s;%s;%s;%s;%s;%s;%s",
+	field[0], field[1], field[2], field[3], field[4], field[5], field[6]);
+	g_strfreev(address_fields);
+
+	vcard_printf(vcards,"ADR;%s:%s", category_string, buf);
 }
 
 static void vcard_printf_datetime(GString *vcards,
@@ -465,8 +504,19 @@ void phonebook_add_contact(GString *vcards, struct phonebook_contact *contact,
 		}
 	}
 
-	if (filter & FILTER_ADR)
-		vcard_printf_adr(vcards, contact);
+	if (filter & FILTER_ADR) {
+		GSList *l = contact->addresses;
+
+		if (g_slist_length(l) == 0)
+			vcard_printf_address(vcards, format, NULL,
+							ADDR_TYPE_OTHER);
+
+		for (; l; l = l->next) {
+			struct phonebook_address *addr = l->data;
+			vcard_printf_address(vcards, format, addr->addr,
+								addr->type);
+		}
+	}
 
 	if (filter & FILTER_BDAY)
 		vcard_printf_tag(vcards, format, "BDAY", NULL,
@@ -509,6 +559,14 @@ static void email_free(gpointer data, gpointer user_data)
 	g_free(email);
 }
 
+static void address_free(gpointer data, gpointer user_data)
+{
+	struct phonebook_address *addr = data;
+
+	g_free(addr->addr);
+	g_free(addr);
+}
+
 void phonebook_contact_free(struct phonebook_contact *contact)
 {
 	if (contact == NULL)
@@ -520,13 +578,15 @@ void phonebook_contact_free(struct phonebook_contact *contact)
 	g_slist_foreach(contact->emails, email_free, NULL);
 	g_slist_free(contact->emails);
 
+	g_slist_foreach(contact->addresses, address_free, NULL);
+	g_slist_free(contact->addresses);
+
 	g_free(contact->fullname);
 	g_free(contact->given);
 	g_free(contact->family);
 	g_free(contact->additional);
 	g_free(contact->prefix);
 	g_free(contact->suffix);
-	g_free(contact->address);
 	g_free(contact->birthday);
 	g_free(contact->nickname);
 	g_free(contact->website);
diff --git a/plugins/vcard.h b/plugins/vcard.h
index b1e971e..8be6df4 100644
--- a/plugins/vcard.h
+++ b/plugins/vcard.h
@@ -40,6 +40,12 @@ enum phonebook_call_type {
 	CALL_TYPE_OUTGOING,
 };
 
+enum phonebook_address_type {
+	ADDR_TYPE_HOME,
+	ADDR_TYPE_WORK,
+	ADDR_TYPE_OTHER,
+};
+
 struct phonebook_number {
 	char *tel;
 	int type;
@@ -50,6 +56,11 @@ struct phonebook_email {
 	int  type;
 };
 
+struct phonebook_address {
+	char *addr;
+	int type;
+};
+
 struct phonebook_contact {
 	char *fullname;
 	char *given;
@@ -59,7 +70,7 @@ struct phonebook_contact {
 	GSList *emails;
 	char *prefix;
 	char *suffix;
-	char *address;
+	GSList *addresses;
 	char *birthday;
 	char *nickname;
 	char *website;
-- 
1.6.3.3


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux