Diff between 7aa82b382a9742ad1f6dc1b91e0f340554b82a23 and 96ea0081a9a3b67be110046ab6275003f71f30f6

Changed Files

File Additions Deletions Status
obexd/plugins/pbap.c +11 -412 renamed
obexd/plugins/phonebook-dummy.c +52 -0 added
obexd/plugins/phonebook-ebook.c +433 -0 added
obexd/plugins/phonebook.h +39 -0 added
obexd/plugins/telephony-dummy.c +38 -0 added
obexd/plugins/telephony.h +25 -0 added

Full Patch

diff --git a/obexd/plugins/ebook.c b/obexd/plugins/pbap.c
similarity index 56%
rename from obexd/plugins/ebook.c
rename to obexd/plugins/pbap.c
index a5b43c8..c553deb 100644
--- a/obexd/plugins/ebook.c
+++ b/obexd/plugins/pbap.c
@@ -34,12 +34,12 @@
 #include <openobex/obex.h>
 #include <openobex/obex_const.h>
 
-#include <libebook/e-book.h>
-
 #include "plugin.h"
 #include "logging.h"
 #include "obex.h"
 #include "service.h"
+#include "phonebook.h"
+#include "telephony.h"
 
 #define PHONEBOOK_TYPE		"x-bt/phonebook"
 #define VCARDLISTING_TYPE	"x-bt/vcard-listing"
@@ -70,17 +70,6 @@
 
 #define DEFAULT_COUNT 65535
 
-#define EOL_CHARS "\n"
-#define VL_VERSION "<?xml version=\"1.0\"?>" EOL_CHARS
-#define VL_TYPE "<!DOCTYPE vcard-listing SYSTEM \"vcard-listing.dtd\">" EOL_CHARS
-#define VL_BODY_BEGIN "<vCard-listing version=\"1.0\">" EOL_CHARS
-#define VL_BODY_END "</vCard-listing>" EOL_CHARS
-#define VL_ELEMENT "<card handle = \"%d.vcf\" name = \"%s\"/>" EOL_CHARS
-
-#define QUERY_FAMILY_NAME "(contains \"family_name\" \"%s\")"
-#define QUERY_GIVEN_NAME "(contains \"given_name\" \"%s\")"
-#define QUERY_PHONE "(contains \"phone\" \"%s\")"
-
 #define APPARAM_HDR_SIZE 2
 
 #define get_be64(val)	GUINT64_FROM_BE(bt_get_unaligned((guint64 *) val))
@@ -137,400 +126,10 @@ struct apparam_hdr {
 	uint8_t		val[0];
 } __attribute__ ((packed));
 
-struct apparam_field {
-	guint64		filter;
-	guint16		maxlistcount;
-	guint16		liststartoffset;
-	guint8		format;
-	guint8		order;
-	guint8		searchattrib;
-	guint8		*searchval;
-};
-
-struct phonebook_data {
-	obex_t *obex;
-	obex_object_t *obj;
-	struct apparam_field params;
-};
-
 static const guint8 PBAP_TARGET[TARGET_SIZE] = {
 			0x79, 0x61, 0x35, 0xF0,  0xF0, 0xC5, 0x11, 0xD8,
 			0x09, 0x66, 0x08, 0x00,  0x20, 0x0C, 0x9A, 0x66  };
 
