From 2e2c48dfc234088c664d663233beb31521819e0a Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Mon, 1 Mar 2010 17:09:18 -0300 Subject: [PATCH] obexd: Initial support for mimetype drivers on PBAP Initial step to convert the current PBAP implementation to mimetype driver approach. This patch breaks ebook driver support temporarily. --- obexd/plugins/filesystem.c | 7 +- obexd/plugins/filesystem.h | 25 ++ obexd/plugins/ftp.c | 2 +- obexd/plugins/opp.c | 2 +- obexd/plugins/pbap.c | 445 ++++++++++++-------------------- obexd/plugins/phonebook-dummy.c | 43 ++- obexd/plugins/phonebook-ebook.c | 383 +++------------------------ obexd/plugins/phonebook.h | 15 +- obexd/plugins/syncevolution.c | 2 +- obexd/src/obex.c | 2 +- obexd/src/service.h | 2 +- 11 files changed, 277 insertions(+), 651 deletions(-) create mode 100644 obexd/plugins/filesystem.h diff --git a/obexd/plugins/filesystem.c b/obexd/plugins/filesystem.c index dcc03ff2f..9775bcbef 100644 --- a/obexd/plugins/filesystem.c +++ b/obexd/plugins/filesystem.c @@ -49,6 +49,7 @@ #include "obex.h" #include "mimetype.h" #include "service.h" +#include "filesystem.h" #define EOL_CHARS "\n" @@ -409,7 +410,7 @@ failed: return NULL; } -static int string_free(gpointer object) +int string_free(gpointer object) { GString *string = object; @@ -418,7 +419,7 @@ static int string_free(gpointer object) return 0; } -static ssize_t string_read(gpointer object, void *buf, size_t count) +ssize_t string_read(gpointer object, void *buf, size_t count) { GString *string = object; ssize_t len; @@ -426,7 +427,7 @@ static ssize_t string_read(gpointer object, void *buf, size_t count) if (string->len == 0) return 0; - len = count > string->len ? string->len : count; + len = MIN(string->len, count); memcpy(buf, string->str, len); string = g_string_erase(string, 0, len); diff --git a/obexd/plugins/filesystem.h b/obexd/plugins/filesystem.h new file mode 100644 index 000000000..636ddb27a --- /dev/null +++ b/obexd/plugins/filesystem.h @@ -0,0 +1,25 @@ +/* + * + * OBEX Server + * + * Copyright (C) 2007-2010 Marcel Holtmann + * + * + * 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 string_free(gpointer object); +ssize_t string_read(gpointer object, void *buf, size_t count); diff --git a/obexd/plugins/ftp.c b/obexd/plugins/ftp.c index fe775f455..0bd5a5ec1 100644 --- a/obexd/plugins/ftp.c +++ b/obexd/plugins/ftp.c @@ -193,7 +193,7 @@ static obex_rsp_t ftp_connect(struct OBEX_session *os) return OBEX_RSP_SUCCESS; } -static obex_rsp_t ftp_get(struct OBEX_session *os) +static obex_rsp_t ftp_get(struct OBEX_session *os, obex_object_t *obj) { const char *folder = obex_get_folder(os); const char *type = obex_get_type(os); diff --git a/obexd/plugins/opp.c b/obexd/plugins/opp.c index d003f218a..3325d0820 100644 --- a/obexd/plugins/opp.c +++ b/obexd/plugins/opp.c @@ -151,7 +151,7 @@ static obex_rsp_t opp_put(struct OBEX_session *os) return OBEX_RSP_SUCCESS; } -static obex_rsp_t opp_get(struct OBEX_session *os) +static obex_rsp_t opp_get(struct OBEX_session *os, obex_object_t *obj) { const char *type; diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c index 53d4a9c22..2a7d6d16d 100644 --- a/obexd/plugins/pbap.c +++ b/obexd/plugins/pbap.c @@ -29,6 +29,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include @@ -40,6 +45,8 @@ #include "service.h" #include "phonebook.h" #include "telephony.h" +#include "mimetype.h" +#include "filesystem.h" #include "dbus.h" #define PHONEBOOK_TYPE "x-bt/phonebook" @@ -127,257 +134,16 @@ struct apparam_hdr { uint8_t val[0]; } __attribute__ ((packed)); +struct phonebook_query { + const char *type; + GString *buffer; + struct OBEX_session *os; +}; + static const guint8 PBAP_TARGET[TARGET_SIZE] = { 0x79, 0x61, 0x35, 0xF0, 0xF0, 0xC5, 0x11, 0xD8, 0x09, 0x66, 0x08, 0x00, 0x20, 0x0C, 0x9A, 0x66 }; -static int pbap_parse_apparam_header(obex_t *obex, obex_object_t *obj, - struct apparam_field *apparam) -{ - obex_headerdata_t hd; - guint8 hi; - guint32 hlen; - - while (OBEX_ObjectGetNextHeader(obex, obj, &hi, &hd, &hlen)) { - void *ptr = (void *) hd.bs; - uint32_t len = hlen; - - if (hi != OBEX_HDR_APPARAM) - continue; - - if (hlen < APPARAM_HDR_SIZE) { - g_free(apparam->searchval); - error("PBAP pullphonebook app parameters header" - " is too short: %d", hlen); - return -1; - } - - while (len > APPARAM_HDR_SIZE) { - struct apparam_hdr *hdr = ptr; - - if (hdr->len > len - APPARAM_HDR_SIZE) { - g_free(apparam->searchval); - error("Unexpected PBAP pullphonebook app" - " length, tag %d, len %d", - hdr->tag, hdr->len); - return -1; - } - - switch (hdr->tag) { - case ORDER_TAG: - if (hdr->len == ORDER_LEN) - apparam->order = hdr->val[0]; - break; - case SEARCHATTRIB_TAG: - if (hdr->len == SEARCHATTRIB_LEN) - apparam->searchattrib = hdr->val[0]; - break; - case SEARCHVALUE_TAG: - apparam->searchval = g_try_malloc(hdr->len + 1); - if (apparam->searchval != NULL) { - memcpy(apparam->searchval, hdr->val, - hdr->len); - apparam->searchval[hdr->len] = '\0'; - } - break; - case FILTER_TAG: - if (hdr->len == FILTER_LEN) { - guint64 val; - memcpy(&val, hdr->val, sizeof(val)); - apparam->filter = get_be64(&val); - } - break; - case FORMAT_TAG: - if (hdr->len == FORMAT_LEN) - apparam->format = hdr->val[0]; - break; - case MAXLISTCOUNT_TAG: - if (hdr->len == MAXLISTCOUNT_LEN) { - guint16 val; - memcpy(&val, hdr->val, sizeof(val)); - apparam->maxlistcount = get_be16(&val); - } - break; - case LISTSTARTOFFSET_TAG: - if (hdr->len == LISTSTARTOFFSET_LEN) { - guint16 val; - memcpy(&val, hdr->val, sizeof(val)); - apparam->liststartoffset = get_be16(&val); - } - break; - default: - g_free(apparam->searchval); - error("Unexpected PBAP pullphonebook app" - " parameter, tag %d, len %d", - hdr->tag, hdr->len); - return -1; - } - - ptr += APPARAM_HDR_SIZE + hdr->len; - len -= APPARAM_HDR_SIZE + hdr->len; - } - - /* Ignore multiple app param headers */ - break; - } - - return 0; -} - -/* Add app parameter header, that is sent back to PBAP client */ -static int pbap_add_result_apparam_header(obex_t *obex, obex_object_t *obj, - guint16 maxlistcount, gchar *path_name, - guint16 phonebooksize, - guint8 newmissedcalls, gboolean *addbody) -{ - guint8 rspsize = 0; - gboolean addmissedcalls = FALSE; - obex_headerdata_t hd; - - if (maxlistcount == 0) { - rspsize += APPARAM_HDR_SIZE + PHONEBOOKSIZE_LEN; - *addbody = FALSE; - } - - if (g_str_equal(path_name, SIM1_MCH) == TRUE || - g_str_equal(path_name, MCH) == TRUE) { - rspsize += APPARAM_HDR_SIZE + NEWMISSEDCALLS_LEN; - addmissedcalls = TRUE; - } - - if (rspsize > 0) { - void *buf, *ptr; - - buf = g_try_malloc0(rspsize); - if (buf == NULL) - return -ENOMEM; - - ptr = buf; - - if (maxlistcount == 0) { - struct apparam_hdr *hdr = ptr; - guint16 val = GUINT16_TO_BE(phonebooksize); - - hdr->tag = PHONEBOOKSIZE_TAG; - hdr->len = PHONEBOOKSIZE_LEN; - memcpy(hdr->val, &val, sizeof(val)); - - ptr += APPARAM_HDR_SIZE + PHONEBOOKSIZE_LEN; - } - - if (addmissedcalls == TRUE) { - struct apparam_hdr *hdr = ptr; - - hdr->tag = NEWMISSEDCALLS_TAG; - hdr->len = NEWMISSEDCALLS_LEN; - hdr->val[0] = newmissedcalls; - - ptr += APPARAM_HDR_SIZE + NEWMISSEDCALLS_LEN; - } - - hd.bs = buf; - OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_APPARAM, - hd, rspsize, 0); - g_free(buf); - } - - return 0; -} - -static int pbap_pullphonebook(obex_t *obex, obex_object_t *obj, - gboolean *addbody) -{ - struct obex_session *session = OBEX_GetUserData(obex); - struct apparam_field params; - guint8 newmissedcalls = 0; - guint16 phonebooksize = 0; - int err; - - memset(¶ms, 0, sizeof(struct apparam_field)); - - err = pbap_parse_apparam_header(obex, obj, ¶ms); - if (err < 0) - return err; - - if (params.maxlistcount == 0) { - phonebooksize = DEFAULT_COUNT; - goto done; - } - - err = phonebook_pullphonebook(obex, obj, params); - if (err < 0) - return err; - -done: - return pbap_add_result_apparam_header(obex, obj, params.maxlistcount, - session->name, phonebooksize, - newmissedcalls, addbody); -} - -static int pbap_pullvcardlisting(obex_t *obex, obex_object_t *obj, - gboolean *addbody) -{ - struct obex_session *session = OBEX_GetUserData(obex); - gchar *fullname; - struct apparam_field params; - guint8 newmissedcalls = 0; - guint16 phonebooksize = 0; - int err; - - memset(¶ms, 0, sizeof(struct apparam_field)); - - err = pbap_parse_apparam_header(obex, obj, ¶ms); - if (err < 0) - return err; - - if (params.maxlistcount == 0) { - phonebooksize = DEFAULT_COUNT; - goto proceed; - } - - /* libebook does not support sound attribute */ - if (params.searchattrib >= 2) { - DBG("libebook does not support sound attribute"); - goto done; - } - - err = phonebook_pullvcardlisting(obex, obj, params); - if (err < 0) - goto done; - -proceed: - - fullname = g_build_filename(session->current_folder, session->name, - NULL); - if (fullname != NULL) - fullname = g_strconcat(fullname, ".vcf", NULL); - - err = pbap_add_result_apparam_header(obex, obj, params.maxlistcount, - fullname, phonebooksize, - newmissedcalls, addbody); - g_free(fullname); - -done: - g_free(params.searchval); - return err; -} - -static int pbap_pullvcardentry(obex_t *obex, obex_object_t *obj) -{ - struct apparam_field params; - int err; - - memset(¶ms, 0, sizeof(struct apparam_field)); - err = pbap_parse_apparam_header(obex, obj, ¶ms); - if (err < 0) - return err; - - err = phonebook_pullvcardentry(obex, obj, params); - - g_free(params.searchval); - return err; -} - static obex_rsp_t pbap_connect(struct OBEX_session *os) { manager_register_session(os); @@ -385,56 +151,47 @@ static obex_rsp_t pbap_connect(struct OBEX_session *os) return OBEX_RSP_SUCCESS; } -static obex_rsp_t pbap_get(struct OBEX_session *os) +static obex_rsp_t pbap_get(struct OBEX_session *os, obex_object_t *obj) { - int addbody = TRUE; - const char *type = obex_get_type(os); - const char *name = obex_get_name(os); - int err; + const gchar *type = obex_get_type(os); + const gchar *folder = obex_get_folder(os); + const gchar *name = obex_get_name(os); + gchar *path; + gint ret; if (type == NULL) - goto fail; + return OBEX_RSP_BAD_REQUEST; - if (g_str_equal(type, VCARDLISTING_TYPE) == FALSE - && name == NULL) - goto fail; + if (strcmp(type, PHONEBOOK_TYPE) == 0) + /* Always contains the absolute path */ + path = g_strdup(name); + else if (strcmp(type, VCARDLISTING_TYPE) == 0) + /* Always relative */ + if (!name || strlen(name) == 0) + /* Current folder */ + path = g_strdup(folder); + else + /* Current folder + relative path */ + path = g_build_filename(folder, name, NULL); - /* FIXME: broken */ -#if 0 - OBEX_ObjectReParseHeaders(, obj); -#endif - if (g_str_equal(type, PHONEBOOK_TYPE) == TRUE) - err = pbap_pullphonebook(NULL, NULL, NULL); - else if (g_str_equal(type, VCARDLISTING_TYPE) == TRUE) - err = pbap_pullvcardlisting(NULL, NULL, NULL); - else if (g_str_equal(type, VCARDENTRY_TYPE) == TRUE) - err = pbap_pullvcardentry(NULL, NULL); + else if (strcmp(type, VCARDENTRY_TYPE) == 0) + /* Always relative */ + path = g_build_filename(folder, name, NULL); else - goto fail; + return OBEX_RSP_BAD_REQUEST; - if (err < 0) - goto fail; + ret = obex_stream_start(os, path); + g_free(path); - if (addbody == TRUE) { -#if 0 - OBEX_SuspendRequest(obex, obj); - session->size = 0; + switch (ret) { + case 0: + return OBEX_RSP_SUCCESS; + case -ENOENT: + return OBEX_RSP_NOT_FOUND; + default: + return OBEX_RSP_FORBIDDEN; - /* Add body header */ - hd.bs = NULL; - OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY, - hd, 0, OBEX_FL_STREAM_START); -#endif } - -#if 0 - OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); -#endif - - return OBEX_RSP_SUCCESS; - -fail: - return OBEX_RSP_FORBIDDEN; } static gboolean pbap_is_valid_folder(struct obex_session *session) @@ -555,14 +312,128 @@ struct obex_service_driver pbap = { .chkput = pbap_chkput }; +static void query_result(const gchar *buffer, size_t bufsize, + gint vcards, gint missed, gpointer user_data) +{ + struct phonebook_query *query = user_data; + + if (!query->buffer) + query->buffer = g_string_new_len(buffer, bufsize); + else + query->buffer = g_string_append_len(query->buffer, buffer, bufsize); + + obex_object_set_io_flags(query, G_IO_IN, 0); +} + +static gpointer vobject_open(const char *name, int oflag, mode_t mode, + size_t *size, struct OBEX_session *os, int *err) +{ + const gchar *type = obex_get_type(os); + struct phonebook_query *query; + + if (oflag != O_RDONLY) + goto fail; + + /* TODO: mch? */ + + /* TODO: get application parameter */ + query = g_new0(struct phonebook_query, 1); + query->type = type; + query->os = os; + + if (phonebook_query(name, query_result, query) < 0) { + g_free(query); + goto fail; + } + + if (size) + *size = 1; + + return query; + +fail: + if (err) + *err = -EPERM; + + return NULL; +} + +static ssize_t vobject_read(gpointer object, void *buf, size_t count) +{ + struct phonebook_query *query = object; + + if (query->buffer) + return string_read(query->buffer, buf, count); + + return -EAGAIN; +} + +static int vobject_close(gpointer object) +{ + struct phonebook_query *query = object; + + if (query->buffer) + string_free(query->buffer); + + g_free(query); + + return 0; +} + +struct obex_mime_type_driver mime_pull = { + .target = PBAP_TARGET, + .mimetype = "x-bt/phonebook", + .open = vobject_open, + .close = vobject_close, + .read = vobject_read, +}; + +struct obex_mime_type_driver mime_list = { + .target = PBAP_TARGET, + .mimetype = "x-bt/vcard-listing", + .open = vobject_open, + .close = vobject_close, + .read = vobject_read, +}; + +struct obex_mime_type_driver mime_vcard = { + .target = PBAP_TARGET, + .mimetype = "x-bt/vcard", + .open = vobject_open, + .close = vobject_close, + .read = vobject_read, +}; + static int pbap_init(void) { + int err; + + err = phonebook_init(); + if (err < 0) + return err; + + err = obex_mime_type_driver_register(&mime_pull); + if (err < 0) + return err; + + err = obex_mime_type_driver_register(&mime_list); + if (err < 0) + return err; + + err = obex_mime_type_driver_register(&mime_vcard); + if (err < 0) + return err; + return obex_service_driver_register(&pbap); } static void pbap_exit(void) { obex_service_driver_unregister(&pbap); + obex_mime_type_driver_unregister(&mime_pull); + obex_mime_type_driver_unregister(&mime_list); + obex_mime_type_driver_unregister(&mime_vcard); + phonebook_exit(); } OBEX_PLUGIN_DEFINE(pbap, pbap_init, pbap_exit) diff --git a/obexd/plugins/phonebook-dummy.c b/obexd/plugins/phonebook-dummy.c index df3760c4e..38b2803f1 100644 --- a/obexd/plugins/phonebook-dummy.c +++ b/obexd/plugins/phonebook-dummy.c @@ -26,27 +26,56 @@ #include #endif +#include #include #include #include +#include "logging.h" #include "phonebook.h" -int phonebook_pullphonebook(obex_t *obex, obex_object_t *obj, - struct apparam_field params) +#define VCARD0 \ + "BEGIN:VCARD\n" \ + "VERSION:3.0\n" \ + "N:Klaus;Santa\n" \ + "FN:\n" \ + "TEL:+001122334455\n" \ + "END:VCARD\n" + + +struct dummy_data { + phonebook_cb cb; + gpointer user_data; +}; + +int phonebook_init(void) { return 0; } -int phonebook_pullvcardlisting(obex_t *obex, obex_object_t *obj, - struct apparam_field params) +void phonebook_exit(void) { - return 0; } -int phonebook_pullvcardentry(obex_t *obex, obex_object_t *obj, - struct apparam_field params) +static gboolean dummy_result(gpointer data) { + struct dummy_data *dummy = data; + + dummy->cb(VCARD0, strlen(VCARD0), 1, 0, dummy->user_data); + + return FALSE; +} + +int phonebook_query(const gchar *name, phonebook_cb cb, gpointer user_data) +{ + struct dummy_data *dummy; + + dummy = g_new0(struct dummy_data, 1); + dummy->cb = cb; + dummy->user_data = user_data; + + g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, + dummy_result, dummy, g_free); return 0; } diff --git a/obexd/plugins/phonebook-ebook.c b/obexd/plugins/phonebook-ebook.c index b25ce25bf..e1a7996ad 100644 --- a/obexd/plugins/phonebook-ebook.c +++ b/obexd/plugins/phonebook-ebook.c @@ -52,380 +52,77 @@ #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; +struct query_data { + phonebook_cb cb; + gpointer user_data; }; -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 EBook *ebook = NULL; -static void ebookpull_cb(EBook *book, EBookStatus status, GList *list, +static void ebookpull_cb(EBook *book, EBookStatus status, GList *contacts, 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; + struct query_data *data = user_data; + GString *string = g_string_new(""); + GList *l; - 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; + for (l = contacts; l; l = g_list_next(l)) { + EContact *contact; + EVCard *evcard; + gchar *vcard; 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); + vcard = e_vcard_to_string(evcard, EVC_FORMAT_VCARD_30); + string = g_string_append(string, 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); + data->cb(string->str, string->len, + g_list_length(contacts), 0, data->user_data); } -int phonebook_pullphonebook(obex_t *obex, obex_object_t *obj, - struct apparam_field params) +int phonebook_init(void) { - 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; + GError *gerr = NULL; + + ebook = e_book_new_default_addressbook(&gerr); + if (!ebook) { + error("Can't create user's default address book: %s", + gerr->message); + g_error_free(gerr); + return -EIO; } - 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++; + if (!e_book_open(ebook, FALSE, &gerr)) { + error("Can't open e-book address book: %s", gerr->message); + g_error_free(gerr); + return -EIO; } - 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) +void phonebook_exit(void) { - 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); + if (ebook) + g_object_unref(ebook); } -int phonebook_pullvcardentry(obex_t *obex, obex_object_t *obj, - struct apparam_field params) +int phonebook_query(const gchar *name, phonebook_cb cb, gpointer user_data) { - struct phonebook_data *pb_data; - EBook *book; + struct query_data *data; 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); + data = g_new0(struct query_data, 1); + data->cb = cb; + data->user_data = user_data; - OBEX_SuspendRequest(obex, obj); + e_book_async_get_contacts(ebook, query, ebookpull_cb, data); + + e_book_query_unref(query); return 0; } diff --git a/obexd/plugins/phonebook.h b/obexd/plugins/phonebook.h index cc5743ede..dc8e5e008 100644 --- a/obexd/plugins/phonebook.h +++ b/obexd/plugins/phonebook.h @@ -31,9 +31,12 @@ struct apparam_field { 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); +typedef void (*phonebook_cb) (const gchar *buffer, size_t bufsize, + gint vcards, gint missed, gpointer user_data); + +int phonebook_init(void); +void phonebook_exit(void); + +int phonebook_setfolder(const gchar *name); + +int phonebook_query(const gchar *name, phonebook_cb cb, gpointer user_data); diff --git a/obexd/plugins/syncevolution.c b/obexd/plugins/syncevolution.c index 5f7895242..60cd15d8b 100644 --- a/obexd/plugins/syncevolution.c +++ b/obexd/plugins/syncevolution.c @@ -392,7 +392,7 @@ static obex_rsp_t synce_put(struct OBEX_session *os) return OBEX_RSP_SUCCESS; } -static obex_rsp_t synce_get(struct OBEX_session *os) +static obex_rsp_t synce_get(struct OBEX_session *os, obex_object_t *obj) { struct synce_context *context; diff --git a/obexd/src/obex.c b/obexd/src/obex.c index 0484523d4..0b0c0f2d0 100644 --- a/obexd/src/obex.c +++ b/obexd/src/obex.c @@ -364,7 +364,7 @@ static void cmd_get(struct obex_session *os, obex_t *obex, obex_object_t *obj) } } - rsp = os->service->get(os); + rsp = os->service->get(os, obj); if (rsp == OBEX_RSP_SUCCESS) { hd.bq4 = os->size; OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_LENGTH, hd, 4, 0); diff --git a/obexd/src/service.h b/obexd/src/service.h index 4bd78fe13..b6fc28936 100644 --- a/obexd/src/service.h +++ b/obexd/src/service.h @@ -34,7 +34,7 @@ struct obex_service_driver { const gchar *record; obex_rsp_t (*connect) (struct OBEX_session *os); void (*progress) (struct OBEX_session *os); - obex_rsp_t (*get) (struct OBEX_session *os); + obex_rsp_t (*get) (struct OBEX_session *os, obex_object_t *obj); obex_rsp_t (*put) (struct OBEX_session *os); gint (*chkput) (struct OBEX_session *os); obex_rsp_t (*setpath) (struct OBEX_session *os, obex_object_t *obj); -- 2.47.3