summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.dentz@openbossa.org>2009-10-30 16:16:28 -0300
committerJohan Hedberg <johan.hedberg@nokia.com>2009-11-03 17:06:17 +0200
commit69a62bd3bd44cfc965edf15d592407da3ebee44f (patch)
tree74dea5ca7c050f7373c3970e6824171ccad4dcd0
parenta9e02bf5b5b3dbbcc5f0072bb14d9badcf55bd0d (diff)
downloadobexd-69a62bd3bd44cfc965edf15d592407da3ebee44f.tar.gz
Introduce phonebook and telephony drivers.
Those will be used by pbap plugin which is now builtin as opp and ftp and can be set on build time using --with-phonebook and --with-telephony (default are dummy drivers) e.g: ./configure --with-phonebook=ebook This will expand to plugins/phonebook-ebook.c which then will be linked as plugins/phonebook.c.
-rw-r--r--Makefile.am27
-rwxr-xr-xbootstrap-configure2
-rw-r--r--configure.ac18
-rw-r--r--plugins/pbap.c (renamed from plugins/ebook.c)423
-rw-r--r--plugins/phonebook-dummy.c52
-rw-r--r--plugins/phonebook-ebook.c433
-rw-r--r--plugins/phonebook.h39
-rw-r--r--plugins/telephony-dummy.c38
-rw-r--r--plugins/telephony.h25
9 files changed, 626 insertions, 431 deletions
diff --git a/Makefile.am b/Makefile.am
index 20b0feb..f5ca3b1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,6 +38,11 @@ builtin_sources += plugins/opp.c
builtin_modules += ftp
builtin_sources += plugins/ftp.c
+builtin_modules += pbap
+builtin_sources += plugins/pbap.c
+
+builtin_nodist += plugins/phonebook.c plugins/telephony.c
+
libexec_PROGRAMS += src/obexd
src_obexd_SOURCES = $(gdbus_sources) $(builtin_sources) \
@@ -49,7 +54,8 @@ src_obexd_SOURCES = $(gdbus_sources) $(builtin_sources) \
src/service.h src/service.c
src_obexd_LDADD = @DBUS_LIBS@ @GLIB_LIBS@ @GTHREAD_LIBS@ \
- @OPENOBEX_LIBS@ @BLUEZ_LIBS@ -ldl
+ @EBOOK_LIBS@ @OPENOBEX_LIBS@ \
+ @BLUEZ_LIBS@ -ldl
src_obexd_LDFLAGS = -Wl,--export-dynamic
@@ -61,17 +67,6 @@ plugindir = $(libdir)/obex/plugins
plugin_LTLIBRARIES =
-if EBOOK
-plugin_LTLIBRARIES += plugins/ebook.la
-
-plugins_ebook_la_SOURCES = plugins/ebook.c
-
-plugins_ebook_la_LIBADD = @EBOOK_LIBS@
-
-plugins_ebook_la_CFLAGS = -fvisibility=hidden @EBOOK_CFLAGS@
-plugins_ebook_la_LDFLAGS = -no-undefined -module -avoid-version
-endif
-
noinst_PROGRAMS = test/obex-test
test_obex_test_SOURCES = $(gwobex_sources) test/main.c
@@ -100,7 +95,7 @@ endif
service_DATA = $(service_in_files:.service.in=.service)
-AM_CFLAGS = @OPENOBEX_CFLAGS@ @BLUEZ_CFLAGS@ \
+AM_CFLAGS = @OPENOBEX_CFLAGS@ @BLUEZ_CFLAGS@ @EBOOK_CFLAGS@ \
@GTHREAD_CFLAGS@ @GLIB_CFLAGS@ @DBUS_CFLAGS@ \
-DOBEX_PLUGIN_BUILTIN -DPLUGINDIR=\""$(plugindir)"\"
@@ -119,3 +114,9 @@ MAINTAINERCLEANFILES = Makefile.in \
%.service: %.service.in config.log
$(AM_V_GEN)$(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
+
+plugins/phonebook.c: plugins/@PHONEBOOK_DRIVER@
+ $(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
+
+plugins/telephony.c: plugins/@TELEPHONY_DRIVER@
+ $(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
diff --git a/bootstrap-configure b/bootstrap-configure
index 6f7c0d4..73e993a 100755
--- a/bootstrap-configure
+++ b/bootstrap-configure
@@ -11,4 +11,4 @@ fi
--libexec=/usr/lib/obex \
--mandir=/usr/share/man \
--sysconfdir=/etc \
- --enable-ebook $*
+ --with-phonebook=ebook $*
diff --git a/configure.ac b/configure.ac
index 587edbd..39ab903 100644
--- a/configure.ac
+++ b/configure.ac
@@ -103,13 +103,12 @@ AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],
fi
])
-AC_ARG_ENABLE(ebook, AC_HELP_STRING([--enable-ebook],
- [enable EBook plugin]), [
- enable_ebook=${enableval}
+phonebook_driver=dummy
+AC_ARG_WITH(phonebook, AC_HELP_STRING([--with-phonebook=DRIVER], [select phonebook driver]), [
+ phonebook_driver=${withval}
])
-AM_CONDITIONAL(EBOOK, test "${enable_ebook}" = "yes")
-if (test "${enable_ebook}" = "yes"); then
+if (test "${phonebook_driver}" = "ebook"); then
AC_DEFINE(NEED_THREADS, 1, [Define if threading support is required])
PKG_CHECK_MODULES(EBOOK, libebook-1.2, dummy=yes,
@@ -123,6 +122,15 @@ if (test "${enable_ebook}" = "yes"); then
AC_SUBST(GTHREAD_LIBS)
fi
+AC_SUBST([PHONEBOOK_DRIVER], [phonebook-${phonebook_driver}.c])
+
+telephony_driver=dummy
+AC_ARG_WITH(telephony, AC_HELP_STRING([--with-telephony=DRIVER], [select telephony driver]), [
+ telephony_driver=${withval}
+])
+
+AC_SUBST([TELEPHONY_DRIVER], [telephony-${telephony_driver}.c])
+
AC_ARG_ENABLE(server, AC_HELP_STRING([--disable-server],
[disable compilation of OBEX server]), [
enable_server=${enableval}
diff --git a/plugins/ebook.c b/plugins/pbap.c
index a5b43c8..c553deb 100644
--- a/plugins/ebook.c
+++ b/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/plugins/phonebook-dummy.c b/plugins/phonebook-dummy.c
new file mode 100644
index 0000000..abcdce7
--- /dev/null
+++ b/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/plugins/phonebook-ebook.c b/plugins/phonebook-ebook.c
new file mode 100644
index 0000000..cc9d016
--- /dev/null
+++ b/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/plugins/phonebook.h b/plugins/phonebook.h
new file mode 100644
index 0000000..4d1c4c0
--- /dev/null
+++ b/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/plugins/telephony-dummy.c b/plugins/telephony-dummy.c
new file mode 100644
index 0000000..9a4ec82
--- /dev/null
+++ b/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/plugins/telephony.h b/plugins/telephony.h
new file mode 100644
index 0000000..8f9a4c0
--- /dev/null
+++ b/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);