-static char *vcard_attribs[29] = { EVC_VERSION, EVC_FN, EVC_N, EVC_PHOTO,
-				EVC_BDAY, EVC_ADR, EVC_LABEL, EVC_TEL,
-				EVC_EMAIL, EVC_MAILER, NULL, EVC_GEO,
-				EVC_TITLE, EVC_ROLE, EVC_LOGO, NULL,
-				EVC_ORG, EVC_NOTE, EVC_REV, NULL, EVC_URL,
-				EVC_UID, EVC_KEY, EVC_NICKNAME, EVC_CATEGORIES,
-				EVC_PRODID, NULL, NULL, NULL };
-
-static void ebookpull_cb(EBook *book, EBookStatus status, GList *list,
-				gpointer user_data)
-{
-	struct phonebook_data *pb_data = user_data;
-	struct apparam_field *params = &pb_data->params;
-	struct obex_session *session = OBEX_GetUserData(pb_data->obex);
-	guint16 offset = 0, count = 0;
-	GList *contacts = list;
-	GString *pb;
-	gchar *result;
-	gint32 size;
-
-	pb = g_string_new(NULL);
-
-	/* Mandatory attributes for vCard 3.0 are VERSION, N, FN and TEL */
-	if (params->filter != 0 && params->format == EVC_FORMAT_VCARD_30)
-		params->filter |= 0x87;
-
-	for (; contacts != NULL; contacts = g_list_next(contacts)) {
-		EContact *contact = NULL;
-		EVCard *evcard = NULL, *evcard_filtered = NULL;
-		GList *attrib_list = NULL, *l;
-		char *vcard;
-
-		if (offset < params->liststartoffset) {
-			offset++;
-			continue;
-		}
-
-		if (count < params->maxlistcount)
-			count++;
-		else
-			break;
-
-		contact = E_CONTACT(contacts->data);
-		evcard = E_VCARD(contact);
-		attrib_list = e_vcard_get_attributes(evcard);
-
-		if (!params->filter) {
-			vcard = e_vcard_to_string(evcard, params->format);
-			goto done;
-		}
-
-		evcard_filtered = e_vcard_new();
-		for (l = attrib_list; l; l = l->next) {
-			int i;
-			const char *attrib_name = e_vcard_attribute_get_name(
-						(EVCardAttribute *)l->data);
-
-			for (i = 0; i <= 28; i++) {
-				int mask;
-
-				mask = 1 << i;
-				if (!(params->filter & mask))
-					continue;
-				if (g_strcmp0(vcard_attribs[i], attrib_name))
-					continue;
-				e_vcard_add_attribute(
-					evcard_filtered,
-					e_vcard_attribute_copy(
-					(EVCardAttribute *)l->data));
-				break;
-			}
-		}
-		vcard = e_vcard_to_string(evcard_filtered, params->format);
-		g_object_unref(evcard_filtered);
-
-done:		g_string_append_printf(pb, "%s\n", vcard);
-		g_free(vcard);
-	}
-
-	result = g_string_free(pb, FALSE);
-	size = strlen(result);
-
-	if (size != 0) {
-		session->buf = g_realloc(session->buf, session->size + size);
-		memcpy(session->buf + session->size, result, size);
-		session->size += size;
-	}
-
-	session->finished = 1;
-	OBEX_ResumeRequest(session->obex);
-
-	g_free(result);
-	g_free(pb_data);
-	g_object_unref(book);
-}
-
-static int ebook_pullphonebook(obex_t *obex, obex_object_t *obj,
-				struct apparam_field params)
-{
-	struct phonebook_data *pb_data;
-	EBook *book;
-	EBookQuery *query;
-
-	if (params.format != EVC_FORMAT_VCARD_30) {
-		DBG("libebook does not support e_vcard_to_string_vcard_21()");
-		return -1;
-	}
-
-	pb_data = g_new0(struct phonebook_data, 1);
-	pb_data->obex = obex;
-	pb_data->obj = obj;
-	pb_data->params = params;
-
-	book = e_book_new_default_addressbook(NULL);
-
-	e_book_open(book, FALSE, NULL);
-
-	query = e_book_query_any_field_contains("");
-
-	e_book_async_get_contacts(book, query, ebookpull_cb, pb_data);
-
-	e_book_query_unref(query);
-
-	OBEX_SuspendRequest(obex, obj);
-
-	return 0;
-}
-
-static void ebooklist_cb(EBook *book, EBookStatus status, GList *list,
-				gpointer user_data)
-{
-	struct phonebook_data *pb_data = user_data;
-	struct apparam_field *params = &pb_data->params;
-	struct obex_session *session = OBEX_GetUserData(pb_data->obex);
-	guint16 offset = 0, count = 0;
-	GString *listing;
-	GList *contacts = list;
-	gchar *result;
-	gint32 size;
-
-	listing = g_string_new(VL_VERSION);
-	listing = g_string_append(listing, VL_TYPE);
-	listing = g_string_append(listing, VL_BODY_BEGIN);
-
-	for (; contacts != NULL; contacts = g_list_next(contacts)) {
-		EContact *contact = NULL;
-		EVCard *evcard = NULL;
-		EVCardAttribute *name_attrib = NULL;
-		GList *name_values = NULL;
-		gchar *name = NULL, *name_part = NULL, *element = NULL;
-
-		if (offset < params->liststartoffset) {
-			offset++;
-			continue;
-		}
-
-		if (count < params->maxlistcount)
-			count++;
-		else
-			break;
-
-		contact = E_CONTACT(contacts->data);
-		evcard = E_VCARD(contact);
-		name_attrib = e_vcard_get_attribute(evcard, EVC_N);
-
-		if (name_attrib) {
-			name_values = e_vcard_attribute_get_values(name_attrib);
-			for (; name_values; name_values = name_values->next) {
-				if (!name_part) {
-					name_part = g_strdup(name_values->data);
-					continue;
-				}
-				name = g_strjoin(";", name_part,
-						name_values->data, NULL);
-				g_free(name_part);
-				name_part = name;
-			}
-
-			element = g_strdup_printf(VL_ELEMENT, offset, name);
-			listing = g_string_append(listing, element);
-
-			g_free(name);
-			g_free(element);
-		}
-
-		offset++;
-	}
-
-	listing = g_string_append(listing, VL_BODY_END);
-	result = g_string_free(listing, FALSE);
-	size = strlen(result);
-
-	if (size != 0) {
-		session->buf = g_realloc(session->buf, session->size + size);
-		memcpy(session->buf + session->size, result, size);
-		session->size += size;
-	}
-
-	session->finished = 1;
-	OBEX_ResumeRequest(session->obex);
-
-	g_free(result);
-	g_free(pb_data);
-	g_object_unref(book);
-}
-
-static int ebook_pullvcardlisting(obex_t *obex, obex_object_t *obj,
-				struct apparam_field params)
-{
-	struct phonebook_data *pb_data;
-	EBook *book;
-	EBookQuery *query = NULL, *query1 = NULL, *query2 = NULL;
-	gchar *str1 = NULL, *str2 = NULL;
-	gchar **value_list = NULL;
-
-	pb_data = g_new0(struct phonebook_data, 1);
-	pb_data->obex = obex;
-	pb_data->obj = obj;
-	pb_data->params = params;
-
-	book = e_book_new_default_addressbook(NULL);
-
-	e_book_open(book, FALSE, NULL);
-
-	/* All the vCards shall be returned if SearchValue header is
-	 * not specified */
-	if (!params.searchval || !strlen((char *) params.searchval)) {
-		query = e_book_query_any_field_contains("");
-		goto done;
-	}
-
-	if (params.searchattrib == 0) {
-		value_list = g_strsplit((gchar *) params.searchval, ";", 5);
-
-		if (value_list[0])
-			str1 = g_strdup_printf(QUERY_FAMILY_NAME,
-						value_list[0]);
-		if (value_list[1])
-			str2 = g_strdup_printf(QUERY_GIVEN_NAME, value_list[1]);
-
-		if (str1)
-			query1 = e_book_query_from_string(str1);
-		if (str2)
-			query2 = e_book_query_from_string(str2);
-		if (query1 && query2)
-			query = e_book_query_andv(query1, query2, NULL);
-		else
-			query = query1;
-	} else {
-		str1 = g_strdup_printf(QUERY_PHONE, params.searchval);
-		query = e_book_query_from_string((char *) params.searchval);
-	}
-
-done:
-	e_book_async_get_contacts(book, query, ebooklist_cb, pb_data);
-
-	g_free(str1);
-	g_free(str2);
-	if (query1 && query1 != query)
-		e_book_query_unref(query1);
-	if (query2)
-		e_book_query_unref(query2);
-	e_book_query_unref(query);
-	g_strfreev(value_list);
-
-	OBEX_SuspendRequest(obex, obj);
-
-	return 0;
-}
-
-static void ebookpullentry_cb(EBook *book, EBookStatus status, GList *list,
-                                gpointer user_data)
-{
-	struct phonebook_data *pb_data = user_data;
-	struct apparam_field *params = &pb_data->params;
-	struct obex_session *session = OBEX_GetUserData(pb_data->obex);
-	guint16 i = 0, index;
-	GList *contacts = list, *attrib_list = NULL, *l;
-	EContact *contact = NULL;
-	EVCard *evcard = NULL, *evcard_filtered = NULL;
-	gint32 size = 0;
-	char *vcard = NULL;
-
-	if (params->filter != 0 && params->format == EVC_FORMAT_VCARD_30)
-		params->filter |= 0x87;
-
-	sscanf(session->name, "%hu.vcf", &index);
-
-	for (; contacts != NULL; contacts = g_list_next(contacts)) {
-		if (i < index) {
-			i++;
-			continue;
-		}
-
-		contact = E_CONTACT(contacts->data);
-		evcard = E_VCARD(contact);
-
-		if (!params->filter) {
-			vcard = e_vcard_to_string(evcard, params->format);
-			break;
-		}
-
-		attrib_list = e_vcard_get_attributes(evcard);
-		evcard_filtered = e_vcard_new();
-		for (l = attrib_list; l; l = l->next) {
-			int i;
-			const char *attrib_name = e_vcard_attribute_get_name(
-						(EVCardAttribute *)l->data);
-			for (i = 0; i <= 28; i++) {
-				int mask;
-
-				mask = 1 << i;
-				if (!(params->filter & mask))
-					continue;
-				if (g_strcmp0(vcard_attribs[i], attrib_name))
-					continue;
-
-				e_vcard_add_attribute(
-					evcard_filtered,
-					e_vcard_attribute_copy(
-					(EVCardAttribute *)l->data));
-				 break;
-			}
-		}
-		vcard = e_vcard_to_string(evcard_filtered, params->format);
-		g_object_unref(evcard_filtered);
-		break;
-	}
-
-	if (vcard) {
-		size = strlen(vcard);
-		session->buf = g_realloc(session->buf, session->size + size);
-		memcpy(session->buf + session->size, vcard, size);
-		session->size += size;
-	}
-
-	session->finished = 1;
-	OBEX_ResumeRequest(session->obex);
-
-	g_free(vcard);
-	g_free(pb_data);
-	g_object_unref(book);
-}
-
-static int ebook_pullvcardentry(obex_t *obex, obex_object_t *obj,
-				struct apparam_field params)
-{
-	struct phonebook_data *pb_data;
-	EBook *book;
-	EBookQuery *query;
-
-	if (params.format != EVC_FORMAT_VCARD_30) {
-		DBG("libebook does not support e_vcard_to_string_vcard_21()");
-		return -1;
-	}
-
-	pb_data = g_new0(struct phonebook_data, 1);
-	pb_data->obex = obex;
-	pb_data->obj = obj;
-	pb_data->params = params;
-
-	book = e_book_new_default_addressbook(NULL);
-
-	e_book_open(book, FALSE, NULL);
-
-	query = e_book_query_any_field_contains("");
-
-	e_book_async_get_contacts(book, query, ebookpullentry_cb, pb_data);
-
-	OBEX_SuspendRequest(obex, obj);
-
-	return 0;
-}
-
 static int pbap_parse_apparam_header(obex_t *obex, obex_object_t *obj,
 						struct apparam_field *apparam)
 {
@@ -704,7 +303,7 @@ static int pbap_pullphonebook(obex_t *obex, obex_object_t *obj,
 		goto done;
 	}
 
-	err = ebook_pullphonebook(obex, obj, params);
+	err = phonebook_pullphonebook(obex, obj, params);
 	if (err < 0)
 		return err;
 
@@ -741,7 +340,7 @@ static int pbap_pullvcardlisting(obex_t *obex, obex_object_t *obj,
 		goto done;
 	}
 
-	err = ebook_pullvcardlisting(obex, obj, params);
+	err = phonebook_pullvcardlisting(obex, obj, params);
 	if (err < 0)
 		goto done;
 
@@ -772,7 +371,7 @@ static int pbap_pullvcardentry(obex_t *obex, obex_object_t *obj)
 	if (err < 0)
 		return err;
 
-	err = ebook_pullvcardentry(obex, obj, params);
+	err = phonebook_pullvcardentry(obex, obj, params);
 
 	g_free(params.searchval);
 	return err;
@@ -929,7 +528,7 @@ static void pbap_setpath(obex_t *obex, obex_object_t *obj)
 	OBEX_ObjectSetRsp(obj, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS);
 }
 
