* [PATCH 2/2] Add handling for more than one address in vCard
@ 2010-09-01 10:23 Rafał Michalski
2010-09-01 10:48 ` Johan Hedberg
0 siblings, 1 reply; 2+ messages in thread
From: Rafał Michalski @ 2010-09-01 10:23 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Rafał Michalski
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: 0002-Add-handling-for-more-than-one-address-in-vCard.patch --]
[-- Type: text/x-patch, Size: 14151 bytes --]
From f3d85a8a94fd2d44e16b64c486c29e642c7da192 Mon Sep 17 00:00:00 2001
From: Rafal Michalski <michalski.raf@gmail.com>
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
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH 2/2] Add handling for more than one address in vCard
2010-09-01 10:23 [PATCH 2/2] Add handling for more than one address in vCard Rafał Michalski
@ 2010-09-01 10:48 ` Johan Hedberg
0 siblings, 0 replies; 2+ messages in thread
From: Johan Hedberg @ 2010-09-01 10:48 UTC (permalink / raw)
To: Rafał Michalski; +Cc: linux-bluetooth
Hi Rafal,
On Wed, Sep 01, 2010, Rafał Michalski wrote:
> +static struct phonebook_address *find_address(GSList *addresses,
> + const char *address, int type)
> +{
> + GSList *l = addresses;
> +
> + for (; l; l = l->next) {
Please avoid initialization upon declaration of variables when possible.
The first part of the for-statement is where you should usually
initialize the iterator, i.e. in this case do the l = addresses there.
> +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) {
Same here for i. Additionally you could rename address_fields to simply
fields since the function is short and the context pretty obvious.
You'll also avoid the split line that way (another thing I wouldn't
object to is to move the initialization separate from the variable
declaration).
> -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;
Hmm, it seems you have the same function in vcard.c and
phonebook-tracker.c? Why not remove the phonebook-tracker.c one and
export the vcard.c version through vcard.h?
Johan
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2010-09-01 10:48 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-09-01 10:23 [PATCH 2/2] Add handling for more than one address in vCard Rafał Michalski
2010-09-01 10:48 ` Johan Hedberg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox