Diff between 11f7e9efe758f192f266f37beb0b61db5fcba55e and a4b6035009ec7ecb3b900f0f1188f2788d4df5c9

Changed Files

File Additions Deletions Status
obexd/plugins/phonebook-tracker.c +63 -9 modified
obexd/plugins/vcard.c +32 -38 modified
obexd/plugins/vcard.h +6 -1 modified

Full Patch

diff --git a/obexd/plugins/phonebook-tracker.c b/obexd/plugins/phonebook-tracker.c
index a15bf20..f684bfd 100644
--- a/obexd/plugins/phonebook-tracker.c
+++ b/obexd/plugins/phonebook-tracker.c
@@ -823,22 +823,76 @@ static void add_email(struct phonebook_contact *contact, const char *address,
 	contact->emails = g_slist_append(contact->emails, email);
 }
 
+static gboolean addr_matches(struct phonebook_addr *a, struct phonebook_addr *b)
+{
+	GSList *la, *lb;
+
+	if (a->type != b->type)
+		return FALSE;
+
+	for (la = a->fields, lb = b->fields; la && lb;
+						la = la->next, lb = lb->next) {
+		char *field_a = la->data;
+		char *field_b = lb->data;
+
+		if (g_strcmp0(field_a, field_b) != 0)
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+/* generates phonebook_addr struct from tracker address data string. */
+static struct phonebook_addr *gen_addr(const char *address, int type)
+{
+	struct phonebook_addr *addr;
+	GSList *fields = NULL;
+	char **addr_parts;
+	int i;
+
+	/* This test handles cases when address points to empty string
+	 * (or address is NULL pointer) or string containing only six
+	 * separators. It indicates that none of address fields is present
+	 * and there is no sense to create dummy phonebook_addr struct */
+	if (address == NULL || strlen(address) < ADDR_FIELD_AMOUNT)
+		return NULL;
+
+	addr_parts = g_strsplit(address, ";", ADDR_FIELD_AMOUNT);
+
+	for (i = 0; i < ADDR_FIELD_AMOUNT; ++i)
+		fields = g_slist_append(fields, g_strdup(addr_parts[i]));
+
+	g_strfreev(addr_parts);
+
+	addr = g_new0(struct phonebook_addr, 1);
+	addr->fields = fields;
+	addr->type = type;
+
+	return addr;
+}
+
 static void add_address(struct phonebook_contact *contact,
 					const char *address, int type)
 {
-	struct phonebook_field *addr;
-
-	if (address == NULL || address_fields_present(address) == FALSE)
-		return;
+	struct phonebook_addr *addr;
+	GSList *l;
 
-	/* Not adding address if there is already added with the same value */
-	if (find_field(contact->addresses, address, type))
+	addr = gen_addr(address, type);
+	if (addr == NULL)
 		return;
 
-	addr = g_new0(struct phonebook_field, 1);
+	/* Not adding address if there is already added with the same value.
+	 * These type of checks have to be done because sometimes tracker
+	 * returns results for contact data in more than 1 row - then the same
+	 * address may be returned more than once in query results */
+	for (l = contact->addresses; l; l = l->next) {
+		struct phonebook_addr *tmp = l->data;
 
-	addr->text = g_strdup(address);
-	addr->type = type;
+		if (addr_matches(tmp, addr)) {
+			phonebook_addr_free(addr);
+			return;
+		}
+	}
 
 	contact->addresses = g_slist_append(contact->addresses, addr);
 }
diff --git a/obexd/plugins/vcard.c b/obexd/plugins/vcard.c
index 5a5bcf4..a4a1921 100644
--- a/obexd/plugins/vcard.c
+++ b/obexd/plugins/vcard.c
@@ -201,24 +201,6 @@ static gboolean contact_fields_present(struct phonebook_contact * contact)
 	return FALSE;
 }
 
-gboolean address_fields_present(const char *address)
-{
-	gchar **fields = g_strsplit(address, ";", ADDR_FIELD_AMOUNT);
-	int i;
-
-	for (i = 0; i < ADDR_FIELD_AMOUNT; ++i) {
-
-		if (strlen(fields[i]) != 0) {
-			g_strfreev(fields);
-			return TRUE;
-		}
-	}
-
-	g_strfreev(fields);
-
-	return FALSE;
-}
-
 static void vcard_printf_name(GString *vcards,
 					struct phonebook_contact *contact)
 {
@@ -440,21 +422,19 @@ static void vcard_printf_org(GString *vcards,
 }
 
 static void vcard_printf_address(GString *vcards, uint8_t format,
-					const char *address,
-					enum phonebook_field_type category)
+					struct phonebook_addr *address)
 {
-	char buf[LEN_MAX];
-	char field[ADDR_FIELD_AMOUNT][LEN_MAX];
+	char *fields, field_esc[LEN_MAX];
 	const char *category_string = "";
-	int len, i;
-	gchar **address_fields;
+	size_t len;
+	GSList *l;
 
-	if (!address || address_fields_present(address) == FALSE) {
+	if (!address) {
 		vcard_printf(vcards, "ADR:");
 		return;
 	}
 
-	switch (category) {
+	switch (address->type) {
 	case FIELD_TYPE_HOME:
 		if (format == FORMAT_VCARD21)
 			category_string = "HOME";
@@ -475,18 +455,25 @@ static void vcard_printf_address(GString *vcards, uint8_t format,
 		break;
 	}
 
-	address_fields = g_strsplit(address, ";", ADDR_FIELD_AMOUNT);
+	/* allocate enough memory to insert address fields separated by ';'
+	 * and terminated by '\0' */
+	len = ADDR_FIELD_AMOUNT * LEN_MAX;
+	fields = g_malloc0(len);
+
+	for (l = address->fields; l; l = l->next) {
+		char *field = l->data;
+
+		add_slash(field_esc, field, LEN_MAX, strlen(field));
+		g_strlcat(fields, field_esc, len);
 
-	for (i = 0; i < ADDR_FIELD_AMOUNT; ++i) {
-		len = strlen(address_fields[i]);
-		add_slash(field[i], address_fields[i], LEN_MAX, len);
+		if (l->next)
+			/* not addding ';' after last addr field */
+			g_strlcat(fields, ";", 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, fields);
 
-	vcard_printf(vcards,"ADR;%s:%s", category_string, buf);
+	g_free(fields);
 }
 
 static void vcard_printf_datetime(GString *vcards,
@@ -576,9 +563,8 @@ void phonebook_add_contact(GString *vcards, struct phonebook_contact *contact,
 		GSList *l = contact->addresses;
 
 		for (; l; l = l->next) {
-			struct phonebook_field *addr = l->data;
-			vcard_printf_address(vcards, format, addr->text,
-								addr->type);
+			struct phonebook_addr *addr = l->data;
+			vcard_printf_address(vcards, format, addr);
 		}
 	}
 
@@ -627,6 +613,14 @@ static void field_free(gpointer data)
 	g_free(field);
 }
 
+void phonebook_addr_free(gpointer addr)
+{
+	struct phonebook_addr *address = addr;
+
+	g_slist_free_full(address->fields, g_free);
+	g_free(address);
+}
+
 void phonebook_contact_free(struct phonebook_contact *contact)
 {
 	if (contact == NULL)
@@ -634,7 +628,7 @@ void phonebook_contact_free(struct phonebook_contact *contact)
 
 	g_slist_free_full(contact->numbers, field_free);
 	g_slist_free_full(contact->emails, field_free);
-	g_slist_free_full(contact->addresses, field_free);
+	g_slist_free_full(contact->addresses, phonebook_addr_free);
 	g_slist_free_full(contact->urls, field_free);
 
 	g_free(contact->uid);
diff --git a/obexd/plugins/vcard.h b/obexd/plugins/vcard.h
index 88cdbed..22c3f68 100644
--- a/obexd/plugins/vcard.h
+++ b/obexd/plugins/vcard.h
@@ -45,6 +45,11 @@ struct phonebook_field {
 	int type;
 };
 
+struct phonebook_addr {
+	GSList *fields;
+	int type;
+};
+
 struct phonebook_contact {
 	char *uid;
 	char *fullname;
@@ -73,4 +78,4 @@ void phonebook_add_contact(GString *vcards, struct phonebook_contact *contact,
 
 void phonebook_contact_free(struct phonebook_contact *contact);
 
-gboolean address_fields_present(const char *address);
+void phonebook_addr_free(gpointer addr);