From patchwork Fri Jul 23 13:58:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dylan Van Assche X-Patchwork-Id: 12396151 X-Patchwork-Delegate: luiz.dentz@gmail.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0FE61C4320E for ; Fri, 23 Jul 2021 13:59:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E765060EB4 for ; Fri, 23 Jul 2021 13:58:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235336AbhGWNSZ (ORCPT ); Fri, 23 Jul 2021 09:18:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56588 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235302AbhGWNSY (ORCPT ); Fri, 23 Jul 2021 09:18:24 -0400 Received: from mout-p-201.mailbox.org (mout-p-201.mailbox.org [IPv6:2001:67c:2050::465:201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 43B7CC061575 for ; Fri, 23 Jul 2021 06:58:58 -0700 (PDT) Received: from smtp1.mailbox.org (smtp1.mailbox.org [80.241.60.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-201.mailbox.org (Postfix) with ESMTPS id 4GWWBm5Yg2zQkFR; Fri, 23 Jul 2021 15:58:56 +0200 (CEST) X-Virus-Scanned: amavisd-new at heinlein-support.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dylanvanassche.be; s=MBO0001; t=1627048734; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=P1dZFKDe3ERf4PCfbDBy/+WBP8mvVFI6Ey7cIpjvGf0=; b=zel36RxLnrADnH7k4zD3VJvt5xx1mcck+YZ3msYsAI3QWQUMn0BIN/IbJPbpogjLORLASA RqKWb4PhDsGgoK11HG5+RbzrZcQ2UoDXCRT5aHFIbwGIxVWcH4DyspGhqLL5rEqX6evGkP 8mtjzI3fxDuky2JqnJ4xQKVyy/ym0/7NFNOfQZYg+1cKx3Ip/D9TkNinf82OoKw7XzHlMK J1bsSFano/oeiEYaNZS7TKVb6EvS3auvG/41fzDPOGVXxZhkoULzpBGuqeGxqDYbosWbci SZNpUH19xWI6QKtqutv8BaDgibbQENFmfq71yd0Oc5W1Gb+qXxPa1VExCKoZTg== Received: from smtp1.mailbox.org ([80.241.60.240]) by gerste.heinlein-support.de (gerste.heinlein-support.de [91.198.250.173]) (amavisd-new, port 10030) with ESMTP id VqWhj0Xxy0ku; Fri, 23 Jul 2021 15:58:51 +0200 (CEST) From: Dylan Van Assche To: linux-bluetooth@vger.kernel.org Cc: Dylan Van Assche Subject: [PATCH BlueZ 1/4] obexd: phonebook-ebook: modernize Date: Fri, 23 Jul 2021 15:58:21 +0200 Message-Id: <20210723135824.8032-2-me@dylanvanassche.be> In-Reply-To: <20210723135824.8032-1-me@dylanvanassche.be> References: <20210723135824.8032-1-me@dylanvanassche.be> MIME-Version: 1.0 X-Rspamd-Queue-Id: 8C4BF1898 X-Rspamd-UID: eaca67 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Modernize PBAP phonebook-ebook plugin for newer libebook version of the Evolution Data Server. The ebook plugin was introduced during GSoC 2011 [1] and allows BlueZ to share contacts stored in the Evolution Data Server to connected clients such as car multimedia systems. With the rise of Mobile Linux thanks to the PinePhone and Librem 5, this plugin was modernized to compile with newer libebook versions because the API was changed [2]. [1] http://www.bluez.org/gsoc-eds-backend-of-phonebook-access-profilepbap/ [2] https://wiki.gnome.org/Apps/Evolution/ESourceMigrationGuide --- obexd/plugins/phonebook-ebook.c | 668 +++++++++++++++----------------- 1 file changed, 320 insertions(+), 348 deletions(-) diff --git a/obexd/plugins/phonebook-ebook.c b/obexd/plugins/phonebook-ebook.c index 30be9d921..29ec9d213 100644 --- a/obexd/plugins/phonebook-ebook.c +++ b/obexd/plugins/phonebook-ebook.c @@ -3,8 +3,9 @@ * * OBEX Server * - * Copyright (C) 2009-2010 Intel Corporation - * Copyright (C) 2007-2010 Marcel Holtmann + * Copyright (C) 2009-2021 Intel Corporation + * Copyright (C) 2007-2021 Marcel Holtmann + * Copyright (C) 2021 Dylan Van Assche * * */ @@ -13,35 +14,44 @@ #include #endif -#include +#define _GNU_SOURCE +#include #include - +#include +#include +#include #include -#include - -#include "lib/bluetooth.h" +#include +#include +#include +#include +#include +#include +#include #include "obexd/src/log.h" -#include "obexd/src/obex.h" -#include "obexd/src/service.h" #include "phonebook.h" -#define QUERY_FN "(contains \"family_name\" \"%s\")" -#define QUERY_NAME "(contains \"given_name\" \"%s\")" -#define QUERY_PHONE "(contains \"phone\" \"%s\")" +#define CONNECTION_TIMEOUT 30 // seconds +#define PB_FORMAT_VCARD21 0 +#define PB_FORMAT_VCARD30 1 +#define PB_FORMAT_NONE 2 + +ESourceRegistry *registry; +ESource *address_book; +EBookClient *book_client; struct query_context { const struct apparam_field *params; phonebook_cb contacts_cb; phonebook_entry_cb entry_cb; phonebook_cache_ready_cb ready_cb; - EBookQuery *query; + gchar *query; unsigned int count; GString *buf; - char *id; + char *uid; unsigned queued_calls; void *user_data; - GSList *ebooks; gboolean canceled; }; @@ -76,39 +86,30 @@ static char *attribute_mask[] = { "SORT-STRING", /* 28 */ "X-IRMC-CALL-DATETIME", NULL - }; -static void close_ebooks(GSList *ebooks) -{ - g_slist_free_full(ebooks, g_object_unref); -} - static void free_query_context(struct query_context *data) { - g_free(data->id); + g_free(data->uid); if (data->buf != NULL) g_string_free(data->buf, TRUE); if (data->query != NULL) - e_book_query_unref(data->query); - - close_ebooks(data->ebooks); + g_free(data->query); g_free(data); } static char *evcard_to_string(EVCard *evcard, unsigned int format, - uint64_t filter) + uint64_t filter) { EVCard *evcard2; GList *l; char *vcard; if (!filter) - return e_vcard_to_string(evcard, EVC_FORMAT_VCARD_30); - /* XXX There is no support for VCARD 2.1 at this time */ + return e_vcard_to_string(evcard, format); /* * Mandatory attributes for vCard 2.1 are VERSION ,N and TEL. @@ -135,7 +136,7 @@ static char *evcard_to_string(EVCard *evcard, unsigned int format, continue; e_vcard_add_attribute(evcard2, - e_vcard_attribute_copy(attrib)); + e_vcard_attribute_copy(attrib)); } } @@ -145,25 +146,149 @@ static char *evcard_to_string(EVCard *evcard, unsigned int format, return vcard; } -static void ebookpull_cb(EBook *book, const GError *gerr, GList *contacts, - void *user_data) +char *phonebook_set_folder(const char *current_folder, const char *new_folder, + uint8_t flags, int *err) +{ + gboolean root, child; + char *fullname = NULL, *tmp1, *tmp2, *base; + int ret = 0, len; + + root = (g_strcmp0("/", current_folder) == 0); + child = (new_folder && strlen(new_folder) != 0); + + /* Evolution back-end will support /telecom/pb folder only */ + switch (flags) { + case 0x02: + /* Go back to root */ + if (!child) { + fullname = g_strdup("/"); + goto done; + } + + /* Go down 1 level */ + fullname = g_build_filename(current_folder, new_folder, NULL); + if (strcmp(PB_TELECOM_FOLDER, fullname) != 0 && + strcmp(PB_CONTACTS_FOLDER, fullname) != 0) { + g_free(fullname); + fullname = NULL; + ret = -ENOENT; + } + + break; + case 0x03: + /* Go up 1 level */ + if (root) { + /* Already root */ + ret = -EBADR; + goto done; + } + + /* + * Removing one level of the current folder. Current folder + * contains AT LEAST one level since it is not at root folder. + * Use glib utility functions to handle invalid chars in the + * folder path properly. + */ + tmp1 = g_path_get_basename(current_folder); + tmp2 = g_strrstr(current_folder, tmp1); + len = tmp2 - (current_folder + 1); + + g_free(tmp1); + + if (len == 0) + base = g_strdup("/"); + else + base = g_strndup(current_folder, len); + + /* Return one level only */ + if (!child) { + fullname = base; + goto done; + } + + fullname = g_build_filename(base, new_folder, NULL); + if (strcmp(fullname, PB_TELECOM_FOLDER) != 0 && + strcmp(fullname, PB_CONTACTS_FOLDER) != 0) { + g_free(fullname); + fullname = NULL; + ret = -ENOENT; + } + + g_free(base); + + break; + default: + ret = -EBADR; + break; + } + +done: + if (err) + *err = ret; + + return fullname; +} + +void phonebook_req_finalize(void *request) +{ + /* Free resources after pull request */ + struct query_context *data = request; + + if (data->queued_calls == 0) + free_query_context(data); + else + data->canceled = TRUE; +} + +void *phonebook_pull(const char *name, const struct apparam_field *params, + phonebook_cb cb, void *user_data, int *err) +{ + struct query_context *data; + EBookQuery *query; + + /* Request should be for '/telecom/pb.vcf', reject others */ + if (g_strcmp0(PB_CONTACTS, name) != 0) { + if (err) + *err = -ENOENT; + return NULL; + } + + data = g_new0(struct query_context, 1); + data->contacts_cb = cb; + data->params = params; + data->user_data = user_data; + data->buf = g_string_new(""); + query = e_book_query_any_field_contains(""); // all contacts + data->query = e_book_query_to_string(query); + e_book_query_unref(query); + + return data; +} + +static void phonebook_pull_read_ready(GObject *source_object, + GAsyncResult *result, gpointer user_data) { struct query_context *data = user_data; - GList *l; + GSList *l = NULL; + GSList *contacts = NULL; + GError *gerr = NULL; unsigned int count, maxcount; + /* Finish async call to retrieve contacts */ data->queued_calls--; if (data->canceled) goto canceled; + e_book_client_get_contacts_finish(E_BOOK_CLIENT(source_object), + result, &contacts, &gerr); + if (gerr != NULL) { - error("E-Book query failed: %s", gerr->message); + error("Failed to retrieve contacts, invalid query"); + g_error_free(gerr); goto done; } - DBG(""); - /* * When MaxListCount is zero, PCE wants to know the number of used * indexes in the phonebook of interest. All other parameters that @@ -171,42 +296,48 @@ static void ebookpull_cb(EBook *book, const GError *gerr, GList *contacts, */ maxcount = data->params->maxlistcount; if (maxcount == 0) { - data->count += g_list_length(contacts); + data->count += g_slist_length(contacts); goto done; } - l = g_list_nth(contacts, data->params->liststartoffset); - - for (count = 0; l && count + data->count < maxcount; l = g_list_next(l), - count++) { + /* + * Convert each contact to a vCard and append the card to + * the buffer string. + */ + l = g_slist_nth(contacts, data->params->liststartoffset); + for (count = 0; l && count + data->count < maxcount; + l = g_slist_next(l), count++) { EContact *contact = E_CONTACT(l->data); EVCard *evcard = E_VCARD(contact); char *vcard; - vcard = evcard_to_string(evcard, EVC_FORMAT_VCARD_30, - data->params->filter); + if (data->params->format == PB_FORMAT_VCARD30) + vcard = evcard_to_string(evcard, EVC_FORMAT_VCARD_30, + data->params->filter); + else if (data->params->format == PB_FORMAT_VCARD21) + vcard = evcard_to_string(evcard, EVC_FORMAT_VCARD_21, + data->params->filter); + else + error("unknown format: %d", data->params->format); data->buf = g_string_append(data->buf, vcard); data->buf = g_string_append(data->buf, "\r\n"); g_free(vcard); } - DBG("collected %d vcards", count); + DBG("collected %d contacts", count); data->count += count; - - g_list_free_full(contacts, g_object_unref); + g_slist_free_full(contacts, (GDestroyNotify) g_object_unref); done: if (data->queued_calls == 0) { GString *buf = data->buf; data->buf = NULL; - data->contacts_cb(buf->str, buf->len, data->count, - 0, TRUE, data->user_data); - + data->contacts_cb(buf->str, buf->len, data->count, 0, TRUE, + data->user_data); g_string_free(buf, TRUE); - } return; @@ -216,9 +347,31 @@ canceled: free_query_context(data); } -static void ebook_entry_cb(EBook *book, const GError *gerr, - EContact *contact, void *user_data) +int phonebook_pull_read(void *request) { + struct query_context *data = request; + GError *gerr = NULL; + + if (!data) { + error("Request data is empty"); + return -ENOENT; + } + + DBG("retrieving all contacts"); + + /* Fetch async contacts from default address book */ + e_book_client_get_contacts(book_client, data->query, NULL, + (GAsyncReadyCallback) phonebook_pull_read_ready, data); + data->queued_calls++; + + return 0; +} + +static void phonebook_get_entry_ready(GObject *source_object, + GAsyncResult *result, gpointer user_data) +{ + GError *gerr = NULL; + EContact *contact = NULL; struct query_context *data = user_data; EVCard *evcard; char *vcard; @@ -226,20 +379,27 @@ static void ebook_entry_cb(EBook *book, const GError *gerr, data->queued_calls--; + e_book_client_get_contact_finish(E_BOOK_CLIENT(source_object), result, + &contact, &gerr); if (data->canceled) goto done; if (gerr != NULL) { - error("E-Book query failed: %s", gerr->message); + error("Getting contact failed: %s", gerr->message); + g_error_free(gerr); goto done; } - DBG(""); - evcard = E_VCARD(contact); - vcard = evcard_to_string(evcard, EVC_FORMAT_VCARD_30, - data->params->filter); + if (data->params->format == PB_FORMAT_VCARD30) + vcard = evcard_to_string(evcard, EVC_FORMAT_VCARD_30, + data->params->filter); + else if (data->params->format == PB_FORMAT_VCARD21) + vcard = evcard_to_string(evcard, EVC_FORMAT_VCARD_21, + data->params->filter); + else + error("Unknown vCard format: %d", data->params->format); len = vcard ? strlen(vcard) : 0; @@ -247,18 +407,45 @@ static void ebook_entry_cb(EBook *book, const GError *gerr, data->contacts_cb(vcard, len, 1, 0, TRUE, data->user_data); g_free(vcard); - g_object_unref(contact); - return; + DBG("retrieving entry successful"); done: if (data->queued_calls == 0) { if (data->count == 0) data->contacts_cb(NULL, 0, 1, 0, TRUE, - data->user_data); + data->user_data); else if (data->canceled) free_query_context(data); } + + g_object_unref(contact); +} + +void *phonebook_get_entry(const char *folder, const char *id, + const struct apparam_field *params, phonebook_cb cb, + void *user_data, int *err) +{ + struct query_context *data; + GSList *l; + + DBG("retrieving entry: %s", id); + + data = g_new0(struct query_context, 1); + data->contacts_cb = cb; + data->params = params; + data->user_data = user_data; + data->uid = g_strdup(id); + + /* Fetch async contacts from default address book */ + e_book_client_get_contact(book_client, data->uid, NULL, + (GAsyncReadyCallback) phonebook_get_entry_ready, data); + data->queued_calls++; + + if (err) + *err = (data->queued_calls == 0 ? -ENOENT : 0); + + return data; } static char *evcard_name_attribute_to_string(EVCard *evcard) @@ -291,25 +478,28 @@ static char *evcard_name_attribute_to_string(EVCard *evcard) return g_string_free(name, FALSE); } -static void cache_cb(EBook *book, const GError *gerr, GList *contacts, - void *user_data) +static void phonebook_create_cache_ready(GObject *source_object, + GAsyncResult *result, gpointer user_data) { struct query_context *data = user_data; - GList *l; + GSList *l = NULL; + GSList *contacts = NULL; + GError *gerr = NULL; data->queued_calls--; if (data->canceled) goto canceled; + e_book_client_get_contacts_finish(E_BOOK_CLIENT(source_object), + result, &contacts, &gerr); + if (gerr != NULL) { - error("E-Book operation failed: %s", gerr->message); + error("Getting contacts failed: %s", gerr->message); goto done; } - DBG(""); - - for (l = contacts; l; l = g_list_next(l)) { + for (l = contacts; l; l = g_slist_next(l)) { EContact *contact = E_CONTACT(l->data); EVCard *evcard = E_VCARD(contact); EVCardAttribute *attrib; @@ -341,7 +531,9 @@ static void cache_cb(EBook *book, const GError *gerr, GList *contacts, g_free(tel); } - g_list_free_full(contacts, g_object_unref); + DBG("caching successful"); + + g_slist_free_full(contacts, (GDestroyNotify) g_object_unref); done: if (data->queued_calls == 0) @@ -354,275 +546,16 @@ canceled: free_query_context(data); } -static GSList *traverse_sources(GSList *ebooks, GSList *sources, - char **default_src) { - GError *gerr = NULL; - - for (; sources != NULL; sources = g_slist_next(sources)) { - char *uri; - ESource *source = E_SOURCE(sources->data); - EBook *ebook = e_book_new(source, &gerr); - - if (ebook == NULL) { - error("Can't create user's address book: %s", - gerr->message); - g_clear_error(&gerr); - continue; - } - - uri = e_source_get_uri(source); - if (g_strcmp0(*default_src, uri) == 0) { - g_free(uri); - continue; - } - g_free(uri); - - if (e_book_open(ebook, FALSE, &gerr) == FALSE) { - error("Can't open e-book address book: %s", - gerr->message); - g_object_unref(ebook); - g_clear_error(&gerr); - continue; - } - - if (*default_src == NULL) - *default_src = e_source_get_uri(source); - - DBG("%s address book opened", e_source_peek_name(source)); - - ebooks = g_slist_append(ebooks, ebook); - } - - return ebooks; -} - -int phonebook_init(void) -{ - g_type_init(); - - return 0; -} - -static GSList *open_ebooks(void) -{ - GError *gerr = NULL; - ESourceList *src_list; - GSList *list; - char *default_src = NULL; - GSList *ebooks = NULL; - - if (e_book_get_addressbooks(&src_list, &gerr) == FALSE) { - error("Can't list user's address books: %s", gerr->message); - g_error_free(gerr); - return NULL; - } - - list = e_source_list_peek_groups(src_list); - while (list != NULL) { - ESourceGroup *group = E_SOURCE_GROUP(list->data); - GSList *sources = e_source_group_peek_sources(group); - - ebooks = traverse_sources(ebooks, sources, &default_src); - - list = list->next; - } - - g_free(default_src); - g_object_unref(src_list); - - return ebooks; -} - -void phonebook_exit(void) -{ -} - -char *phonebook_set_folder(const char *current_folder, - const char *new_folder, uint8_t flags, int *err) -{ - gboolean root, child; - char *fullname = NULL, *tmp1, *tmp2, *base; - int ret = 0, len; - - root = (g_strcmp0("/", current_folder) == 0); - child = (new_folder && strlen(new_folder) != 0); - - /* Evolution back-end will support /telecom/pb folder only */ - - switch (flags) { - case 0x02: - /* Go back to root */ - if (!child) { - fullname = g_strdup("/"); - goto done; - } - - /* Go down 1 level */ - fullname = g_build_filename(current_folder, new_folder, NULL); - if (strcmp(PB_TELECOM_FOLDER, fullname) != 0 && - strcmp(PB_CONTACTS_FOLDER, fullname) != 0) { - g_free(fullname); - fullname = NULL; - ret = -ENOENT; - } - - break; - case 0x03: - /* Go up 1 level */ - if (root) { - /* Already root */ - ret = -EBADR; - goto done; - } - - /* - * Removing one level of the current folder. Current folder - * contains AT LEAST one level since it is not at root folder. - * Use glib utility functions to handle invalid chars in the - * folder path properly. - */ - tmp1 = g_path_get_basename(current_folder); - tmp2 = g_strrstr(current_folder, tmp1); - len = tmp2 - (current_folder + 1); - - g_free(tmp1); - - if (len == 0) - base = g_strdup("/"); - else - base = g_strndup(current_folder, len); - - /* Return one level only */ - if (!child) { - fullname = base; - goto done; - } - - fullname = g_build_filename(base, new_folder, NULL); - if (strcmp(fullname, PB_TELECOM_FOLDER) != 0 && - strcmp(fullname, PB_CONTACTS_FOLDER) != 0) { - g_free(fullname); - fullname = NULL; - ret = -ENOENT; - } - - g_free(base); - - break; - default: - ret = -EBADR; - break; - } - -done: - if (err) - *err = ret; - - return fullname; -} - -void phonebook_req_finalize(void *request) -{ - struct query_context *data = request; - - if (data->queued_calls == 0) - free_query_context(data); - else - data->canceled = TRUE; -} - -void *phonebook_pull(const char *name, const struct apparam_field *params, - phonebook_cb cb, void *user_data, int *err) -{ - struct query_context *data; - - if (g_strcmp0(PB_CONTACTS, name) != 0) { - if (err) - *err = -ENOENT; - - return NULL; - } - - data = g_new0(struct query_context, 1); - data->contacts_cb = cb; - data->params = params; - data->user_data = user_data; - data->buf = g_string_new(""); - data->query = e_book_query_any_field_contains(""); - data->ebooks = open_ebooks(); - - if (err) - *err = data->ebooks == NULL ? -EIO : 0; - - return data; -} - -int phonebook_pull_read(void *request) -{ - struct query_context *data = request; - GSList *l; - - if (!data) - return -ENOENT; - - for (l = data->ebooks; l != NULL; l = g_slist_next(l)) { - EBook *ebook = l->data; - - if (e_book_is_opened(ebook) == FALSE) - continue; - - if (e_book_get_contacts_async(ebook, data->query, - ebookpull_cb, data) == TRUE) - data->queued_calls++; - } - - if (data->queued_calls == 0) - return -ENOENT; - - return 0; -} - -void *phonebook_get_entry(const char *folder, const char *id, - const struct apparam_field *params, - phonebook_cb cb, void *user_data, int *err) -{ - struct query_context *data; - GSList *l; - - data = g_new0(struct query_context, 1); - data->contacts_cb = cb; - data->params = params; - data->user_data = user_data; - data->id = g_strdup(id); - data->ebooks = open_ebooks(); - - for (l = data->ebooks; l != NULL; l = g_slist_next(l)) { - EBook *ebook = l->data; - - if (e_book_is_opened(ebook) == FALSE) - continue; - - if (e_book_get_contact_async(ebook, data->id, - ebook_entry_cb, data) == TRUE) - data->queued_calls++; - } - - if (err) - *err = (data->queued_calls == 0 ? -ENOENT : 0); - - return data; -} - void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb, - phonebook_cache_ready_cb ready_cb, void *user_data, int *err) + phonebook_cache_ready_cb ready_cb, void *user_data, int *err) { + /* Build a cache of contacts */ struct query_context *data; EBookQuery *query; - GSList *l; EContact *me; + EBookClient *me_client; EVCard *evcard; GError *gerr = NULL; - EBook *eb; EVCardAttribute *attrib; char *uid, *tel, *cname; @@ -633,23 +566,25 @@ void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb, return NULL; } - DBG(""); - - query = e_book_query_any_field_contains(""); + DBG("creating cache"); data = g_new0(struct query_context, 1); data->entry_cb = entry_cb; data->ready_cb = ready_cb; data->user_data = user_data; - data->query = query; - data->ebooks = open_ebooks(); + query = e_book_query_any_field_contains(""); // all contacts + data->query = e_book_query_to_string(query); + e_book_query_unref(query); - /* Add 0.vcf */ - if (e_book_get_self(&me, &eb, &gerr) == FALSE) { + /* Myself as contact should always be 0.vcf if found in address book */ + if (!e_book_client_get_self(registry, &me, &me_client, &gerr)) { + DBG("owner is not in address book: %s", gerr->message); g_error_free(gerr); goto next; } + DBG("caching address book owner"); + evcard = E_VCARD(me); cname = evcard_name_attribute_to_string(evcard); @@ -668,28 +603,65 @@ void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb, tel = g_strdup(""); data->entry_cb(uid, 0, cname, NULL, tel, data->user_data); - data->count++; g_free(cname); g_free(uid); g_free(tel); - g_object_unref(eb); next: - for (l = data->ebooks; l != NULL; l = g_slist_next(l)) { - EBook *ebook = l->data; - - if (e_book_is_opened(ebook) == FALSE) - continue; - - if (e_book_get_contacts_async(ebook, query, - cache_cb, data) == TRUE) - data->queued_calls++; - } + /* Fetch async contacts from default address book */ + DBG("caching contacts"); + e_book_client_get_contacts(book_client, data->query, NULL, + (GAsyncReadyCallback) phonebook_create_cache_ready, data); + data->queued_calls++; if (err) *err = (data->queued_calls == 0 ? -ENOENT : 0); return data; } + +int phonebook_init(void) +{ + EClient *client; + GError *gerr = NULL; + + /* Acquire ESource Registry */ + registry = e_source_registry_new_sync(NULL, &gerr); + if (gerr != NULL) { + error("Unable to acquire registery: %s\n", gerr->message); + g_error_free(gerr); + return -1; + } + + /* Get ref to default address book */ + address_book = e_source_registry_ref_default_address_book(registry); + if (address_book == NULL) { + error("Unable to get reference to default address book"); + return -2; + } + + /* Allocate e-book client for address book */ + gerr = NULL; + client = e_book_client_connect_sync(address_book, CONNECTION_TIMEOUT, + NULL, &gerr); + if (gerr != NULL || client == NULL) { + error("Cannot connect ebook client to EDS: %s", + gerr != NULL ? gerr->message : "NULL"); + g_error_free(gerr); + return -3; + } + book_client = E_BOOK_CLIENT(client); + + DBG("created address book client"); + + return 0; +} + +void phonebook_exit(void) +{ + g_object_unref(book_client); + g_object_unref(address_book); + g_object_unref(registry); +} From patchwork Fri Jul 23 13:58:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dylan Van Assche X-Patchwork-Id: 12396145 X-Patchwork-Delegate: luiz.dentz@gmail.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C1B27C4338F for ; Fri, 23 Jul 2021 13:58:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 989BE60EFD for ; Fri, 23 Jul 2021 13:58:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235288AbhGWNSY (ORCPT ); Fri, 23 Jul 2021 09:18:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56580 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235094AbhGWNSX (ORCPT ); Fri, 23 Jul 2021 09:18:23 -0400 Received: from mout-p-202.mailbox.org (mout-p-202.mailbox.org [IPv6:2001:67c:2050::465:202]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 40129C061757 for ; Fri, 23 Jul 2021 06:58:57 -0700 (PDT) Received: from smtp1.mailbox.org (smtp1.mailbox.org [IPv6:2001:67c:2050:105:465:1:1:0]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-202.mailbox.org (Postfix) with ESMTPS id 4GWWBl3F5TzQk8x; Fri, 23 Jul 2021 15:58:55 +0200 (CEST) X-Virus-Scanned: amavisd-new at heinlein-support.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dylanvanassche.be; s=MBO0001; t=1627048733; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ItoljjU9olhXYnPeHhYDqZkjzBSH2FEO3akZAxBYXT0=; b=CESz7/DwYkMxcDh5JB08LyLMBxOtQIDUNngPu6+XyXcBsvAH+3H5/lUIFvZGhvAOa21hv/ RyuEcWxtsdq/xT6C4/RSCgavInRJc0frnK8sabSGFflRcH76wgrThT0pLtpbDa0+WBDnq2 /LmFDpg3oWELTKa8reLaN+J0a+hQikL1gqDqK3EWz6i8Y4H4orzoSMPMg6SLHFWsJz14z5 yHNhwNBP8X+g8Pyah0j+dIpGhjRe3EYwYB2c6EG0PxcdZRxU4Ux5P3Rl3LwLY1jjdXdp7j gtTLgjVgyDgE3nNoMMMseRFIkPbPD6vEnPhuhJ1eLsna0BWpWVcMYQWaqmDlug== Received: from smtp1.mailbox.org ([80.241.60.240]) by gerste.heinlein-support.de (gerste.heinlein-support.de [91.198.250.173]) (amavisd-new, port 10030) with ESMTP id vWRYvLLj_AJi; Fri, 23 Jul 2021 15:58:52 +0200 (CEST) From: Dylan Van Assche To: linux-bluetooth@vger.kernel.org Cc: Juho Hamalainen Subject: [PATCH BlueZ 2/4] configure.ac: specify phonebook plugin at build time Date: Fri, 23 Jul 2021 15:58:22 +0200 Message-Id: <20210723135824.8032-3-me@dylanvanassche.be> In-Reply-To: <20210723135824.8032-1-me@dylanvanassche.be> References: <20210723135824.8032-1-me@dylanvanassche.be> MIME-Version: 1.0 X-Rspamd-Queue-Id: 77DEB18CA X-Rspamd-UID: ac0dc6 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Juho Hamalainen Various phonebook plugins are available, by default phonebook-dummy is always built. Allow to specify which plugin to use at build time. --- Makefile.obexd | 2 +- configure.ac | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Makefile.obexd b/Makefile.obexd index 6f5dc04c0..285a56197 100644 --- a/Makefile.obexd +++ b/Makefile.obexd @@ -41,7 +41,7 @@ obexd_builtin_modules += pbap obexd_builtin_sources += obexd/plugins/pbap.c \ obexd/plugins/vcard.h obexd/plugins/vcard.c \ obexd/plugins/phonebook.h \ - obexd/plugins/phonebook-dummy.c + obexd/plugins/phonebook-@PLUGIN_PHONEBOOK@.c obexd_builtin_modules += mas obexd_builtin_sources += obexd/plugins/mas.c obexd/src/map_ap.h \ diff --git a/configure.ac b/configure.ac index be32782a6..113ab0e0f 100644 --- a/configure.ac +++ b/configure.ac @@ -416,4 +416,12 @@ fi AC_DEFINE_UNQUOTED(ANDROID_STORAGEDIR, "${storagedir}/android", [Directory for the Android daemon storage files]) +AC_ARG_WITH([phonebook], AC_HELP_STRING([--with-phonebook=PLUGIN], + [obexd phonebook plugin (default=dummy)]), + [plugin_phonebook=${withval}]) +if (test -z "${plugin_phonebook}"); then + plugin_phonebook=dummy +fi +AC_SUBST(PLUGIN_PHONEBOOK, [${plugin_phonebook}]) + AC_OUTPUT(Makefile src/bluetoothd.rst lib/bluez.pc mesh/bluetooth-meshd.rst) From patchwork Fri Jul 23 13:58:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dylan Van Assche X-Patchwork-Id: 12396149 X-Patchwork-Delegate: luiz.dentz@gmail.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 528EDC432BE for ; Fri, 23 Jul 2021 13:58:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 320A060EB4 for ; Fri, 23 Jul 2021 13:58:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235318AbhGWNSZ (ORCPT ); Fri, 23 Jul 2021 09:18:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56582 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235126AbhGWNSX (ORCPT ); Fri, 23 Jul 2021 09:18:23 -0400 Received: from mout-p-102.mailbox.org (mout-p-102.mailbox.org [IPv6:2001:67c:2050::465:102]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6C3F4C06175F for ; Fri, 23 Jul 2021 06:58:57 -0700 (PDT) Received: from smtp1.mailbox.org (smtp1.mailbox.org [80.241.60.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4GWWBl6l9zzQkBs; Fri, 23 Jul 2021 15:58:55 +0200 (CEST) X-Virus-Scanned: amavisd-new at heinlein-support.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dylanvanassche.be; s=MBO0001; t=1627048734; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=c0GPxelqby7YufxBOEsKvHYMlKRcOobr61YmT/rUX2E=; b=nQbtfs5gmgTRlNhkjdAxXwlGJGmo45HZNgY9w8H/rs9WGYVwjDRbkFfiA2NT1hCrqctB1F f8VOKdK9M4cpYmFRXRuCoLQN122lOuOdm0XufUY0ciuM6Ym21sBWgq0u/VuM5l895t7Pd3 /VmCcUy54k7J3z3MBCgtREZRQcdKWsg6rszH+MIWjj7Qpb3Y8Vn5HAH0fdwBw2g2AuHxEz tGuPuwKMa++jwfXl+HE5yQZYqxSc269BbfRQtUUB+Mo7BGzpZh05OHq/4KBchnoY005rmf cubjvqj2TJY8TD6cAjJ2A7TXsyk4Jw8sxTjKo8lIou2o7r2b1CxQB9KCIPxwXQ== Received: from smtp1.mailbox.org ([80.241.60.240]) by spamfilter02.heinlein-hosting.de (spamfilter02.heinlein-hosting.de [80.241.56.116]) (amavisd-new, port 10030) with ESMTP id 31EJClwTXw0c; Fri, 23 Jul 2021 15:58:53 +0200 (CEST) From: Dylan Van Assche To: linux-bluetooth@vger.kernel.org Cc: Dylan Van Assche Subject: [PATCH BlueZ 3/4] configure.ac: add libebook dependency Date: Fri, 23 Jul 2021 15:58:23 +0200 Message-Id: <20210723135824.8032-4-me@dylanvanassche.be> In-Reply-To: <20210723135824.8032-1-me@dylanvanassche.be> References: <20210723135824.8032-1-me@dylanvanassche.be> MIME-Version: 1.0 X-Rspamd-Queue-Id: 2955918B5 X-Rspamd-UID: d946f0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org Require libebook when phonebook-ebook plugin is built. --- Makefile.am | 2 +- Makefile.obexd | 2 +- configure.ac | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 497f05f06..0fd405e8c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ pkgincludedir = $(includedir)/bluetooth pkginclude_HEADERS = -AM_CFLAGS = $(WARNING_CFLAGS) $(MISC_CFLAGS) $(UDEV_CFLAGS) $(ell_cflags) +AM_CFLAGS = $(WARNING_CFLAGS) $(MISC_CFLAGS) $(UDEV_CFLAGS) $(LIBEBOOK_CFLAGS) $(LIBEDATASERVER_CFLAGS) $(ell_cflags) AM_LDFLAGS = $(MISC_LDFLAGS) if DATAFILES diff --git a/Makefile.obexd b/Makefile.obexd index 285a56197..2c0d19518 100644 --- a/Makefile.obexd +++ b/Makefile.obexd @@ -80,7 +80,7 @@ obexd_src_obexd_SOURCES = $(btio_sources) $(gobex_sources) \ obexd/src/map_ap.h obexd_src_obexd_LDADD = lib/libbluetooth-internal.la \ gdbus/libgdbus-internal.la \ - $(ICAL_LIBS) $(DBUS_LIBS) $(GLIB_LIBS) -ldl + $(ICAL_LIBS) $(DBUS_LIBS) $(LIBEBOOK_LIBS) $(LIBEDATASERVER_LIBS) $(GLIB_LIBS) -ldl obexd_src_obexd_LDFLAGS = $(AM_LDFLAGS) -Wl,--export-dynamic diff --git a/configure.ac b/configure.ac index 113ab0e0f..a5afaea6c 100644 --- a/configure.ac +++ b/configure.ac @@ -422,6 +422,15 @@ AC_ARG_WITH([phonebook], AC_HELP_STRING([--with-phonebook=PLUGIN], if (test -z "${plugin_phonebook}"); then plugin_phonebook=dummy fi + +if (test "${plugin_phonebook}" = "ebook"); then + PKG_CHECK_MODULES(LIBEBOOK, [libebook-1.2 >= 3.3], dummy=yes, AC_MSG_ERROR(libebook >= 3.3 is required)) + AC_SUBST(LIBEBOOK_CFLAGS) + AC_SUBST(LIBEBOOK_LIBS) + PKG_CHECK_MODULES(LIBEDATESERVER, [libedataserver-1.2 >= 3.3], dummy=yes, AC_MSG_ERROR(libedataserver >= 3.3 is required)) + AC_SUBST(LIBEDATESERVER_CFLAGS) + AC_SUBST(LIBEDATESERVER_LIBS) +fi AC_SUBST(PLUGIN_PHONEBOOK, [${plugin_phonebook}]) AC_OUTPUT(Makefile src/bluetoothd.rst lib/bluez.pc mesh/bluetooth-meshd.rst) From patchwork Fri Jul 23 13:58:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dylan Van Assche X-Patchwork-Id: 12396147 X-Patchwork-Delegate: luiz.dentz@gmail.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE14AC43214 for ; Fri, 23 Jul 2021 13:58:59 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9120060EB4 for ; Fri, 23 Jul 2021 13:58:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235323AbhGWNSZ (ORCPT ); Fri, 23 Jul 2021 09:18:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56590 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235311AbhGWNSY (ORCPT ); Fri, 23 Jul 2021 09:18:24 -0400 Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [IPv6:2001:67c:2050::465:101]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7891AC061757 for ; Fri, 23 Jul 2021 06:58:58 -0700 (PDT) Received: from smtp1.mailbox.org (smtp1.mailbox.org [80.241.60.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4GWWBm73sYzQjBM; Fri, 23 Jul 2021 15:58:56 +0200 (CEST) X-Virus-Scanned: amavisd-new at heinlein-support.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dylanvanassche.be; s=MBO0001; t=1627048735; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rqbpAGcd49pYp2w1BblwMuGhH6qZvIOz8MUBv68fiFI=; b=XWOIHfK50ZuWtsUPtewXJcr2UiikzFGHrroXaeT/OvMP1bF3LBcvuQ1gFgGj/hpxwRCiBE bWWQQiPEEy9Ajw3Ate+jeCU/MASKWi5D7ARA6YOR26JeV9xyd/a7hBsMuAL60pZDGT/s/w b9oMzZs5wykf7PvdDOf5Qyb6TXAfvOdmox57nD4WKaO9DTJafgOe6Ioi1WxsgeVKqsNMhE K4YmI2UyL+VgrH45BzjOHRFiyTMc2Q2Mybh8gmIgM7PIHFXby0ZOZXHnKo6u2eFghFt8rl k9RsSkWAc8eNsK3P6WxHATfLqG9ooxWjxxrr25r9xYz0y0QpO3n3CXw133Mcug== Received: from smtp1.mailbox.org ([80.241.60.240]) by spamfilter05.heinlein-hosting.de (spamfilter05.heinlein-hosting.de [80.241.56.123]) (amavisd-new, port 10030) with ESMTP id SvvYvM_GF8Cv; Fri, 23 Jul 2021 15:58:54 +0200 (CEST) From: Dylan Van Assche To: linux-bluetooth@vger.kernel.org Cc: Hannu Mallat Subject: [PATCH BlueZ 4/4] obexd: phonebook: Set default apparams for PTS clients Date: Fri, 23 Jul 2021 15:58:24 +0200 Message-Id: <20210723135824.8032-5-me@dylanvanassche.be> In-Reply-To: <20210723135824.8032-1-me@dylanvanassche.be> References: <20210723135824.8032-1-me@dylanvanassche.be> MIME-Version: 1.0 X-Rspamd-Queue-Id: 3976918C6 X-Rspamd-UID: d8e3da Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Hannu Mallat Some PTS clients do not send all the mandatory apparams when retrieving the phonebook. Clients such as car multimedia systems cannot be fixed, therefore working around this issue by inserting default apparams which makes these clients work as well. --- obexd/plugins/pbap.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c index efae92cd8..ab5236316 100644 --- a/obexd/plugins/pbap.c +++ b/obexd/plugins/pbap.c @@ -511,6 +511,21 @@ static int pbap_get(struct obex_session *os, void *user_data) rsize = 0; } + /* Workaround for PTS client not sending mandatory apparams */ + if (!rsize && g_ascii_strcasecmp(type, VCARDLISTING_TYPE) == 0) { + static const uint8_t default_apparams[] = { + 0x04, 0x02, 0xff, 0xff + }; + buffer = default_apparams; + rsize = sizeof(default_apparams); + } else if (!rsize && g_ascii_strcasecmp(type, VCARDENTRY_TYPE) == 0) { + static const uint8_t default_apparams[] = { + 0x07, 0x01, 0x00 + }; + buffer = default_apparams; + rsize = sizeof(default_apparams); + } + params = parse_aparam(buffer, rsize); if (params == NULL) return -EBADR;