From 581b305d17b53397ea7abc0d614b64811f2d27cf Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 31 Mar 2010 19:10:26 -0300 Subject: [PATCH] obexd: Changes the interface between the PBAP core and backends Removes phonebook vcard list operation in the backends. Adds initial functions to build the contacts cache. Adds phonebook pull vcard for ebook integrated with the cache information. --- obexd/plugins/filesystem.c | 19 ++- obexd/plugins/filesystem.h | 2 +- obexd/plugins/pbap.c | 270 ++++++++++++++++++++------------ obexd/plugins/phonebook-dummy.c | 8 +- obexd/plugins/phonebook-ebook.c | 200 +++++++++++------------ obexd/plugins/phonebook.h | 41 ++++- obexd/plugins/syncevolution.c | 6 +- 7 files changed, 336 insertions(+), 210 deletions(-) diff --git a/obexd/plugins/filesystem.c b/obexd/plugins/filesystem.c index f94dd736c..168058bb8 100644 --- a/obexd/plugins/filesystem.c +++ b/obexd/plugins/filesystem.c @@ -468,13 +468,11 @@ int string_free(gpointer object) return 0; } -ssize_t string_read(gpointer object, void *buf, size_t count, guint8 *hi) +ssize_t string_read(gpointer object, void *buf, size_t count) { GString *string = object; ssize_t len; - *hi = OBEX_HDR_BODY; - if (string->len == 0) return 0; @@ -485,18 +483,25 @@ ssize_t string_read(gpointer object, void *buf, size_t count, guint8 *hi) return len; } +static ssize_t folder_read(gpointer object, void *buf, size_t count, guint8 *hi) +{ + *hi = OBEX_HDR_BODY; + return string_read(object, buf, count); +} + static ssize_t capability_read(gpointer object, void *buf, size_t count, guint8 *hi) { struct capability_object *obj = object; + *hi = OBEX_HDR_BODY; + if (obj->buffer) - return string_read(obj->buffer, buf, count, hi); + return string_read(obj->buffer, buf, count); if (obj->pid >= 0) return -EAGAIN; - *hi = OBEX_HDR_BODY; return read(obj->output, buf, count); } @@ -539,7 +544,7 @@ static struct obex_mime_type_driver folder = { .mimetype = "x-obex/folder-listing", .open = folder_open, .close = string_free, - .read = string_read, + .read = folder_read, }; static struct obex_mime_type_driver pcsuite = { @@ -549,7 +554,7 @@ static struct obex_mime_type_driver pcsuite = { .mimetype = "x-obex/folder-listing", .open = pcsuite_open, .close = string_free, - .read = string_read, + .read = folder_read, }; static int filesystem_init(void) diff --git a/obexd/plugins/filesystem.h b/obexd/plugins/filesystem.h index 1e1b352aa..636ddb27a 100644 --- a/obexd/plugins/filesystem.h +++ b/obexd/plugins/filesystem.h @@ -22,4 +22,4 @@ */ int string_free(gpointer object); -ssize_t string_read(gpointer object, void *buf, size_t count, guint8 *hi); +ssize_t string_read(gpointer object, void *buf, size_t count); diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c index f7b7b9bce..af6ae3933 100644 --- a/obexd/plugins/pbap.c +++ b/obexd/plugins/pbap.c @@ -26,6 +26,7 @@ #include #endif +#include #include #include #include @@ -75,10 +76,6 @@ #define MCH "telecom/mch.vcf" #define SIM1_MCH "SIM1/telecom/mch.vcf" -#define DEFAULT_COUNT 65535 - -#define APPARAM_HDR_SIZE 2 - #define PBAP_CHANNEL 15 #define PBAP_RECORD " \ @@ -130,12 +127,15 @@ struct aparam_header { struct cache { gboolean ready; + gboolean valid; + guint32 index; + gchar *folder; GSList *entries; }; struct cache_entry { - gchar *handle; - gpointer id; + guint32 handle; + gchar *id; gchar *name; gchar *sound; gchar *tel; @@ -145,7 +145,6 @@ struct pbap_session { struct apparam_field *params; gchar *folder; GString *buffer; - guint16 phonebooksize; struct cache cache; }; @@ -156,24 +155,15 @@ static const guint8 PBAP_TARGET[TARGET_SIZE] = { typedef int (*cache_sort_f) (struct cache_entry *entry, gpointer user_data); typedef void (*cache_element_f) (struct cache_entry *entry, gpointer user_data); -static gint entry_handle_cmp(gconstpointer a, gconstpointer b) -{ - const struct cache_entry *entry = a; - const char* handle = b; - - return strcmp(entry->handle, handle); -} - static void cache_entry_free(struct cache_entry *entry) { - g_free(entry->handle); g_free(entry->id); g_free(entry->name); g_free(entry->sound); g_free(entry->tel); g_free(entry); } - +#if 0 static void cache_foreach(struct cache *cache, cache_sort_f sort, cache_element_f elem, gpointer user_data) { @@ -188,28 +178,25 @@ static void cache_foreach(struct cache *cache, cache_sort_f sort, elem(entry, user_data); } } +#endif -static gpointer cache_find(struct cache *cache, const gchar *handle) +static const gchar *cache_find(struct cache *cache, guint32 handle) { - struct cache_entry *entry; GSList *l; - l = g_slist_find_custom(cache->entries, handle, entry_handle_cmp); - if (!l) - return NULL; - - entry = l->data; + for (l = cache->entries; l; l = l->next) { + struct cache_entry *entry = l->data; - return entry->id; -} + if (entry->handle == handle) + return entry->id; + } -static void cache_add(struct cache *cache, struct cache_entry *entry) -{ - cache->entries = g_slist_append(cache->entries, entry); + return NULL; } static void cache_clear(struct cache *cache) { + g_free(cache->folder); g_slist_foreach(cache->entries, (GFunc) cache_entry_free, NULL); g_slist_free(cache->entries); cache->entries = NULL; @@ -226,8 +213,17 @@ static void phonebook_size_result(const gchar *buffer, size_t bufsize, gint vcards, gint missed, gpointer user_data) { struct pbap_session *pbap = user_data; + gchar aparam[4]; + struct aparam_header *hdr = (struct aparam_header *) aparam; + guint16 phonebooksize; + + phonebooksize = htons(vcards); - pbap->phonebooksize = vcards; + hdr->tag = PHONEBOOKSIZE_TAG; + hdr->len = PHONEBOOKSIZE_LEN; + memcpy(hdr->val, &phonebooksize, sizeof(phonebooksize)); + + pbap->buffer = g_string_new_len(aparam, sizeof(aparam)); obex_object_set_io_flags(pbap, G_IO_IN, 0); } @@ -246,6 +242,63 @@ static void query_result(const gchar *buffer, size_t bufsize, gint vcards, obex_object_set_io_flags(pbap, G_IO_IN, 0); } +static void cache_entry_notify(const gchar *id, const gchar *name, + const gchar *sound, const gchar *tel, gpointer user_data) +{ + struct pbap_session *pbap = user_data; + struct cache_entry *entry = g_new0(struct cache_entry, 1); + struct cache *cache = &pbap->cache; + + entry->handle = ++pbap->cache.index; + entry->id = g_strdup(id); + entry->name = g_strdup(name); + entry->sound = g_strdup(sound); + entry->tel = g_strdup(tel); + + cache->entries = g_slist_append(cache->entries, entry); +} + +static void cache_ready_notify(gpointer user_data) +{ + struct pbap_session *pbap = user_data; + + if (pbap->params->maxlistcount == 0) { + /* Ignore all other parameter and return PhoneBookSize */ + gchar aparam[4]; + struct aparam_header *hdr = (struct aparam_header *) aparam; + guint16 size = g_slist_length(pbap->cache.entries); + + hdr->tag = PHONEBOOKSIZE_TAG; + hdr->len = PHONEBOOKSIZE_LEN; + memcpy(hdr->val, &size, sizeof(size)); + + pbap->buffer = g_string_new_len(aparam, sizeof(aparam)); + } else { + GSList *l; + + pbap->buffer = g_string_new(VCARD_LISTING_BEGIN); + l = g_slist_nth(pbap->cache.entries, + pbap->params->liststartoffset); + + for (; l; l = l->next) { + struct cache_entry *entry = l->data; + + /* FIXME: check if the entry matches */ + + g_string_append_printf(pbap->buffer, + VCARD_LISTING_ELEMENT, + entry->handle, entry->name); + } + + pbap->buffer = g_string_append(pbap->buffer, VCARD_LISTING_END); + } + + if (!pbap->cache.valid) { + pbap->cache.valid = TRUE; + obex_object_set_io_flags(pbap, G_IO_IN, 0); + } +} + static struct apparam_field *parse_aparam(const guint8 *buffer, guint32 hlen) { struct apparam_field *param; @@ -351,10 +404,26 @@ static int pbap_get(struct obex_session *os, obex_object_t *obj, if (type == NULL) return -EBADR; - if (strcmp(type, PHONEBOOK_TYPE) == 0) + rsize = obex_aparam_read(os, obj, &buffer); + if (rsize < 0) + return -EBADR; + + params = parse_aparam(buffer, rsize); + if (params == NULL) + return -EBADR; + + if (pbap->params) { + g_free(pbap->params->searchval); + g_free(pbap->params); + } + + pbap->params = params; + + if (strcmp(type, PHONEBOOK_TYPE) == 0) { /* Always contains the absolute path */ path = g_strdup(name); - else if (strcmp(type, VCARDLISTING_TYPE) == 0) + *stream = (params->maxlistcount == 0 ? FALSE : TRUE); + } else if (strcmp(type, VCARDLISTING_TYPE) == 0) { /* Always relative */ if (!name || strlen(name) == 0) /* Current folder */ @@ -363,46 +432,24 @@ static int pbap_get(struct obex_session *os, obex_object_t *obj, /* Current folder + relative path */ path = g_build_filename(pbap->folder, name, NULL); - else if (strcmp(type, VCARDENTRY_TYPE) == 0) - /* Always relative */ - path = g_build_filename(pbap->folder, name, NULL); - else - return -EBADR; - - rsize = obex_aparam_read(os, obj, &buffer); - if (rsize < 0) { - ret = -EBADR; - goto failed; - } - - params = parse_aparam(buffer, rsize); - if (params == NULL) { - ret = -EBADR; - goto failed; - } - - if (pbap->params) { - g_free(pbap->params->searchval); - g_free(pbap->params); - } - - if (params->maxlistcount == 0) - *stream = FALSE; - else + *stream = (params->maxlistcount == 0 ? FALSE : TRUE); + } else if (strcmp(type, VCARDENTRY_TYPE) == 0) { + /* File name only */ + path = g_strdup(name); *stream = TRUE; + } else + return -EBADR; pbap->params = params; - ret = obex_get_stream_start(os, path, pbap); -failed: + g_free(path); return ret; } - static int pbap_setpath(struct obex_session *os, obex_object_t *obj, - gpointer user_data) + gpointer user_data) { struct pbap_session *pbap = user_data; const gchar *name; @@ -428,6 +475,13 @@ static int pbap_setpath(struct obex_session *os, obex_object_t *obj, set_folder(pbap, fullname); + /* + * FIXME: Define a criteria to mark the cache as invalid + */ + pbap->cache.valid = FALSE; + pbap->cache.index = 0; + cache_clear(&pbap->cache); + g_free(fullname); return 0; @@ -506,7 +560,6 @@ static gpointer vobject_list_open(const char *name, int oflag, mode_t mode, gpointer context, size_t *size, int *err) { struct pbap_session *pbap = context; - phonebook_cb cb; int ret; if (oflag != O_RDONLY) { @@ -514,19 +567,24 @@ static gpointer vobject_list_open(const char *name, int oflag, mode_t mode, goto fail; } - if (pbap->params->maxlistcount == 0) - cb = phonebook_size_result; - else - cb = query_result; + /* PullvCardListing always get the contacts from the cache */ - /* FIXME: PullvCardList should read data from the cache only */ - cache_add(&pbap->cache, NULL); - cache_foreach(&pbap->cache, NULL, NULL, NULL); + /* + * FIXME: When the name is given and the OBEX non header flags are + * provided it is necessary to check if the cache still valid. + */ + if (pbap->cache.valid) { + cache_ready_notify(pbap); + goto done; + } + + ret = phonebook_create_cache(name, + cache_entry_notify, cache_ready_notify, pbap); - ret = phonebook_list(name, pbap->params, cb, pbap); if (ret < 0) goto fail; +done: if (size) *size = OBJECT_SIZE_UNKNOWN; @@ -539,12 +597,12 @@ fail: return NULL; } - static gpointer vobject_vcard_open(const char *name, int oflag, mode_t mode, - gpointer context, size_t *size, int *err) + gpointer context, size_t *size, int *err) { struct pbap_session *pbap = context; - gpointer id; + const gchar *id; + guint32 handle; int ret; if (oflag != O_RDONLY) { @@ -552,14 +610,14 @@ static gpointer vobject_vcard_open(const char *name, int oflag, mode_t mode, goto fail; } - id = cache_find(&pbap->cache, name); + sscanf(name, "%u.vcf", &handle); + id = cache_find(&pbap->cache, handle); if (!id) { ret = -ENOENT; goto fail; } - /* FIXME: use id */ - ret = phonebook_get_entry(name, pbap->params, query_result, pbap); + ret = phonebook_get_entry(id, pbap->params, query_result, pbap); if (ret < 0) goto fail; @@ -575,33 +633,51 @@ fail: return NULL; } -static ssize_t vobject_read(gpointer object, void *buf, size_t count, +static ssize_t vobject_pull_read(gpointer object, void *buf, size_t count, guint8 *hi) { struct pbap_session *pbap = object; - ssize_t ret = -EAGAIN; + + if (!pbap->buffer) + return -EAGAIN; /* PhoneBookSize */ - if (pbap->params->maxlistcount == 0) { - guint8 data[4]; - guint16 phonebooksize; - struct aparam_header *hdr = (struct aparam_header *) data; + if (pbap->params->maxlistcount == 0) + *hi = OBEX_HDR_APPARAM; + else + /* Stream data */ + *hi = OBEX_HDR_BODY; - phonebooksize = htons(pbap->phonebooksize); - hdr->tag = PHONEBOOKSIZE_TAG; - hdr->len = PHONEBOOKSIZE_LEN; - memcpy(hdr->val, &phonebooksize, sizeof(phonebooksize)); + return string_read(pbap->buffer, buf, count); +} + +static ssize_t vobject_list_read(gpointer object, void *buf, size_t count, + guint8 *hi) +{ + struct pbap_session *pbap = object; + + /* Backend still busy reading contacts */ + if (!pbap->cache.valid) + return -EAGAIN; - memcpy(buf, data, sizeof(data)); + if (pbap->params->maxlistcount == 0) *hi = OBEX_HDR_APPARAM; - ret = 0; - } else if (pbap->buffer) { - /* Stream data */ + else *hi = OBEX_HDR_BODY; - ret = string_read(pbap->buffer, buf, count, hi); - } - return ret; + return string_read(pbap->buffer, buf, count); +} + +static ssize_t vobject_vcard_read(gpointer object, void *buf, size_t count, + guint8 *hi) +{ + struct pbap_session *pbap = object; + + if (!pbap->buffer) + return -EAGAIN; + + *hi = OBEX_HDR_BODY; + return string_read(pbap->buffer, buf, count); } static int vobject_close(gpointer object) @@ -621,7 +697,7 @@ static struct obex_mime_type_driver mime_pull = { .mimetype = "x-bt/phonebook", .open = vobject_pull_open, .close = vobject_close, - .read = vobject_read, + .read = vobject_pull_read, }; static struct obex_mime_type_driver mime_list = { @@ -629,7 +705,7 @@ static struct obex_mime_type_driver mime_list = { .mimetype = "x-bt/vcard-listing", .open = vobject_list_open, .close = vobject_close, - .read = vobject_read, + .read = vobject_list_read, }; static struct obex_mime_type_driver mime_vcard = { @@ -637,7 +713,7 @@ static struct obex_mime_type_driver mime_vcard = { .mimetype = "x-bt/vcard", .open = vobject_vcard_open, .close = vobject_close, - .read = vobject_read, + .read = vobject_vcard_read, }; static int pbap_init(void) diff --git a/obexd/plugins/phonebook-dummy.c b/obexd/plugins/phonebook-dummy.c index 38736a293..02edf2ace 100644 --- a/obexd/plugins/phonebook-dummy.c +++ b/obexd/plugins/phonebook-dummy.c @@ -85,14 +85,14 @@ int phonebook_pull(const gchar *name, const struct apparam_field *params, return 0; } -int phonebook_get_entry(const gchar *name, const struct apparam_field *params, +int phonebook_get_entry(const gchar *id, const struct apparam_field *params, phonebook_cb cb, gpointer user_data) { return -1; } -int phonebook_list(const gchar *name, const struct apparam_field *params, - phonebook_cb cb, gpointer user_data) +int phonebook_create_cache(const gchar *name, phonebook_entry_cb entry_cb, + phonebook_cache_ready_cb ready_cb, gpointer user_data) { - return -1; + return 0; } diff --git a/obexd/plugins/phonebook-ebook.c b/obexd/plugins/phonebook-ebook.c index c401a2889..7afcf09c8 100644 --- a/obexd/plugins/phonebook-ebook.c +++ b/obexd/plugins/phonebook-ebook.c @@ -41,24 +41,22 @@ #include "service.h" #include "phonebook.h" -#define EOL "\r\n" -#define VCARD_LISTING_BEGIN \ - "" EOL \ - "" EOL \ - "" EOL -#define VCARD_LISTING_ELEMENT "" EOL -#define VCARD_LISTING_END "" - #define QUERY_FN "(contains \"family_name\" \"%s\")" #define QUERY_NAME "(contains \"given_name\" \"%s\")" #define QUERY_PHONE "(contains \"phone\" \"%s\")" -struct query_data { +struct contacts_query { const struct apparam_field *params; phonebook_cb cb; gpointer user_data; }; +struct cache_query { + phonebook_entry_cb entry_cb; + phonebook_cache_ready_cb ready_cb; + gpointer user_data; +}; + static EBook *ebook = NULL; static gchar *attribute_mask[] = { @@ -130,13 +128,21 @@ static gchar *evcard_to_string(EVCard *evcard, guint format, guint64 filter) return vcard; } -static void ebookpull_cb(EBook *book, EBookStatus status, GList *contacts, +static void ebookpull_cb(EBook *book, EBookStatus estatus, GList *contacts, gpointer user_data) { - struct query_data *data = user_data; + struct contacts_query *data = user_data; GString *string = g_string_new(""); - GList *l = g_list_nth(contacts, data->params->liststartoffset); - guint count = 0, maxcount = data->params->maxlistcount; + guint count = 0, maxcount; + GList *l; + + if (estatus != E_BOOK_ERROR_OK) { + error("E-Book query failed: status %d", estatus); + goto done; + } + + maxcount = data->params->maxlistcount; + l = g_list_nth(contacts, data->params->liststartoffset); /* FIXME: Missing 0.vcf */ @@ -145,19 +151,47 @@ static void ebookpull_cb(EBook *book, EBookStatus status, GList *contacts, EVCard *evcard = E_VCARD(contact); gchar *vcard; - vcard = evcard_to_string(evcard, - data->params->format, data->params->filter); + vcard = evcard_to_string(evcard, data->params->format, + data->params->filter); string = g_string_append(string, vcard); g_free(vcard); } +done: data->cb(string->str, string->len, count, 0, data->user_data); g_string_free(string, TRUE); g_free(data); } +static void ebook_entry_cb(EBook *book, EBookStatus estatus, + EContact *contact, gpointer user_data) +{ + struct contacts_query *data = user_data; + EVCard *evcard; + gchar *vcard; + size_t len; + + if (estatus != E_BOOK_ERROR_OK) { + error("E-Book query failed: status %d", estatus); + data->cb(NULL, 0, 1, 0, data->user_data); + g_free(data); + return; + } + + evcard = E_VCARD(contact); + + vcard = evcard_to_string(evcard, data->params->format, + data->params->filter); + + len = vcard ? strlen(vcard) : 0; + + data->cb(vcard, len, 1, 0, data->user_data); + + g_free(data); +} + static gchar *evcard_name_attribute_to_string(EVCard *evcard) { EVCardAttribute *attrib; @@ -188,36 +222,48 @@ static gchar *evcard_name_attribute_to_string(EVCard *evcard) return g_string_free(name, FALSE); } -static void ebooklist_cb(EBook *book, EBookStatus status, GList *contacts, +static void cache_cb(EBook *book, EBookStatus estatus, GList *contacts, gpointer user_data) { - struct query_data *data = user_data; - GString *string = g_string_new(VCARD_LISTING_BEGIN); - GList *l = g_list_nth(contacts, data->params->liststartoffset); - guint count = 0, maxcount = data->params->maxlistcount; + struct cache_query *data = user_data; + GList *l; - for (; l && count < maxcount; l = g_list_next(l), count++) { + if (estatus != E_BOOK_ERROR_OK) { + error("E-Book query failed: status %d", estatus); + goto done; + } + + for (l = contacts; l; l = g_list_next(l)) { EContact *contact = E_CONTACT(l->data); EVCard *evcard = E_VCARD(contact); - gchar *element, *name; + EVCardAttribute *attrib; + gchar *uid, *tel, *name; name = evcard_name_attribute_to_string(evcard); if (!name) continue; - element = g_strdup_printf(VCARD_LISTING_ELEMENT, count, name); + attrib = e_vcard_get_attribute(evcard, EVC_UID); + if (!attrib) + continue; - string = g_string_append(string, element); - g_free(name); - g_free(element); - } + uid = e_vcard_attribute_get_value(attrib); + if (!uid) + continue; - string = g_string_append(string, VCARD_LISTING_END); + attrib = e_vcard_get_attribute(evcard, EVC_TEL); + if (!attrib) + continue; - data->cb(string->str, string->len, count, 0, data->user_data); + tel = e_vcard_attribute_get_value(attrib); - g_string_free(string, TRUE); - g_free(data); + data->entry_cb(uid, name, NULL, tel, data->user_data); + g_free(name); + g_free(uid); + g_free(tel); + } +done: + data->ready_cb(data->user_data); } int phonebook_init(void) @@ -253,7 +299,7 @@ int phonebook_set_folder(const gchar *current_folder, gboolean root, child; int ret; - root = (!current_folder || strlen(current_folder) == 0); + root = (g_strcmp0("/", current_folder) == 0); child = (new_folder && strlen(new_folder) != 0); /* Evolution back-end will support telecom/pb folder only */ @@ -266,7 +312,7 @@ int phonebook_set_folder(const gchar *current_folder, /* Go down 1 level */ if (root) ret = (strcmp("telecom", new_folder) != 0) ? -EBADR: 0; - else if (strcmp("telecom", current_folder) == 0) + else if (strcmp("/telecom", current_folder) == 0) ret = (strcmp("pb", new_folder) != 0) ? -EBADR: 0; else ret = -EBADR; @@ -282,9 +328,9 @@ int phonebook_set_folder(const gchar *current_folder, return 0; /* /telecom or /telecom/pb */ - if (strcmp("telecom", current_folder) == 0) + if (strcmp("/telecom", current_folder) == 0) ret = (strcmp("telecom", new_folder) != 0) ? -EBADR : 0; - else if (strcmp("telecom/pb", current_folder) == 0) + else if (strcmp("/telecom/pb", current_folder) == 0) ret = (strcmp("pb", new_folder) != 0) ? -EBADR : 0; else ret = -EBADR; @@ -298,14 +344,14 @@ int phonebook_set_folder(const gchar *current_folder, } gint phonebook_pull(const gchar *name, const struct apparam_field *params, - phonebook_cb cb, gpointer user_data) + phonebook_cb cb, gpointer user_data) { - struct query_data *data; + struct contacts_query *data; EBookQuery *query; query = e_book_query_any_field_contains(""); - data = g_new0(struct query_data, 1); + data = g_new0(struct contacts_query, 1); data->cb = cb; data->params = params; data->user_data = user_data; @@ -317,79 +363,41 @@ gint phonebook_pull(const gchar *name, const struct apparam_field *params, return 0; } -int phonebook_get_entry(const gchar *name, const struct apparam_field *params, +int phonebook_get_entry(const gchar *id, const struct apparam_field *params, phonebook_cb cb, gpointer user_data) { - return -1; -} - -static EBookQuery *create_query(guint8 attrib, guint8 *searchval) -{ - EBookQuery *query; - gchar *fam, *str, **values; - - if (!searchval || strlen((gchar *) searchval) == 0) - return e_book_query_any_field_contains(""); - - switch (attrib) { - case 0: - /* Name */ - values = g_strsplit((gchar *) searchval, ";", 2); - - str = NULL; - - fam = (values[0] ? g_strdup_printf(QUERY_FN, values[0]) : NULL); - - if (values[1]) { - char *given = g_strdup_printf(QUERY_NAME, values[1]); - - str = fam ? - g_strconcat(fam, " and ", given, NULL) : given; + struct contacts_query *data; - g_free(fam); - g_free(given); - } - - if (!str) - str = fam; + data = g_new0(struct contacts_query, 1); + data->cb = cb; + data->params = params; + data->user_data = user_data; - g_strfreev(values); - break; - case 1: - /* Number */ - str = g_strdup_printf(QUERY_PHONE, searchval); - break; - case 2: - /* Sound */ - /* TODO: not yet implemented */ - default: - return NULL; + if (e_book_async_get_contact(ebook, id, ebook_entry_cb, data)) { + g_free(data); + return -EPERM; } - query = e_book_query_from_string(str); - g_free(str); - - return query; + return 0; } -int phonebook_list(const gchar *name, const struct apparam_field *params, - phonebook_cb cb, gpointer user_data) +int phonebook_create_cache(const gchar *name, phonebook_entry_cb entry_cb, + phonebook_cache_ready_cb ready_cb, gpointer user_data) { - struct query_data *data; + struct cache_query *data; EBookQuery *query; + gboolean ret; - query = create_query(params->searchattrib, params->searchval); - if (!query) - return -EBADR; + query = e_book_query_any_field_contains(""); - data = g_new0(struct query_data, 1); - data->cb = cb; - data->params = params; + data = g_new0(struct cache_query, 1); + data->entry_cb = entry_cb; + data->ready_cb = ready_cb; data->user_data = user_data; - e_book_async_get_contacts(ebook, query, ebooklist_cb, data); + ret = e_book_async_get_contacts(ebook, query, cache_cb, data); e_book_query_unref(query); - return 0; + return (ret == FALSE ? 0 : -EBADR); } diff --git a/obexd/plugins/phonebook.h b/obexd/plugins/phonebook.h index b0878fb34..5d3e33dfd 100644 --- a/obexd/plugins/phonebook.h +++ b/obexd/plugins/phonebook.h @@ -21,6 +21,14 @@ * */ +#define EOL "\r\n" +#define VCARD_LISTING_BEGIN \ + "" EOL\ + "" EOL\ + "" EOL +#define VCARD_LISTING_ELEMENT "" EOL +#define VCARD_LISTING_END "" + struct apparam_field { /* list and pull attributes */ guint16 maxlistcount; @@ -36,20 +44,47 @@ struct apparam_field { guint8 *searchval; }; +/* + * Interface between the PBAP core and backends to retrieve + * all contacts that match the application parameters rules. + * Contacts will be returned in the vcard format. + */ typedef void (*phonebook_cb) (const gchar *buffer, size_t bufsize, gint vcards, gint missed, gpointer user_data); +/* + * Interface between the PBAP core and backends to + * append a new entry in the PBAP folder cache. + */ +typedef void (*phonebook_entry_cb) (const gchar *id, const gchar *name, + const gchar *sound, const gchar *tel, gpointer user_data); + +/* + * After notify all entries to PBAP core, the backend + * needs to notify that the operation has finished. + */ +typedef void (*phonebook_cache_ready_cb) (gpointer user_data); + + int phonebook_init(void); void phonebook_exit(void); int phonebook_set_folder(const gchar *current_folder, const gchar *new_folder, guint8 flags); +/* + * PullPhoneBook never use cached entries. PCE use this + * function to get all entries of a given folder. + */ int phonebook_pull(const gchar *name, const struct apparam_field *params, phonebook_cb cb, gpointer user_data); -int phonebook_get_entry(const gchar *name, const struct apparam_field *params, +int phonebook_get_entry(const gchar *id, const struct apparam_field *params, phonebook_cb cb, gpointer user_data); -int phonebook_list(const gchar *name, const struct apparam_field *params, - phonebook_cb cb, gpointer user_data); +/* + * PBAP core will keep the contacts cache per folder. SetPhoneBook or + * PullvCardListing can invalidate the cache if the current folder changes. + */ +int phonebook_create_cache(const gchar *name, phonebook_entry_cb entry_cb, + phonebook_cache_ready_cb ready_cb, gpointer user_data); diff --git a/obexd/plugins/syncevolution.c b/obexd/plugins/syncevolution.c index a646cc6eb..7a76a49b5 100644 --- a/obexd/plugins/syncevolution.c +++ b/obexd/plugins/syncevolution.c @@ -339,8 +339,10 @@ static ssize_t synce_read(gpointer object, void *buf, size_t count, guint8 *hi) gboolean authenticate; DBusPendingCall *call; - if (context->buffer) - return string_read(context->buffer, buf, count, hi); + if (context->buffer) { + *hi = OBEX_HDR_BODY; + return string_read(context->buffer, buf, count); + } conn = obex_dbus_get_connection(); if (conn == NULL) -- 2.47.3