-struct obex_service_driver driver = {
+struct obex_service_driver pbap = {
 	.name = "Phonebook Access server",
 	.service = OBEX_PBAP,
 	.channel = PBAP_CHANNEL,
@@ -939,14 +538,14 @@ struct obex_service_driver driver = {
 	.setpath = pbap_setpath
 };
 
-static int ebook_init(void)
+static int pbap_init(void)
 {
-	return obex_service_driver_register(&driver);
+	return obex_service_driver_register(&pbap);
 }
 
-static void ebook_exit(void)
+static void pbap_exit(void)
 {
-	obex_service_driver_unregister(&driver);
+	obex_service_driver_unregister(&pbap);
 }
 
-OBEX_PLUGIN_DEFINE("ebook", ebook_init, ebook_exit)
+OBEX_PLUGIN_DEFINE(pbap, pbap_init, pbap_exit)
diff --git a/obexd/plugins/phonebook-dummy.c b/obexd/plugins/phonebook-dummy.c
new file mode 100644
index 0000000..abcdce7
--- /dev/null
+++ b/obexd/plugins/phonebook-dummy.c
@@ -0,0 +1,52 @@
+/*
+ *
+ *  OBEX Server
+ *
+ *  Copyright (C) 2009  Intel Corporation
+ *  Copyright (C) 2007-2009  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+
+#include <openobex/obex.h>
+#include <openobex/obex_const.h>
+
+#include "phonebook.h"
+
+int phonebook_pullphonebook(obex_t *obex, obex_object_t *obj,
+				struct apparam_field params)
+{
+	return 0;
+}
+
+int phonebook_pullvcardlisting(obex_t *obex, obex_object_t *obj,
+				struct apparam_field params)
+{
+	return 0;
+}
+
+int phonebook_pullvcardentry(obex_t *obex, obex_object_t *obj,
+				struct apparam_field params)
+{
+	return 0;
+}
diff --git a/obexd/plugins/phonebook-ebook.c b/obexd/plugins/phonebook-ebook.c
new file mode 100644
index 0000000..cc9d016
--- /dev/null
+++ b/obexd/plugins/phonebook-ebook.c
@@ -0,0 +1,433 @@
+/*
+ *
+ *  OBEX Server
+ *
+ *  Copyright (C) 2009  Intel Corporation
+ *  Copyright (C) 2007-2009  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <glib.h>
+#include <bluetooth/bluetooth.h>
+
+#include <openobex/obex.h>
+#include <openobex/obex_const.h>
+
+#include <libebook/e-book.h>
+
+#include "logging.h"
+#include "obex.h"
+#include "service.h"
+#include "phonebook.h"
+
+#define EOL_CHARS "\n"
+#define VL_VERSION "<?xml version=\"1.0\"?>" EOL_CHARS
+#define VL_TYPE "<!DOCTYPE vcard-listing SYSTEM \"vcard-listing.dtd\">" EOL_CHARS
+#define VL_BODY_BEGIN "<vCard-listing version=\"1.0\">" EOL_CHARS
+#define VL_BODY_END "</vCard-listing>" EOL_CHARS
+#define VL_ELEMENT "<card handle = \"%d.vcf\" name = \"%s\"/>" EOL_CHARS
+
+#define QUERY_FAMILY_NAME "(contains \"family_name\" \"%s\")"
+#define QUERY_GIVEN_NAME "(contains \"given_name\" \"%s\")"
+#define QUERY_PHONE "(contains \"phone\" \"%s\")"
+
+struct phonebook_data {
+	obex_t *obex;
+	obex_object_t *obj;
+	struct apparam_field params;
+};
+
+static char *vcard_attribs[29] = { EVC_VERSION, EVC_FN, EVC_N, EVC_PHOTO,
+				EVC_BDAY, EVC_ADR, EVC_LABEL, EVC_TEL,
+				EVC_EMAIL, EVC_MAILER, NULL, EVC_GEO,
+				EVC_TITLE, EVC_ROLE, EVC_LOGO, NULL,
+				EVC_ORG, EVC_NOTE, EVC_REV, NULL, EVC_URL,
+				EVC_UID, EVC_KEY, EVC_NICKNAME, EVC_CATEGORIES,
+				EVC_PRODID, NULL, NULL, NULL };
+
+static void ebookpull_cb(EBook *book, EBookStatus status, GList *list,
+				gpointer user_data)
+{
+	struct phonebook_data *pb_data = user_data;
+	struct apparam_field *params = &pb_data->params;
+	struct obex_session *session = OBEX_GetUserData(pb_data->obex);
+	guint16 offset = 0, count = 0;
+	GList *contacts = list;
+	GString *pb;
+	gchar *result;
+	gint32 size;
+
+	pb = g_string_new(NULL);
+
+	/* Mandatory attributes for vCard 3.0 are VERSION, N, FN and TEL */
+	if (params->filter != 0 && params->format == EVC_FORMAT_VCARD_30)
+		params->filter |= 0x87;
+
+	for (; contacts != NULL; contacts = g_list_next(contacts)) {
+		EContact *contact = NULL;
+		EVCard *evcard = NULL, *evcard_filtered = NULL;
+		GList *attrib_list = NULL, *l;
+		char *vcard;
+
+		if (offset < params->liststartoffset) {
+			offset++;
+			continue;
+		}
+
+		if (count < params->maxlistcount)
+			count++;
+		else
+			break;
+
+		contact = E_CONTACT(contacts->data);
+		evcard = E_VCARD(contact);
+		attrib_list = e_vcard_get_attributes(evcard);
+
+		if (!params->filter) {
+			vcard = e_vcard_to_string(evcard, params->format);
+			goto done;
+		}
+
+		evcard_filtered = e_vcard_new();
+		for (l = attrib_list; l; l = l->next) {
+			int i;
+			const char *attrib_name = e_vcard_attribute_get_name(
+						(EVCardAttribute *)l->data);
+
+			for (i = 0; i <= 28; i++) {
+				int mask;
+
+				mask = 1 << i;
+				if (!(params->filter & mask))
+					continue;
+				if (g_strcmp0(vcard_attribs[i], attrib_name))
+					continue;
+				e_vcard_add_attribute(
+					evcard_filtered,
+					e_vcard_attribute_copy(
+					(EVCardAttribute *)l->data));
+				break;
+			}
+		}
+		vcard = e_vcard_to_string(evcard_filtered, params->format);
+		g_object_unref(evcard_filtered);
+
+done:		g_string_append_printf(pb, "%s\n", vcard);
+		g_free(vcard);
+	}
+
+	result = g_string_free(pb, FALSE);
+	size = strlen(result);
+
+	if (size != 0) {
+		session->buf = g_realloc(session->buf, session->size + size);
+		memcpy(session->buf + session->size, result, size);
+		session->size += size;
+	}
+
+	session->finished = 1;
+	OBEX_ResumeRequest(session->obex);
+
+	g_free(result);
+	g_free(pb_data);
+	g_object_unref(book);
+}
+
+int phonebook_pullphonebook(obex_t *obex, obex_object_t *obj,
+				struct apparam_field params)
+{
+	struct phonebook_data *pb_data;
+	EBook *book;
+	EBookQuery *query;
+
+	if (params.format != EVC_FORMAT_VCARD_30) {
+		DBG("libebook does not support e_vcard_to_string_vcard_21()");
+		return -1;
+	}
+
+	pb_data = g_new0(struct phonebook_data, 1);
+	pb_data->obex = obex;
+	pb_data->obj = obj;
+	pb_data->params = params;
+
+	book = e_book_new_default_addressbook(NULL);
+
+	e_book_open(book, FALSE, NULL);
+
+	query = e_book_query_any_field_contains("");
+
+	e_book_async_get_contacts(book, query, ebookpull_cb, pb_data);
+
+	e_book_query_unref(query);
+
+	OBEX_SuspendRequest(obex, obj);
+
+	return 0;
+}
+
+static void ebooklist_cb(EBook *book, EBookStatus status, GList *list,
+				gpointer user_data)
+{
+	struct phonebook_data *pb_data = user_data;
+	struct apparam_field *params = &pb_data->params;
+	struct obex_session *session = OBEX_GetUserData(pb_data->obex);
+	guint16 offset = 0, count = 0;
+	GString *listing;
+	GList *contacts = list;
+	gchar *result;
+	gint32 size;
+
+	listing = g_string_new(VL_VERSION);
+	listing = g_string_append(listing, VL_TYPE);
+	listing = g_string_append(listing, VL_BODY_BEGIN);
+
+	for (; contacts != NULL; contacts = g_list_next(contacts)) {
+		EContact *contact = NULL;
+		EVCard *evcard = NULL;
+		EVCardAttribute *name_attrib = NULL;
+		GList *name_values = NULL;
+		gchar *name = NULL, *name_part = NULL, *element = NULL;
+
+		if (offset < params->liststartoffset) {
+			offset++;
+			continue;
+		}
+
+		if (count < params->maxlistcount)
+			count++;
+		else
+			break;
+
+		contact = E_CONTACT(contacts->data);
+		evcard = E_VCARD(contact);
+		name_attrib = e_vcard_get_attribute(evcard, EVC_N);
+
+		if (name_attrib) {
+			name_values = e_vcard_attribute_get_values(name_attrib);
+			for (; name_values; name_values = name_values->next) {
+				if (!name_part) {
+					name_part = g_strdup(name_values->data);
+					continue;
+				}
+				name = g_strjoin(";", name_part,
+						name_values->data, NULL);
+				g_free(name_part);
+				name_part = name;
+			}
+
+			element = g_strdup_printf(VL_ELEMENT, offset, name);
+			listing = g_string_append(listing, element);
+
+			g_free(name);
+			g_free(element);
+		}
+
+		offset++;
+	}
+
+	listing = g_string_append(listing, VL_BODY_END);
+	result = g_string_free(listing, FALSE);
+	size = strlen(result);
+
+	if (size != 0) {
+		session->buf = g_realloc(session->buf, session->size + size);
+		memcpy(session->buf + session->size, result, size);
+		session->size += size;
+	}
+
+	session->finished = 1;
+	OBEX_ResumeRequest(session->obex);
+
+	g_free(result);
+	g_free(pb_data);
+	g_object_unref(book);
+}
+
+int phonebook_pullvcardlisting(obex_t *obex, obex_object_t *obj,
+				struct apparam_field params)
+{
+	struct phonebook_data *pb_data;
+	EBook *book;
+	EBookQuery *query = NULL, *query1 = NULL, *query2 = NULL;
+	gchar *str1 = NULL, *str2 = NULL;
+	gchar **value_list = NULL;
+
+	pb_data = g_new0(struct phonebook_data, 1);
+	pb_data->obex = obex;
+	pb_data->obj = obj;
+	pb_data->params = params;
+
+	book = e_book_new_default_addressbook(NULL);
+
+	e_book_open(book, FALSE, NULL);
+
+	/* All the vCards shall be returned if SearchValue header is
+	 * not specified */
+	if (!params.searchval || !strlen((char *) params.searchval)) {
+		query = e_book_query_any_field_contains("");
+		goto done;
+	}
+
+	if (params.searchattrib == 0) {
+		value_list = g_strsplit((gchar *) params.searchval, ";", 5);
+
+		if (value_list[0])
+			str1 = g_strdup_printf(QUERY_FAMILY_NAME,
+						value_list[0]);
+		if (value_list[1])
+			str2 = g_strdup_printf(QUERY_GIVEN_NAME, value_list[1]);
+
+		if (str1)
+			query1 = e_book_query_from_string(str1);
+		if (str2)
+			query2 = e_book_query_from_string(str2);
+		if (query1 && query2)
+			query = e_book_query_andv(query1, query2, NULL);
+		else
+			query = query1;
+	} else {
+		str1 = g_strdup_printf(QUERY_PHONE, params.searchval);
+		query = e_book_query_from_string((char *) params.searchval);
+	}
+
+done:
+	e_book_async_get_contacts(book, query, ebooklist_cb, pb_data);
+
+	g_free(str1);
+	g_free(str2);
+	if (query1 && query1 != query)
+		e_book_query_unref(query1);
+	if (query2)
+		e_book_query_unref(query2);
+	e_book_query_unref(query);
+	g_strfreev(value_list);
+
+	OBEX_SuspendRequest(obex, obj);
+
+	return 0;
+}
+
+static void ebookpullentry_cb(EBook *book, EBookStatus status, GList *list,
+                                gpointer user_data)
+{
+	struct phonebook_data *pb_data = user_data;
+	struct apparam_field *params = &pb_data->params;
+	struct obex_session *session = OBEX_GetUserData(pb_data->obex);
+	guint16 i = 0, index;
+	GList *contacts = list, *attrib_list = NULL, *l;
+	EContact *contact = NULL;
+	EVCard *evcard = NULL, *evcard_filtered = NULL;
+	gint32 size = 0;
+	char *vcard = NULL;
+
+	if (params->filter != 0 && params->format == EVC_FORMAT_VCARD_30)
+		params->filter |= 0x87;
+
+	sscanf(session->name, "%hu.vcf", &index);
+
+	for (; contacts != NULL; contacts = g_list_next(contacts)) {
+		if (i < index) {
+			i++;
+			continue;
+		}
+
+		contact = E_CONTACT(contacts->data);
+		evcard = E_VCARD(contact);
+
+		if (!params->filter) {
+			vcard = e_vcard_to_string(evcard, params->format);
+			break;
+		}
+
+		attrib_list = e_vcard_get_attributes(evcard);
+		evcard_filtered = e_vcard_new();
+		for (l = attrib_list; l; l = l->next) {
+			int i;
+			const char *attrib_name = e_vcard_attribute_get_name(
+						(EVCardAttribute *)l->data);
+			for (i = 0; i <= 28; i++) {
+				int mask;
+
+				mask = 1 << i;
+				if (!(params->filter & mask))
+					continue;
+				if (g_strcmp0(vcard_attribs[i], attrib_name))
+					continue;
+
+				e_vcard_add_attribute(
+					evcard_filtered,
+					e_vcard_attribute_copy(
+					(EVCardAttribute *)l->data));
+				 break;
+			}
+		}
+		vcard = e_vcard_to_string(evcard_filtered, params->format);
+		g_object_unref(evcard_filtered);
+		break;
+	}
+
+	if (vcard) {
+		size = strlen(vcard);
+		session->buf = g_realloc(session->buf, session->size + size);
+		memcpy(session->buf + session->size, vcard, size);
+		session->size += size;
+	}
+
+	session->finished = 1;
+	OBEX_ResumeRequest(session->obex);
+
+	g_free(vcard);
+	g_free(pb_data);
+	g_object_unref(book);
+}
+
+int phonebook_pullvcardentry(obex_t *obex, obex_object_t *obj,
+				struct apparam_field params)
+{
+	struct phonebook_data *pb_data;
+	EBook *book;
+	EBookQuery *query;
+
+	if (params.format != EVC_FORMAT_VCARD_30) {
+		DBG("libebook does not support e_vcard_to_string_vcard_21()");
+		return -1;
+	}
+
+	pb_data = g_new0(struct phonebook_data, 1);
+	pb_data->obex = obex;
+	pb_data->obj = obj;
+	pb_data->params = params;
+
+	book = e_book_new_default_addressbook(NULL);
+
+	e_book_open(book, FALSE, NULL);
+
+	query = e_book_query_any_field_contains("");
+
+	e_book_async_get_contacts(book, query, ebookpullentry_cb, pb_data);
+
+	OBEX_SuspendRequest(obex, obj);
+
+	return 0;
+}
diff --git a/obexd/plugins/phonebook.h b/obexd/plugins/phonebook.h
new file mode 100644
index 0000000..4d1c4c0
--- /dev/null
+++ b/obexd/plugins/phonebook.h
@@ -0,0 +1,39 @@
+/*
+ *
+ *  OBEX Server
+ *
+ *  Copyright (C) 2007-2009  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+struct apparam_field {
+	guint64		filter;
+	guint16		maxlistcount;
+	guint16		liststartoffset;
+	guint8		format;
+	guint8		order;
+	guint8		searchattrib;
+	guint8		*searchval;
+};
+
+int phonebook_pullphonebook(obex_t *obex, obex_object_t *obj,
+				struct apparam_field params);
+int phonebook_pullvcardlisting(obex_t *obex, obex_object_t *obj,
+				struct apparam_field params);
+int phonebook_pullvcardentry(obex_t *obex, obex_object_t *obj,
+				struct apparam_field params);
diff --git a/obexd/plugins/telephony-dummy.c b/obexd/plugins/telephony-dummy.c
new file mode 100644
index 0000000..9a4ec82
--- /dev/null
+++ b/obexd/plugins/telephony-dummy.c
@@ -0,0 +1,38 @@
+/*
+ *
+ *  OBEX Server
+ *
+ *  Copyright (C) 2009  Intel Corporation
+ *  Copyright (C) 2007-2009  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+
+#include "telephony.h"
+
+int telephony_pullmissedcalls(guint8 *missedcalls)
+{
+	*missedcalls = 0;
+
+	return 0;
+}
diff --git a/obexd/plugins/telephony.h b/obexd/plugins/telephony.h
new file mode 100644
index 0000000..8f9a4c0
--- /dev/null
+++ b/obexd/plugins/telephony.h
@@ -0,0 +1,25 @@
+/*
+ *
+ *  OBEX Server
+ *
+ *  Copyright (C) 2007-2009  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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 General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+
+int telephony_pullmissedcalls(guint8 *missedcalls);