[PATCH] Add handling for more than one address with in vCard structure

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

 



From 9a56973f11afbba0135a419de232303ff4cc262e Mon Sep 17 00:00:00 2001
From: Rafal Michalski <michalski.raf@xxxxxxxxx>
Date: Mon, 30 Aug 2010 16:03:12 +0200
Subject: [PATCH] Add handling for more than one address with in vCard structure

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 |  139 +++++++++++++++++++++++++++++++++++++------
 plugins/vcard.c             |   92 +++++++++++++++++++++--------
 plugins/vcard.h             |   26 ++++++--
 3 files changed, 208 insertions(+), 49 deletions(-)

diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c
index 1f1f693..e17995d 100644
--- a/plugins/phonebook-tracker.c
+++ b/plugins/phonebook-tracker.c
@@ -43,16 +43,16 @@
 #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 CONTACTS_QUERY_ALL						\
 	"SELECT ?v nco:fullname(?c) "					\
@@ -64,7 +64,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 +86,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 +115,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 +138,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 +167,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 +190,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 +219,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 +241,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 +269,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 +291,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 +310,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 +345,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 +367,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 +740,73 @@ 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,
+					struct phonebook_address *address)
+{
+	GSList *l;
+
+	for (l = addresses; l; l = l->next) {
+		struct phonebook_address *addr = l->data;
+		if (g_strcmp0(addr->pobox, address->pobox) == 0 &&
+		g_strcmp0(addr->extended, address->extended) == 0 &&
+		g_strcmp0(addr->street, address->street) == 0 &&
+		g_strcmp0(addr->locality, address->locality) == 0 &&
+		g_strcmp0(addr->region, address->region) == 0 &&
+		g_strcmp0(addr->postal, address->postal) == 0 &&
+		g_strcmp0(addr->country, address->country) == 0 &&
+		addr->type == address->type)
+			return addr;
+	}
+
+	return NULL;
+}
+
+static gboolean address_fields_present(struct phonebook_address *address)
+{
+	if (address->pobox && strlen(address->pobox))
+		return TRUE;
+	if (address->extended && strlen(address->extended))
+		return TRUE;
+	if (address->street && strlen(address->street))
+		return TRUE;
+	if (address->locality && strlen(address->locality))
+		return TRUE;
+	if (address->region && strlen(address->region))
+		return TRUE;
+	if (address->postal && strlen(address->postal))
+		return TRUE;
+	if (address->country && strlen(address->country))
+		return TRUE;
+
+	return FALSE;
+}
+
+static void add_address(struct phonebook_contact *contact,
+				struct phonebook_address *address)
+{
+	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))
+		return;
+
+	addr = g_new0(struct phonebook_address, 1);
+
+	addr->pobox = g_strdup(address->pobox);
+	addr->extended = g_strdup(address->extended);
+	addr->street = g_strdup(address->street);
+	addr->locality = g_strdup(address->locality);
+	addr->region = g_strdup(address->region);
+	addr->postal = g_strdup(address->postal);
+	addr->country = g_strdup(address->country);
+	addr->type = address->type;
+
+	contact->addresses = g_slist_append(contact->addresses, addr);
+}
+
 static GString *gen_vcards(GSList *contacts,
 					const struct apparam_field *params)
 {
@@ -803,13 +889,6 @@ add_entry:
 	contact->additional = g_strdup(reply[4]);
 	contact->prefix = g_strdup(reply[5]);
 	contact->suffix = g_strdup(reply[6]);
-	contact->pobox = g_strdup(reply[9]);
-	contact->extended = g_strdup(reply[10]);
-	contact->street = g_strdup(reply[11]);
-	contact->locality = g_strdup(reply[12]);
-	contact->region = g_strdup(reply[13]);
-	contact->postal = g_strdup(reply[14]);
-	contact->country = g_strdup(reply[15]);
 	contact->birthday = g_strdup(reply[18]);
 	contact->nickname = g_strdup(reply[19]);
 	contact->website = g_strdup(reply[20]);
@@ -831,6 +910,30 @@ add_numbers:
 	add_email(contact, reply[COL_HOME_EMAIL], EMAIL_TYPE_HOME);
 	add_email(contact, reply[COL_WORK_EMAIL], EMAIL_TYPE_WORK);
 
+	/* Adding addresses */
+	struct phonebook_address home_addr = {	g_strdup(reply[9]),
+						g_strdup(reply[10]),
+						g_strdup(reply[11]),
+						g_strdup(reply[12]),
+						g_strdup(reply[13]),
+						g_strdup(reply[14]),
+						g_strdup(reply[15]),
+						ADDR_TYPE_HOME
+					};
+
+	struct phonebook_address work_addr = {	g_strdup(reply[25]),
+						g_strdup(reply[26]),
+						g_strdup(reply[27]),
+						g_strdup(reply[28]),
+						g_strdup(reply[29]),
+						g_strdup(reply[30]),
+						g_strdup(reply[31]),
+						ADDR_TYPE_WORK
+					};
+
+	add_address(contact, &home_addr);
+	add_address(contact, &work_addr);
+
 	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 09f4f40..e7e4cc7 100644
--- a/plugins/vcard.c
+++ b/plugins/vcard.c
@@ -155,21 +155,21 @@ 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(struct phonebook_address *address)
 {
-	if (contact->pobox && strlen(contact->pobox))
+	if (address->pobox && strlen(address->pobox))
 		return TRUE;
-	if (contact->extended && strlen(contact->extended))
+	if (address->extended && strlen(address->extended))
 		return TRUE;
-	if (contact->street && strlen(contact->street))
+	if (address->street && strlen(address->street))
 		return TRUE;
-	if (contact->locality && strlen(contact->locality))
+	if (address->locality && strlen(address->locality))
 		return TRUE;
-	if (contact->region && strlen(contact->region))
+	if (address->region && strlen(address->region))
 		return TRUE;
-	if (contact->postal && strlen(contact->postal))
+	if (address->postal && strlen(address->postal))
 		return TRUE;
-	if (contact->country && strlen(contact->country))
+	if (address->country && strlen(address->country))
 		return TRUE;
 
 	return FALSE;
@@ -376,18 +376,43 @@ 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,
+					struct phonebook_address *addr)
 {
-	if (address_fields_present(contact) == FALSE) {
+	char buf[LEN_MAX];
+	const char *category_string = "";
+
+	if (!addr || address_fields_present(addr) == FALSE) {
 		vcard_printf(vcards, "ADR:");
 		return;
 	}
 
-	vcard_printf(vcards, "ADR:%s;%s;%s;%s;%s;%s;%s", contact->pobox,
-					contact->extended, contact->street,
-					contact->locality, contact->region,
-					contact->postal, contact->country);
+	switch (addr->type) {
+	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;
+	}
+
+	snprintf(buf, LEN_MAX, "%s;%s;%s;%s;%s;%s;%s",
+		addr->pobox, addr->extended, addr->street,
+		addr->locality, addr->region, addr->postal, addr->country);
+
+	vcard_printf(vcards, "ADR;%s:%s", category_string, buf);
 }
 
 static void vcard_printf_datetime(GString *vcards,
@@ -468,8 +493,17 @@ 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);
+
+		for (; l; l = l->next) {
+			struct phonebook_address *addr = l->data;
+			vcard_printf_address(vcards, format, addr);
+		}
+	}
 
 	if (filter & FILTER_BDAY)
 		vcard_printf_tag(vcards, format, "BDAY", NULL,
@@ -512,6 +546,20 @@ 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->pobox);
+	g_free(addr->extended);
+	g_free(addr->street);
+	g_free(addr->locality);
+	g_free(addr->region);
+	g_free(addr->postal);
+	g_free(addr->country);
+	g_free(addr);
+}
+
 void phonebook_contact_free(struct phonebook_contact *contact)
 {
 	if (contact == NULL)
@@ -523,19 +571,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->pobox);
-	g_free(contact->extended);
-	g_free(contact->street);
-	g_free(contact->locality);
-	g_free(contact->region);
-	g_free(contact->postal);
-	g_free(contact->country);
 	g_free(contact->birthday);
 	g_free(contact->nickname);
 	g_free(contact->website);
diff --git a/plugins/vcard.h b/plugins/vcard.h
index a22dfc1..c8cac36 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,18 @@ struct phonebook_email {
 	int  type;
 };
 
+struct phonebook_address
+{
+	char *pobox;
+	char *extended;
+	char *street;
+	char *locality;
+	char *region;
+	char *postal;
+	char *country;
+	int type;
+};
+
 struct phonebook_contact {
 	char *fullname;
 	char *given;
@@ -57,15 +75,9 @@ struct phonebook_contact {
 	char *additional;
 	GSList *numbers;
 	GSList *emails;
+	GSList *addresses;
 	char *prefix;
 	char *suffix;
-	char *pobox;
-	char *extended;
-	char *street;
-	char *locality;
-	char *region;
-	char *postal;
-	char *country;
 	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