Subject: [PATCH BlueZ 0/9] Distribution inspired fixes

Hello team,

This series picks (directly where possible) distro shipped fixes, for
upstream inclusion.

In particular we have:
- first two patches have been in SteamOS 3 for about 1 year
- adapter: Remove experimental flag for PowerState - has been shipping
in Gentoo and Fedora since Dec 2022, at least
- use /usr/bin/env python3 sheband - Debian inspired
- remove unused suspend-dummy.c - Debian inspired
- remove three unused obex plugins/backends - inspired by ^^ removal
- ship all conf files with --enable-datafiles - Arch, Gentoo, Fedora

Everything apart from the first two, should be dead trivial. I have
little knowledge about the SteamOS inspired fixes, so hopefully
maintainers won't have too many questions there ;-)

As the comment in the last commit says - there's one final batch
(planned) of patches. Allowing for more flexible conf management, akin
to `man sysctl.d`.

Although I will send those out, once most of the existing patches have
landed.

---
Bastien Nocera (1):
adapter: Remove experimental flag for PowerState

Emil Velikov (6):
test: consistently use /usr/bin/env python3 shebang
profiles: remove unused suspend-dummy.c
obex: remove unused syncevolution plugin
obex: remove unused mas/messages-tracker impl
obex: remove phonebook tracker backend
build: ship all config files with --enable-datafiles

Sam Lantinga (1):
Return at least the title attribute from player_list_metadata()

Vicki Pfau (1):
Enable alternate Bluetooth connection modes

Makefile.am | 8 +-
Makefile.mesh | 1 +
Makefile.obexd | 3 +-
Makefile.plugins | 2 -
configure.ac | 6 +-
obexd/plugins/messages-tracker.c | 332 --------
obexd/plugins/phonebook-tracker.c | 1704 -------------------------------------
obexd/plugins/syncevolution.c | 470 ----------
profiles/audio/avrcp.c | 4 +
profiles/input/suspend-dummy.c | 149 ----
src/adapter.c | 49 +-
src/btd.h | 2 +
src/main.c | 66 ++
src/main.conf | 5 +
test/agent.py | 2 +-
test/example-adv-monitor | 2 +-
test/example-advertisement | 2 +-
test/example-endpoint | 2 +-
test/example-player | 2 +-
test/exchange-business-cards | 2 +-
test/ftp-client | 2 +-
test/get-managed-objects | 2 +-
test/get-obex-capabilities | 2 +-
test/list-devices | 2 +-
test/list-folders | 2 +-
test/map-client | 2 +-
test/monitor-bluetooth | 2 +-
test/opp-client | 2 +-
test/pbap-client | 2 +-
test/simple-agent | 2 +-
test/simple-endpoint | 2 +-
test/simple-obex-agent | 2 +-
test/simple-player | 2 +-
test/test-adapter | 2 +-
test/test-device | 2 +-
test/test-discovery | 2 +-
test/test-gatt-profile | 2 +-
test/test-health | 2 +-
test/test-health-sink | 2 +-
test/test-hfp | 2 +-
test/test-manager | 2 +-
test/test-nap | 2 +-
test/test-network | 2 +-
test/test-profile | 2 +-
test/test-sap-server | 2 +-
45 files changed, 167 insertions(+), 2696 deletions(-)
---
base-commit: a9d1f6f6a625607de6c3f5b7a40a3aac5f36c02b
change-id: 20240124-disto-patches-efd6b726602f

Best regards,
--
Emil Velikov <[email protected]>



Subject: [PATCH BlueZ 3/9] adapter: Remove experimental flag for PowerState

From: Bastien Nocera <[email protected]>

Now that the feature has been tested, that the API is deemed adequate
and the reliability sufficient.

[Emil Velikov]
The feature has landed in Sept 2022, with inclinations that "we might
switch it to stable in the next release", back in Nov 2022.

Today - a bit over 1 year later - various distributions (Fedora, Gentoo
and by extension their derivatives) are carrying this patch. I think we
can say we're reasonably stable and can merge it upstream.
---
src/adapter.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/adapter.c b/src/adapter.c
index 4c6b8f40f..31ccaf54b 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -3956,8 +3956,7 @@ static const GDBusPropertyTable adapter_properties[] = {
{ "Alias", "s", property_get_alias, property_set_alias },
{ "Class", "u", property_get_class },
{ "Powered", "b", property_get_powered, property_set_powered },
- { "PowerState", "s", property_get_power_state, NULL, NULL,
- G_DBUS_PROPERTY_FLAG_EXPERIMENTAL },
+ { "PowerState", "s", property_get_power_state },
{ "Discoverable", "b", property_get_discoverable,
property_set_discoverable },
{ "DiscoverableTimeout", "u", property_get_discoverable_timeout,

--
2.43.0


Subject: [PATCH BlueZ 4/9] test: consistently use /usr/bin/env python3 shebang

From: Emil Velikov <[email protected]>

Currently we have a mix of /usr/bin/python, /usr/bin/python3 and
/usr/bin/env python3. Use the latter since is the more common way of
handling this, plus it allows people to override the system python (for
what ever reason).

Inspired by a Debian patch, doing a mass /usr/bin/python{,3} conversion.

Cc: Nobuhiro Iwamatsu <[email protected]>
---
test/agent.py | 2 +-
test/example-adv-monitor | 2 +-
test/example-advertisement | 2 +-
test/example-endpoint | 2 +-
test/example-player | 2 +-
test/exchange-business-cards | 2 +-
test/ftp-client | 2 +-
test/get-managed-objects | 2 +-
test/get-obex-capabilities | 2 +-
test/list-devices | 2 +-
test/list-folders | 2 +-
test/map-client | 2 +-
test/monitor-bluetooth | 2 +-
test/opp-client | 2 +-
test/pbap-client | 2 +-
test/simple-agent | 2 +-
test/simple-endpoint | 2 +-
test/simple-obex-agent | 2 +-
test/simple-player | 2 +-
test/test-adapter | 2 +-
test/test-device | 2 +-
test/test-discovery | 2 +-
test/test-gatt-profile | 2 +-
test/test-health | 2 +-
test/test-health-sink | 2 +-
test/test-hfp | 2 +-
test/test-manager | 2 +-
test/test-nap | 2 +-
test/test-network | 2 +-
test/test-profile | 2 +-
test/test-sap-server | 2 +-
31 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/test/agent.py b/test/agent.py
index 57a74183d..450fb20a3 100755
--- a/test/agent.py
+++ b/test/agent.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python3
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

import sys
diff --git a/test/example-adv-monitor b/test/example-adv-monitor
index a405fc7b0..09888a973 100644
--- a/test/example-adv-monitor
+++ b/test/example-adv-monitor
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

import argparse
diff --git a/test/example-advertisement b/test/example-advertisement
index 5f022ee67..910701220 100755
--- a/test/example-advertisement
+++ b/test/example-advertisement
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import print_function
diff --git a/test/example-endpoint b/test/example-endpoint
index 16651c683..cb5ac2ae9 100644
--- a/test/example-endpoint
+++ b/test/example-endpoint
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/example-player b/test/example-player
index 167460bad..9d56b4a13 100644
--- a/test/example-player
+++ b/test/example-player
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import print_function
diff --git a/test/exchange-business-cards b/test/exchange-business-cards
index 9a3aa29fb..12d513362 100755
--- a/test/exchange-business-cards
+++ b/test/exchange-business-cards
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

import sys
diff --git a/test/ftp-client b/test/ftp-client
index ef756ab2b..e37c027f4 100755
--- a/test/ftp-client
+++ b/test/ftp-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/get-managed-objects b/test/get-managed-objects
index 5125ee524..7ad359db4 100755
--- a/test/get-managed-objects
+++ b/test/get-managed-objects
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/get-obex-capabilities b/test/get-obex-capabilities
index a7980a442..25a996e18 100755
--- a/test/get-obex-capabilities
+++ b/test/get-obex-capabilities
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

import sys
diff --git a/test/list-devices b/test/list-devices
index 618d2867b..a24c31c7d 100755
--- a/test/list-devices
+++ b/test/list-devices
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/list-folders b/test/list-folders
index b4e3f100b..414bb367b 100755
--- a/test/list-folders
+++ b/test/list-folders
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

import sys
diff --git a/test/map-client b/test/map-client
index f44f512bd..b7369b068 100755
--- a/test/map-client
+++ b/test/map-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/monitor-bluetooth b/test/monitor-bluetooth
index 99f3c857c..347c91ac3 100755
--- a/test/monitor-bluetooth
+++ b/test/monitor-bluetooth
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/opp-client b/test/opp-client
index 4f00a41c0..deb02c77c 100755
--- a/test/opp-client
+++ b/test/opp-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/pbap-client b/test/pbap-client
index e6cafdd30..6dada4a11 100755
--- a/test/pbap-client
+++ b/test/pbap-client
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-agent b/test/simple-agent
index 4fdaff1eb..09437eb22 100755
--- a/test/simple-agent
+++ b/test/simple-agent
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-endpoint b/test/simple-endpoint
index 463f124d1..eace4286d 100755
--- a/test/simple-endpoint
+++ b/test/simple-endpoint
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-obex-agent b/test/simple-obex-agent
index 064f6d30b..65807bff3 100755
--- a/test/simple-obex-agent
+++ b/test/simple-obex-agent
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/simple-player b/test/simple-player
index 7bad3d14f..190e047e2 100755
--- a/test/simple-player
+++ b/test/simple-player
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import print_function
diff --git a/test/test-adapter b/test/test-adapter
index c56ba9577..27aff27b5 100755
--- a/test/test-adapter
+++ b/test/test-adapter
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-device b/test/test-device
index c840f0565..8b1eb86d1 100755
--- a/test/test-device
+++ b/test/test-device
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-discovery b/test/test-discovery
index 54fc51403..6959e7be9 100755
--- a/test/test-discovery
+++ b/test/test-discovery
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-gatt-profile b/test/test-gatt-profile
index a973ae14e..64ff3e5f9 100755
--- a/test/test-gatt-profile
+++ b/test/test-gatt-profile
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-health b/test/test-health
index 3e16c415d..f26def906 100755
--- a/test/test-health
+++ b/test/test-health
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-health-sink b/test/test-health-sink
index 13b9a6b04..fcdc58e3d 100755
--- a/test/test-health-sink
+++ b/test/test-health-sink
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-hfp b/test/test-hfp
index 11e328e54..e1edac0aa 100755
--- a/test/test-hfp
+++ b/test/test-hfp
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-manager b/test/test-manager
index 3fa7205a0..a93819e27 100755
--- a/test/test-manager
+++ b/test/test-manager
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-nap b/test/test-nap
index d5c757b79..76cde74d4 100755
--- a/test/test-nap
+++ b/test/test-nap
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-network b/test/test-network
index acc7dff65..67be86106 100755
--- a/test/test-network
+++ b/test/test-network
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-profile b/test/test-profile
index af1e23f76..7d92f390e 100755
--- a/test/test-profile
+++ b/test/test-profile
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals
diff --git a/test/test-sap-server b/test/test-sap-server
index ddb1efe9b..161a4bfec 100755
--- a/test/test-sap-server
+++ b/test/test-sap-server
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later

from __future__ import absolute_import, print_function, unicode_literals

--
2.43.0


Subject: [PATCH BlueZ 5/9] profiles: remove unused suspend-dummy.c

From: Emil Velikov <[email protected]>

The file has been used for about 8 years now - see commit fb55b7a6a
("profiles/hog: Use no suspend support instead of the dummy FIFO").

Inspired by a Debian patch by Nobuhiro Iwamatsu, which was changing the
/tmp/hogsuspend socket patch to /run. Looking through the codebase we
have a few more sockets that could use a to /run fix, but that will
follow-up at another day.

Cc: Nobuhiro Iwamatsu <[email protected]>
---
Makefile.plugins | 2 -
profiles/input/suspend-dummy.c | 149 -----------------------------------------
2 files changed, 151 deletions(-)

diff --git a/Makefile.plugins b/Makefile.plugins
index 5880ed0df..61a5cf687 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -74,8 +74,6 @@ builtin_sources += profiles/input/hog.c \
profiles/battery/bas.c profiles/battery/bas.h \
profiles/scanparam/scpp.c profiles/scanparam/scpp.h \
profiles/input/suspend.h profiles/input/suspend-none.c
-
-EXTRA_DIST += profiles/input/suspend-dummy.c
endif

if HEALTH
diff --git a/profiles/input/suspend-dummy.c b/profiles/input/suspend-dummy.c
deleted file mode 100644
index ea1835e0f..000000000
--- a/profiles/input/suspend-dummy.c
+++ /dev/null
@@ -1,149 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2012 Nordic Semiconductor Inc.
- * Copyright (C) 2012 Instituto Nokia de Tecnologia - INdT
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include <glib.h>
-
-#include "src/log.h"
-#include "suspend.h"
-
-#define HOG_SUSPEND_FIFO "/tmp/hogsuspend"
-
-static suspend_event suspend_cb = NULL;
-static resume_event resume_cb = NULL;
-static guint watch = 0;
-
-static int fifo_open(void);
-
-static gboolean read_fifo(GIOChannel *io, GIOCondition cond, gpointer user_data)
-{
- char buffer[12];
- gsize offset, left, bread;
- GIOStatus iostatus;
-
- if (cond & (G_IO_ERR | G_IO_HUP)) {
- /*
- * Both ends needs to be open simultaneously before proceeding
- * any input or output operation. When the remote closes the
- * channel, hup signal is received on this end.
- */
- fifo_open();
- return FALSE;
- }
-
- offset = 0;
- left = sizeof(buffer) - 1;
- memset(buffer, 0, sizeof(buffer));
-
- do {
- iostatus = g_io_channel_read_chars(io, &buffer[offset], left,
- &bread, NULL);
-
- offset += bread;
- left -= bread;
- if (left == 0)
- break;
- } while (iostatus == G_IO_STATUS_NORMAL);
-
- if (g_ascii_strncasecmp("suspend", buffer, 7) == 0)
- suspend_cb();
- else if (g_ascii_strncasecmp("resume", buffer, 6) == 0)
- resume_cb();
-
- return TRUE;
-}
-
-static int fifo_open(void)
-{
- GIOCondition condition = G_IO_IN | G_IO_ERR | G_IO_HUP;
- GIOChannel *fifoio;
- int fd;
-
- fd = open(HOG_SUSPEND_FIFO, O_RDONLY | O_NONBLOCK);
- if (fd < 0) {
- int err = -errno;
- error("Can't open FIFO (%s): %s(%d)", HOG_SUSPEND_FIFO,
- strerror(-err), -err);
- return err;
- }
-
- fifoio = g_io_channel_unix_new(fd);
- g_io_channel_set_close_on_unref(fifoio, TRUE);
-
- watch = g_io_add_watch(fifoio, condition, read_fifo, NULL);
-
- g_io_channel_unref(fifoio);
-
- return 0;
-}
-
-int suspend_init(suspend_event suspend, resume_event resume)
-{
- struct stat st;
- int ret;
-
- DBG("");
-
- suspend_cb = suspend;
- resume_cb = resume;
-
- if (stat(HOG_SUSPEND_FIFO, &st) == 0) {
- if (!S_ISFIFO(st.st_mode)) {
- error("Unexpected non-FIFO %s file", HOG_SUSPEND_FIFO);
- return -EIO;
- }
-
- if (unlink(HOG_SUSPEND_FIFO) < 0) {
- int err = -errno;
- error("Failed to remove FIFO (%s): %s (%d)",
- HOG_SUSPEND_FIFO, strerror(-err), -err);
- return err;
- }
- }
-
- if (mkfifo(HOG_SUSPEND_FIFO, 0600) < 0) {
- int err = -errno;
-
- error("Can't create FIFO (%s): %s (%d)", HOG_SUSPEND_FIFO,
- strerror(-err), -err);
- return err;
- }
-
- DBG("Created suspend-dummy FIFO on %s", HOG_SUSPEND_FIFO);
-
- ret = fifo_open();
- if (ret < 0)
- unlink(HOG_SUSPEND_FIFO);
-
- return ret;
-}
-
-void suspend_exit(void)
-{
- if (watch > 0) {
- g_source_remove(watch);
- watch = 0;
- }
-
- unlink(HOG_SUSPEND_FIFO);
-}

--
2.43.0


Subject: [PATCH BlueZ 9/9] build: ship all config files with --enable-datafiles

From: Emil Velikov <[email protected]>

Currently we ship only the dbus/systemd policy files and omit the other
four - /etc/bluetooth/{main,mesh-main,input,network}.conf.

Outside of those files, there is no documentation what the defaults are
and the other possible options. A number of distributions (Arch, Gentoo,
Fedora) have opted to manually copy those into the package. Alas this
does not scale and leaves other distros at disadvantage, in a sense.

Note: we need a custom install target to ensure confdir and statedir
have the correct permissions.
---
Some distributions do toggle some of the default values, by patching the
source tree. Future patches will add support for more maintainable
configuration handling akin to `man sysctl.d`.
---
Makefile.am | 8 +++++++-
Makefile.mesh | 1 +
2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index e738eb3a5..9c19cec49 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,11 +31,17 @@ AM_LDFLAGS = $(MISC_LDFLAGS)
confdir = $(sysconfdir)/bluetooth
statedir = $(localstatedir)/lib/bluetooth

+install-data-hook:
+ install -dm555 $(DESTDIR)$(confdir)
+ install -dm700 $(DESTDIR)$(statedir)
+
if DATAFILES
dbusdir = $(DBUS_CONFDIR)/dbus-1/system.d
dbus_DATA = src/bluetooth.conf

-conf_DATA =
+conf_DATA = src/main.conf
+conf_DATA += profiles/input/input.conf
+conf_DATA += profiles/network/network.conf
state_DATA =
endif

diff --git a/Makefile.mesh b/Makefile.mesh
index 63f085de1..930262d53 100644
--- a/Makefile.mesh
+++ b/Makefile.mesh
@@ -3,6 +3,7 @@ if MESH

if DATAFILES
dbus_DATA += mesh/bluetooth-mesh.conf
+conf_DATA += mesh/mesh-main.conf
endif

if SYSTEMD

--
2.43.0


Subject: [PATCH BlueZ 6/9] obex: remove unused syncevolution plugin

From: Emil Velikov <[email protected]>

Based on my git log archaeology, the plugin was never built despite
receiving multiple updates across the years. It's possible that the git
history is lost when (if?) obexd code was imported.

The file isn't in the official tarball, so end users cannot enable if
even if they wanted to. So let's remove the dead/unused plugin.

There is some existing infra around OBEX_SYNCEVOLUTION which can be
checked/removed as follow-up.
---
obexd/plugins/syncevolution.c | 470 ------------------------------------------
1 file changed, 470 deletions(-)

diff --git a/obexd/plugins/syncevolution.c b/obexd/plugins/syncevolution.c
deleted file mode 100644
index ae3dc48c4..000000000
--- a/obexd/plugins/syncevolution.c
+++ /dev/null
@@ -1,470 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * OBEX Server
- *
- * Copyright (C) 2007-2010 Intel Corporation
- * Copyright (C) 2007-2010 Marcel Holtmann <[email protected]>
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/types.h>
-
-#include <glib.h>
-#include <dbus/dbus.h>
-
-#include "lib/bluetooth.h"
-
-#include "gdbus/gdbus.h"
-
-#include "btio/btio.h"
-#include "obexd/src/plugin.h"
-#include "obexd/src/obex.h"
-#include "obexd/src/service.h"
-#include "obexd/src/mimetype.h"
-#include "obexd/src/log.h"
-#include "obexd/src/manager.h"
-#include "obexd/src/obexd.h"
-#include "filesystem.h"
-
-#define SYNCML_TARGET_SIZE 11
-
-static const uint8_t SYNCML_TARGET[SYNCML_TARGET_SIZE] = {
- 0x53, 0x59, 0x4E, 0x43, 0x4D, 0x4C, 0x2D, 0x53,
- 0x59, 0x4E, 0x43 };
-
-#define SYNCEVOLUTION_CHANNEL 19
-
-#define SYNCEVOLUTION_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\
-<record> \
- <attribute id=\"0x0001\"> \
- <sequence> \
- <uuid value=\"00000002-0000-1000-8000-0002ee000002\"/> \
- </sequence> \
- </attribute> \
- \
- <attribute id=\"0x0004\"> \
- <sequence> \
- <sequence> \
- <uuid value=\"0x0100\"/> \
- </sequence> \
- <sequence> \
- <uuid value=\"0x0003\"/> \
- <uint8 value=\"%u\" name=\"channel\"/> \
- </sequence> \
- <sequence> \
- <uuid value=\"0x0008\"/> \
- </sequence> \
- </sequence> \
- </attribute> \
- \
- <attribute id=\"0x0100\"> \
- <text value=\"%s\" name=\"name\"/> \
- </attribute> \
-</record>"
-
-#define SYNCE_BUS_NAME "org.syncevolution"
-#define SYNCE_PATH "/org/syncevolution/Server"
-#define SYNCE_SERVER_INTERFACE "org.syncevolution.Server"
-#define SYNCE_CONN_INTERFACE "org.syncevolution.Connection"
-
-struct synce_context {
- struct obex_session *os;
- DBusConnection *dbus_conn;
- char *conn_obj;
- unsigned int reply_watch;
- unsigned int abort_watch;
- GString *buffer;
- int lasterr;
- char *id;
-};
-
-static void append_dict_entry(DBusMessageIter *dict, const char *key,
- int type, void *val)
-{
- DBusMessageIter entry;
-
- dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
- NULL, &entry);
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
- dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &val);
- dbus_message_iter_close_container(dict, &entry);
-}
-
-static gboolean reply_signal(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- struct synce_context *context = data;
- const char *path = dbus_message_get_path(msg);
- DBusMessageIter iter, array_iter;
- char *value;
- int length;
-
- if (strcmp(context->conn_obj, path) != 0) {
- obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
- context->lasterr = -EPERM;
- return FALSE;
- }
-
- dbus_message_iter_init(msg, &iter);
-
- dbus_message_iter_recurse(&iter, &array_iter);
- dbus_message_iter_get_fixed_array(&array_iter, &value, &length);
-
- context->buffer = g_string_new_len(value, length);
- obex_object_set_io_flags(context, G_IO_IN, 0);
- context->lasterr = 0;
-
- return TRUE;
-}
-
-static gboolean abort_signal(DBusConnection *conn, DBusMessage *msg,
- void *data)
-{
- struct synce_context *context = data;
-
- obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
- context->lasterr = -EPERM;
-
- return TRUE;
-}
-
-static void connect_cb(DBusPendingCall *call, void *user_data)
-{
- struct synce_context *context = user_data;
- DBusConnection *conn;
- DBusMessage *reply;
- DBusError err;
- char *path;
-
- conn = context->dbus_conn;
-
- reply = dbus_pending_call_steal_reply(call);
-
- dbus_error_init(&err);
- if (dbus_message_get_args(reply, &err, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID) == FALSE) {
- error("%s", err.message);
- dbus_error_free(&err);
- goto failed;
- }
-
- DBG("Got conn object %s from syncevolution", path);
- context->conn_obj = g_strdup(path);
-
- context->reply_watch = g_dbus_add_signal_watch(conn, NULL, path,
- SYNCE_CONN_INTERFACE, "Reply",
- reply_signal, context, NULL);
-
- context->abort_watch = g_dbus_add_signal_watch(conn, NULL, path,
- SYNCE_CONN_INTERFACE, "Abort",
- abort_signal, context, NULL);
-
- dbus_message_unref(reply);
-
- return;
-
-failed:
- obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
- context->lasterr = -EPERM;
-}
-
-static void process_cb(DBusPendingCall *call, void *user_data)
-{
- struct synce_context *context = user_data;
- DBusMessage *reply;
- DBusError derr;
-
- reply = dbus_pending_call_steal_reply(call);
- dbus_error_init(&derr);
- if (dbus_set_error_from_message(&derr, reply)) {
- error("process_cb(): syncevolution replied with an error:"
- " %s, %s", derr.name, derr.message);
- dbus_error_free(&derr);
-
- obex_object_set_io_flags(context, G_IO_ERR, -EPERM);
- context->lasterr = -EPERM;
- goto done;
- }
-
- obex_object_set_io_flags(context, G_IO_OUT, 0);
- context->lasterr = 0;
-
-done:
- dbus_message_unref(reply);
-}
-
-static void *synce_connect(struct obex_session *os, int *err)
-{
- DBusConnection *conn;
- struct synce_context *context;
- char *address;
-
- manager_register_session(os);
-
- conn = manager_dbus_get_connection();
- if (!conn)
- goto failed;
-
- context = g_new0(struct synce_context, 1);
- context->dbus_conn = conn;
- context->lasterr = -EAGAIN;
- context->os = os;
-
- if (obex_getpeername(os, &address) == 0) {
- context->id = g_strdup_printf("%s+%d", address,
- SYNCEVOLUTION_CHANNEL);
- g_free(address);
- }
-
- if (err)
- *err = 0;
-
- return context;
-
-failed:
- if (err)
- *err = -EPERM;
-
- return NULL;
-}
-
-static int synce_put(struct obex_session *os, void *user_data)
-{
- return 0;
-}
-
-static int synce_get(struct obex_session *os, void *user_data)
-{
- return obex_get_stream_start(os, NULL);
-}
-
-static void close_cb(DBusPendingCall *call, void *user_data)
-{
- DBusMessage *reply;
- DBusError derr;
-
- reply = dbus_pending_call_steal_reply(call);
- dbus_error_init(&derr);
- if (dbus_set_error_from_message(&derr, reply)) {
- error("close_cb(): syncevolution replied with an error:"
- " %s, %s", derr.name, derr.message);
- dbus_error_free(&derr);
- }
-
- dbus_message_unref(reply);
-}
-
-static void synce_disconnect(struct obex_session *os, void *user_data)
-{
- struct synce_context *context = user_data;
-
- g_free(context);
-}
-
-static void *synce_open(const char *name, int oflag, mode_t mode,
- void *user_data, size_t *size, int *err)
-{
- struct synce_context *context = user_data;
-
- if (err)
- *err = context ? 0 : -EFAULT;
-
- return user_data;
-}
-
-static int synce_close(void *object)
-{
- struct synce_context *context = object;
- DBusMessage *msg;
- const char *error;
- gboolean normal;
- DBusPendingCall *call;
-
- if (!context->conn_obj)
- goto done;
-
- msg = dbus_message_new_method_call(SYNCE_BUS_NAME, context->conn_obj,
- SYNCE_CONN_INTERFACE, "Close");
- if (!msg)
- goto failed;
-
- normal = TRUE;
- error = "none";
- dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &normal,
- DBUS_TYPE_STRING, &error, DBUS_TYPE_INVALID);
-
- g_dbus_send_message_with_reply(context->dbus_conn, msg, &call, -1);
- dbus_pending_call_set_notify(call, close_cb, NULL, NULL);
- dbus_message_unref(msg);
- dbus_pending_call_unref(call);
-
-failed:
- g_dbus_remove_watch(context->dbus_conn, context->reply_watch);
- context->reply_watch = 0;
- g_dbus_remove_watch(context->dbus_conn, context->abort_watch);
- context->abort_watch = 0;
-
- g_free(context->conn_obj);
- context->conn_obj = NULL;
-
-done:
- dbus_connection_unref(context->dbus_conn);
- g_free(context);
- return 0;
-}
-
-static ssize_t synce_read(void *object, void *buf, size_t count)
-{
- struct synce_context *context = object;
- DBusConnection *conn;
- char transport[36], transport_description[24];
- const char *session;
- DBusMessage *msg;
- DBusMessageIter iter, dict;
- gboolean authenticate;
- DBusPendingCall *call;
-
- if (context->buffer)
- return string_read(context->buffer, buf, count);
-
- conn = manager_dbus_get_connection();
- if (conn == NULL)
- return -EPERM;
-
- msg = dbus_message_new_method_call(SYNCE_BUS_NAME, SYNCE_PATH,
- SYNCE_SERVER_INTERFACE, "Connect");
- if (!msg)
- return -EPERM;
-
- dbus_message_iter_init_append(msg, &iter);
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
- DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
- DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
-
- append_dict_entry(&dict, "id", DBUS_TYPE_STRING, context->id);
-
- snprintf(transport, sizeof(transport), "%s.obexd", OBEXD_SERVICE);
- append_dict_entry(&dict, "transport", DBUS_TYPE_STRING, transport);
-
- snprintf(transport_description, sizeof(transport_description),
- "version %s", VERSION);
- append_dict_entry(&dict, "transport_description", DBUS_TYPE_STRING,
- transport_description);
-
- dbus_message_iter_close_container(&iter, &dict);
-
- authenticate = FALSE;
- session = "";
- dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &authenticate,
- DBUS_TYPE_STRING, &session, DBUS_TYPE_INVALID);
-
- if (!g_dbus_send_message_with_reply(conn, msg, &call, -1)) {
- error("D-Bus call to %s failed.", SYNCE_SERVER_INTERFACE);
- dbus_message_unref(msg);
- return -EPERM;
- }
-
- dbus_pending_call_set_notify(call, connect_cb, context, NULL);
-
- dbus_pending_call_unref(call);
- dbus_message_unref(msg);
-
- return -EAGAIN;
-}
-
-static ssize_t synce_write(void *object, const void *buf, size_t count)
-{
- struct synce_context *context = object;
- DBusMessage *msg;
- DBusMessageIter iter, array_iter;
- DBusPendingCall *call;
- const char *type = obex_get_type(context->os);
-
- if (context->lasterr == 0)
- return count;
-
- if (!context->conn_obj)
- return -EFAULT;
-
- msg = dbus_message_new_method_call(SYNCE_BUS_NAME, context->conn_obj,
- SYNCE_CONN_INTERFACE, "Process");
- if (!msg)
- return -EFAULT;
-
- dbus_message_iter_init_append(msg, &iter);
- dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
- DBUS_TYPE_BYTE_AS_STRING, &array_iter);
-
- dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
- &buf, count);
- dbus_message_iter_close_container(&iter, &array_iter);
-
- dbus_message_append_args(msg, DBUS_TYPE_STRING, &type,
- DBUS_TYPE_INVALID);
-
- if (!g_dbus_send_message_with_reply(context->dbus_conn, msg,
- &call, -1)) {
- error("D-Bus call to %s failed.", SYNCE_CONN_INTERFACE);
- dbus_message_unref(msg);
- return -EPERM;
- }
-
- dbus_pending_call_set_notify(call, process_cb, context, NULL);
-
- dbus_message_unref(msg);
- dbus_pending_call_unref(call);
-
- return -EAGAIN;
-}
-
-static const struct obex_mime_type_driver synce_driver = {
- .target = SYNCML_TARGET,
- .target_size = SYNCML_TARGET_SIZE,
- .open = synce_open,
- .close = synce_close,
- .read = synce_read,
- .write = synce_write,
-};
-
-static const struct obex_service_driver synce = {
- .name = "OBEX server for SyncML, using SyncEvolution",
- .service = OBEX_SYNCEVOLUTION,
- .channel = SYNCEVOLUTION_CHANNEL,
- .secure = TRUE,
- .record = SYNCEVOLUTION_RECORD,
- .target = SYNCML_TARGET,
- .target_size = SYNCML_TARGET_SIZE,
- .get = synce_get,
- .put = synce_put,
- .connect = synce_connect,
- .disconnect = synce_disconnect,
-};
-
-static int synce_init(void)
-{
- int err;
-
- err = obex_mime_type_driver_register(&synce_driver);
- if (err < 0)
- return err;
-
- return obex_service_driver_register(&synce);
-}
-
-static void synce_exit(void)
-{
- obex_service_driver_unregister(&synce);
- obex_mime_type_driver_unregister(&synce_driver);
-}
-
-OBEX_PLUGIN_DEFINE(syncevolution, synce_init, synce_exit)

--
2.43.0


Subject: [PATCH BlueZ 7/9] obex: remove unused mas/messages-tracker impl

From: Emil Velikov <[email protected]>

Currently we have a "dummy" and a "tracker" implementation. The latter
was seemingly never wired into the build... Unless the git history was
rewritten and details were lost.

Remove the file - it's not shipped in the tarball, so even if anyone
want to use it they cannot.
---
obexd/plugins/messages-tracker.c | 332 ---------------------------------------
1 file changed, 332 deletions(-)

diff --git a/obexd/plugins/messages-tracker.c b/obexd/plugins/messages-tracker.c
deleted file mode 100644
index 4ce9f221d..000000000
--- a/obexd/plugins/messages-tracker.c
+++ /dev/null
@@ -1,332 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- *
- * OBEX Server
- *
- * Copyright (C) 2010-2011 Nokia Corporation
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <errno.h>
-#include <glib.h>
-#include <string.h>
-
-#include "messages.h"
-
-struct message_folder {
- char *name;
- GSList *subfolders;
- char *query;
-};
-
-struct session {
- char *cwd;
- struct message_folder *folder;
- char *name;
- uint16_t max;
- uint16_t offset;
- void *user_data;
- void (*folder_list_cb)(void *session, int err, uint16_t size,
- const char *name, void *user_data);
-};
-
-static struct message_folder *folder_tree = NULL;
-
-static struct message_folder *get_folder(const char *folder)
-{
- GSList *folders = folder_tree->subfolders;
- struct message_folder *last = NULL;
- char **path;
- int i;
-
- if (g_strcmp0(folder, "/") == 0)
- return folder_tree;
-
- path = g_strsplit(folder, "/", 0);
-
- for (i = 1; path[i] != NULL; i++) {
- gboolean match_found = FALSE;
- GSList *l;
-
- for (l = folders; l != NULL; l = g_slist_next(l)) {
- struct message_folder *folder = l->data;
-
- if (g_strcmp0(folder->name, path[i]) == 0) {
- match_found = TRUE;
- last = l->data;
- folders = folder->subfolders;
- break;
- }
- }
-
- if (!match_found) {
- g_strfreev(path);
- return NULL;
- }
- }
-
- g_strfreev(path);
-
- return last;
-}
-
-static struct message_folder *create_folder(const char *name, const char *query)
-{
- struct message_folder *folder = g_new0(struct message_folder, 1);
-
- folder->name = g_strdup(name);
- folder->query = g_strdup(query);
-
- return folder;
-}
-
-static void destroy_folder_tree(void *root)
-{
- struct message_folder *folder = root;
- GSList *tmp, *next;
-
- if (folder == NULL)
- return;
-
- g_free(folder->name);
- g_free(folder->query);
-
- tmp = folder->subfolders;
- while (tmp != NULL) {
- next = g_slist_next(tmp);
- destroy_folder_tree(tmp->data);
- tmp = next;
- }
-
- g_slist_free(folder->subfolders);
- g_free(folder);
-}
-
-static void create_folder_tree(void)
-{
- struct message_folder *parent, *child;
-
- folder_tree = create_folder("/", "FILTER (!BOUND(?msg))");
-
- parent = create_folder("telecom", "FILTER (!BOUND(?msg))");
- folder_tree->subfolders = g_slist_append(folder_tree->subfolders,
- parent);
-
- child = create_folder("msg", "FILTER (!BOUND(?msg))");
- parent->subfolders = g_slist_append(parent->subfolders, child);
-
- parent = child;
-
- child = create_folder("inbox", "?msg nmo:isSent \"false\" ; "
- "nmo:isDeleted \"false\" ; "
- "nmo:isDraft \"false\". ");
- parent->subfolders = g_slist_append(parent->subfolders, child);
-
- child = create_folder("sent", "?msg nmo:isDeleted \"false\" ; "
- "nmo:isSent \"true\" . ");
- parent->subfolders = g_slist_append(parent->subfolders, child);
-
- child = create_folder("deleted", "?msg nmo:isDeleted \"true\" . ");
- parent->subfolders = g_slist_append(parent->subfolders, child);
-}
-
-int messages_init(void)
-{
- create_folder_tree();
-
- return 0;
-}
-
-void messages_exit(void)
-{
- destroy_folder_tree(folder_tree);
-}
-
-int messages_connect(void **s)
-{
- struct session *session = g_new0(struct session, 1);
-
- session->cwd = g_strdup("/");
- session->folder = folder_tree;
-
- *s = session;
-
- return 0;
-}
-
-void messages_disconnect(void *s)
-{
- struct session *session = s;
-
- g_free(session->cwd);
- g_free(session);
-}
-
-int messages_set_notification_registration(void *session,
- void (*send_event)(void *session,
- const struct messages_event *event, void *user_data),
- void *user_data)
-{
- return -ENOSYS;
-}
-
-int messages_set_folder(void *s, const char *name, gboolean cdup)
-{
- struct session *session = s;
- char *newrel = NULL;
- char *newabs;
- char *tmp;
-
- if (name && (strchr(name, '/') || strcmp(name, "..") == 0))
- return -EBADR;
-
- if (cdup) {
- if (session->cwd[0] == 0)
- return -ENOENT;
-
- newrel = g_path_get_dirname(session->cwd);
-
- /* We use empty string for indication of the root directory */
- if (newrel[0] == '.' && newrel[1] == 0)
- newrel[0] = 0;
- }
-
- tmp = newrel;
- if (!cdup && (!name || name[0] == 0))
- newrel = g_strdup("");
- else
- newrel = g_build_filename(newrel ? newrel : session->cwd, name,
- NULL);
- g_free(tmp);
-
- if (newrel[0] != '/')
- newabs = g_build_filename("/", newrel, NULL);
- else
- newabs = g_strdup(newrel);
-
- session->folder = get_folder(newabs);
- if (session->folder == NULL) {
- g_free(newrel);
- g_free(newabs);
-
- return -ENOENT;
- }
-
- g_free(newrel);
- g_free(session->cwd);
- session->cwd = newabs;
-
- return 0;
-}
-
-static gboolean async_get_folder_listing(void *s)
-{
- struct session *session = s;
- gboolean count = FALSE;
- int folder_count = 0;
- char *path = NULL;
- struct message_folder *folder;
- GSList *dir;
-
- if (session->name && strchr(session->name, '/') != NULL)
- goto done;
-
- path = g_build_filename(session->cwd, session->name, NULL);
-
- if (path == NULL || strlen(path) == 0)
- goto done;
-
- folder = get_folder(path);
-
- if (folder == NULL)
- goto done;
-
- if (session->max == 0) {
- session->max = 0xffff;
- session->offset = 0;
- count = TRUE;
- }
-
- for (dir = folder->subfolders; dir &&
- (folder_count - session->offset) < session->max;
- folder_count++, dir = g_slist_next(dir)) {
- struct message_folder *dir_data = dir->data;
-
- if (count == FALSE && session->offset <= folder_count)
- session->folder_list_cb(session, -EAGAIN, 0,
- dir_data->name, session->user_data);
- }
-
- done:
- session->folder_list_cb(session, 0, folder_count, NULL,
- session->user_data);
-
- g_free(path);
- g_free(session->name);
-
- return FALSE;
-}
-
-int messages_get_folder_listing(void *s, const char *name,
- uint16_t max, uint16_t offset,
- messages_folder_listing_cb callback,
- void *user_data)
-{
- struct session *session = s;
- session->name = g_strdup(name);
- session->max = max;
- session->offset = offset;
- session->folder_list_cb = callback;
- session->user_data = user_data;
-
- g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, async_get_folder_listing,
- session, NULL);
-
- return 0;
-}
-
-int messages_get_messages_listing(void *session, const char *name,
- uint16_t max, uint16_t offset,
- uint8_t subject_len,
- const struct messages_filter *filter,
- messages_get_messages_listing_cb callback,
- void *user_data)
-{
- return -ENOSYS;
-}
-
-int messages_get_message(void *session, const char *handle,
- unsigned long flags,
- messages_get_message_cb callback,
- void *user_data)
-{
- return -ENOSYS;
-}
-
-int messages_update_inbox(void *session, messages_status_cb callback,
- void *user_data)
-{
- return -ENOSYS;
-}
-
-int messages_set_read(void *session, const char *handle, uint8_t value,
- messages_status_cb callback, void *user_data)
-{
- return -ENOSYS;
-}
-
-int messages_set_delete(void *session, const char *handle, uint8_t value,
- messages_status_cb callback,
- void *user_data)
-{
- return -ENOSYS;
-}
-
-void messages_abort(void *session)
-{
-}

--
2.43.0


Subject: [PATCH BlueZ 8/9] obex: remove phonebook tracker backend

From: Emil Velikov <[email protected]>

Similar to the previous commits - the file was seemingly never build,
according to git log. Unlike the other cases, here the user can provide
the backend name via configure.ac toggle.

Although the case of tracker was never properly handled - no pkg-config
or probe based checks for includes, link library, etc.

Remove the file and enforce the two backend options - dummy and ebook.
---
Makefile.obexd | 3 +-
configure.ac | 6 +-
obexd/plugins/phonebook-tracker.c | 1704 -------------------------------------
3 files changed, 4 insertions(+), 1709 deletions(-)

diff --git a/Makefile.obexd b/Makefile.obexd
index 5d1a4ff65..d2aa06de3 100644
--- a/Makefile.obexd
+++ b/Makefile.obexd
@@ -42,8 +42,7 @@ obexd_builtin_sources += obexd/plugins/pbap.c \
obexd/plugins/vcard.h obexd/plugins/vcard.c \
obexd/plugins/phonebook.h \
obexd/plugins/phonebook-@[email protected]
-EXTRA_DIST += obexd/plugins/phonebook-dummy.c obexd/plugins/phonebook-ebook.c \
- obexd/plugins/phonebook-tracker.c
+EXTRA_DIST += obexd/plugins/phonebook-dummy.c obexd/plugins/phonebook-ebook.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 cab5da581..e6daf00ac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -433,11 +433,11 @@ AC_ARG_WITH([phonebook], AS_HELP_STRING([--with-phonebook=PLUGIN],
[plugin_phonebook=${withval}])
if (test -z "${plugin_phonebook}"); then
plugin_phonebook=dummy
-fi
-
-if (test "${plugin_phonebook}" = "ebook"); then
+else if (test "${plugin_phonebook}" = "ebook"); then
PKG_CHECK_MODULES(LIBEBOOK, libebook-1.2 >= 3.3)
PKG_CHECK_MODULES(LIBEDATESERVER, libedataserver-1.2 >= 3.3)
+else
+ AC_MSG_ERROR([Unsupported phonebook backend ${plugin_phonebook}])
fi
AC_SUBST(PLUGIN_PHONEBOOK, [${plugin_phonebook}])

diff --git a/obexd/plugins/phonebook-tracker.c b/obexd/plugins/phonebook-tracker.c
deleted file mode 100644
index 71a91c1ea..000000000
--- a/obexd/plugins/phonebook-tracker.c
+++ /dev/null
@@ -1,1704 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Phonebook access through D-Bus vCard and call history service
- *
- * Copyright (C) 2010 Nokia Corporation
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-#include <stdio.h>
-#include <errno.h>
-#include <glib.h>
-#include <dbus/dbus.h>
-#include <libtracker-sparql/tracker-sparql.h>
-
-#include "obexd/src/log.h"
-#include "obexd/src/obex.h"
-#include "obexd/src/service.h"
-#include "obexd/src/mimetype.h"
-#include "phonebook.h"
-#include "vcard.h"
-
-#define TRACKER_SERVICE "org.freedesktop.Tracker1"
-#define TRACKER_RESOURCES_PATH "/org/freedesktop/Tracker1/Resources"
-#define TRACKER_RESOURCES_INTERFACE "org.freedesktop.Tracker1.Resources"
-
-#define TRACKER_DEFAULT_CONTACT_ME "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#default-contact-me"
-#define AFFILATION_HOME "Home"
-#define AFFILATION_WORK "Work"
-#define ADDR_FIELD_AMOUNT 7
-#define PULL_QUERY_COL_AMOUNT 23
-#define COUNT_QUERY_COL_AMOUNT 1
-
-#define COL_PHONE_AFF 0 /* work/home phone numbers */
-#define COL_FULL_NAME 1
-#define COL_FAMILY_NAME 2
-#define COL_GIVEN_NAME 3
-#define COL_ADDITIONAL_NAME 4
-#define COL_NAME_PREFIX 5
-#define COL_NAME_SUFFIX 6
-#define COL_ADDR_AFF 7 /* addresses from affilation */
-#define COL_BIRTH_DATE 8
-#define COL_NICKNAME 9
-#define COL_URL 10
-#define COL_PHOTO 11
-#define COL_ORG_ROLE 12
-#define COL_UID 13
-#define COL_TITLE 14
-#define COL_AFF_TYPE 15
-#define COL_ORG_NAME 16
-#define COL_ORG_DEPARTMENT 17
-#define COL_EMAIL_AFF 18 /* email's from affilation (work/home) */
-#define COL_DATE 19
-#define COL_SENT 20
-#define COL_ANSWERED 21
-#define CONTACTS_ID_COL 22
-#define CONTACT_ID_PREFIX "urn:uuid:"
-#define CALL_ID_PREFIX "message:"
-
-#define FAX_NUM_TYPE "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#FaxNumber"
-#define MOBILE_NUM_TYPE "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#CellPhoneNumber"
-
-#define MAIN_DELIM "\30" /* Main delimiter between phones, addresses, emails*/
-#define SUB_DELIM "\31" /* Delimiter used in telephone number strings*/
-#define ADDR_DELIM "\37" /* Delimiter used for address data fields */
-#define MAX_FIELDS 100 /* Max amount of fields to be concatenated at once*/
-#define VCARDS_PART_COUNT 50 /* amount of vcards sent at once to PBAP core */
-#define QUERY_OFFSET_FORMAT "%s OFFSET %d"
-
-#define CONTACTS_QUERY_ALL \
-"SELECT " \
-"(SELECT GROUP_CONCAT(fn:concat(rdf:type(?aff_number)," \
-"\"\31\", nco:phoneNumber(?aff_number)), \"\30\")" \
-"WHERE {" \
-" ?_role nco:hasPhoneNumber ?aff_number" \
-"}) " \
-"nco:fullname(?_contact) " \
-"nco:nameFamily(?_contact) " \
-"nco:nameGiven(?_contact) " \
-"nco:nameAdditional(?_contact) " \
-"nco:nameHonorificPrefix(?_contact) " \
-"nco:nameHonorificSuffix(?_contact) " \
-"(SELECT GROUP_CONCAT(fn:concat(" \
-"tracker:coalesce(nco:pobox(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:extendedAddress(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:streetAddress(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:locality(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:region(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:postalcode(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:country(?aff_addr), \"\"), " \
-"\"\31\", rdfs:label(?_role) ), " \
-"\"\30\") " \
-"WHERE {" \
-"?_role nco:hasPostalAddress ?aff_addr" \
-"}) " \
-"nco:birthDate(?_contact) " \
-"(SELECT " \
-" ?nick " \
-" WHERE { " \
-" { " \
-" ?_contact nco:nickname ?nick " \
-" } UNION { " \
-" ?_contact nco:hasAffiliation ?role . " \
-" ?role nco:hasIMAddress ?im . " \
-" ?im nco:imNickname ?nick " \
-" } " \
-" } " \
-") " \
-"(SELECT GROUP_CONCAT(fn:concat( " \
- "?url_val, \"\31\", tracker:coalesce(rdfs:label(?_role), \"\") "\
- "), \"\30\") " \
- "WHERE {" \
- "?_role nco:url ?url_val . " \
-"})" \
-"nie:url(nco:photo(?_contact)) " \
-"nco:role(?_role) " \
-"nco:contactUID(?_contact) " \
-"nco:title(?_role) " \
-"rdfs:label(?_role) " \
-"nco:fullname(nco:org(?_role))" \
-"nco:department(?_role) " \
-"(SELECT GROUP_CONCAT(fn:concat(?emailaddress,\"\31\"," \
- "tracker:coalesce(rdfs:label(?_role), \"\"))," \
- "\"\30\") " \
- "WHERE { " \
- "?_role nco:hasEmailAddress " \
- " [ nco:emailAddress ?emailaddress ] " \
- "}) " \
-"\"NOTACALL\" \"false\" \"false\" " \
-"?_contact " \
-"WHERE {" \
-" ?_contact a nco:PersonContact ." \
-" OPTIONAL {?_contact nco:hasAffiliation ?_role .}" \
-"}" \
-"ORDER BY tracker:id(?_contact)"
-
-#define CONTACTS_QUERY_ALL_LIST \
- "SELECT ?c nco:nameFamily(?c) " \
- "nco:nameGiven(?c) nco:nameAdditional(?c) " \
- "nco:nameHonorificPrefix(?c) nco:nameHonorificSuffix(?c) " \
- "(SELECT " \
- "?nick " \
- "WHERE { " \
- "{ " \
- "?c nco:nickname ?nick " \
- "} UNION { " \
- "?c nco:hasAffiliation ?role . " \
- "?role nco:hasIMAddress ?im . " \
- "?im nco:imNickname ?nick " \
- "} " \
- "} " \
- ") " \
- "nco:phoneNumber(?h) " \
- "WHERE { " \
- "?c a nco:PersonContact . " \
- "OPTIONAL { ?c nco:hasPhoneNumber ?h . } " \
- "OPTIONAL { " \
- "?c nco:hasAffiliation ?a . " \
- "?a nco:hasPhoneNumber ?h . " \
- "} " \
- "} GROUP BY ?c"
-
-#define CALLS_CONSTRAINTS(CONSTRAINT) \
-" WHERE { " \
- "?_call a nmo:Call . " \
- "?_unb_contact a nco:Contact . " \
- "?_unb_contact nco:hasPhoneNumber ?_cpn . " \
-CONSTRAINT \
- "OPTIONAL { " \
- "{ SELECT ?_contact ?_no ?_role ?_number " \
- "count(?_contact) as ?cnt " \
- "WHERE { " \
- "?_contact a nco:PersonContact . " \
- "{ " \
- "?_contact nco:hasAffiliation ?_role . "\
- "?_role nco:hasPhoneNumber ?_number . " \
- "} UNION { " \
- "?_contact nco:hasPhoneNumber ?_number" \
- "} " \
- "?_number maemo:localPhoneNumber ?_no . " \
- "} GROUP BY ?_no } " \
- "FILTER(?cnt = 1) " \
- "?_cpn maemo:localPhoneNumber ?_no . " \
- "} " \
-"} "
-
-#define CALLS_LIST(CONSTRAINT) \
-"SELECT ?_call nco:nameFamily(?_contact) " \
- "nco:nameGiven(?_contact) nco:nameAdditional(?_contact) " \
- "nco:nameHonorificPrefix(?_contact) " \
- "nco:nameHonorificSuffix(?_contact) " \
- "(SELECT " \
- "?nick " \
- "WHERE { " \
- "{ " \
- "?_contact nco:nickname ?nick " \
- "} UNION { " \
- "?_contact nco:hasAffiliation ?role . " \
- "?role nco:hasIMAddress ?im . " \
- "?im nco:imNickname ?nick " \
- "} " \
- "} " \
- ") " \
- "nco:phoneNumber(?_cpn) " \
-CALLS_CONSTRAINTS(CONSTRAINT) \
-"ORDER BY DESC(nmo:sentDate(?_call)) "
-
-#define CALLS_QUERY(CONSTRAINT) \
-"SELECT " \
-"(SELECT fn:concat(rdf:type(?role_number)," \
- "\"\31\", nco:phoneNumber(?role_number))" \
- "WHERE {" \
- "{" \
- " ?_role nco:hasPhoneNumber ?role_number " \
- " FILTER (?role_number = ?_number)" \
- "} UNION { " \
- "?_unb_contact nco:hasPhoneNumber ?role_number . " \
- " FILTER (!bound(?_role)) " \
- "}" \
-"} GROUP BY nco:phoneNumber(?role_number) ) " \
- "nco:fullname(?_contact) " \
- "nco:nameFamily(?_contact) " \
- "nco:nameGiven(?_contact) " \
- "nco:nameAdditional(?_contact) " \
- "nco:nameHonorificPrefix(?_contact) " \
- "nco:nameHonorificSuffix(?_contact) " \
-"(SELECT GROUP_CONCAT(fn:concat(" \
- "tracker:coalesce(nco:pobox(?aff_addr), \"\"), \"\37\"," \
- "tracker:coalesce(nco:extendedAddress(?aff_addr), \"\"), \"\37\","\
- "tracker:coalesce(nco:streetAddress(?aff_addr), \"\"), \"\37\","\
- "tracker:coalesce(nco:locality(?aff_addr), \"\"), \"\37\"," \
- "tracker:coalesce(nco:region(?aff_addr), \"\"), \"\37\"," \
- "tracker:coalesce(nco:postalcode(?aff_addr), \"\"), \"\37\"," \
- "tracker:coalesce(nco:country(?aff_addr), \"\"), " \
- "\"\31\", rdfs:label(?c_role) ), " \
- "\"\30\") " \
- "WHERE {" \
- "?_contact nco:hasAffiliation ?c_role . " \
- "?c_role nco:hasPostalAddress ?aff_addr" \
- "}) " \
- "nco:birthDate(?_contact) " \
-"(SELECT " \
- "?nick " \
- "WHERE { " \
- " { " \
- " ?_contact nco:nickname ?nick " \
- " } UNION { " \
- " ?_contact nco:hasAffiliation ?role . " \
- " ?role nco:hasIMAddress ?im . " \
- " ?im nco:imNickname ?nick " \
- " } " \
- " } " \
- ") " \
-"(SELECT GROUP_CONCAT(fn:concat(?url_value, \"\31\", " \
- "tracker:coalesce(rdfs:label(?c_role), \"\")), \"\30\") " \
- "WHERE {" \
- "?_contact nco:hasAffiliation ?c_role . " \
- "?c_role nco:url ?url_value . " \
-"})" \
- "nie:url(nco:photo(?_contact)) " \
- "nco:role(?_role) " \
- "nco:contactUID(?_contact) " \
- "nco:title(?_role) " \
- "rdfs:label(?_role) " \
- "nco:fullname(nco:org(?_role)) " \
- "nco:department(?_role) " \
-"(SELECT GROUP_CONCAT(fn:concat(?emailaddress,\"\31\"," \
- "tracker:coalesce(rdfs:label(?c_role), \"\"))," \
- "\"\30\") " \
- "WHERE { " \
- "?_contact nco:hasAffiliation ?c_role . " \
- "?c_role nco:hasEmailAddress " \
- " [ nco:emailAddress ?emailaddress ] " \
- "}) " \
- "nmo:receivedDate(?_call) " \
- "nmo:isSent(?_call) " \
- "nmo:isAnswered(?_call) " \
- "?_call " \
-CALLS_CONSTRAINTS(CONSTRAINT) \
-"ORDER BY DESC(nmo:sentDate(?_call)) "
-
-#define MISSED_CONSTRAINT \
-"?_call nmo:from ?_unb_contact . " \
-"?_call nmo:isSent false . " \
-"?_call nmo:isAnswered false . "
-
-#define INCOMING_CONSTRAINT \
-"?_call nmo:from ?_unb_contact . " \
-"?_call nmo:isSent false . " \
-"?_call nmo:isAnswered true . "
-
-#define OUTGOING_CONSTRAINT \
-"?_call nmo:to ?_unb_contact . " \
-"?_call nmo:isSent true . "
-
-#define COMBINED_CONSTRAINT \
-"{ " \
-" ?_call nmo:from ?_unb_contact . " \
-" ?_call nmo:isSent false " \
-"} UNION { " \
-" ?_call nmo:to ?_unb_contact . " \
-" ?_call nmo:isSent true " \
-"} "
-
-#define CALL_URI_CONSTRAINT \
-COMBINED_CONSTRAINT \
-"FILTER (?_call = <%s>) "
-
-#define MISSED_CALLS_QUERY CALLS_QUERY(MISSED_CONSTRAINT)
-#define MISSED_CALLS_LIST CALLS_LIST(MISSED_CONSTRAINT)
-#define INCOMING_CALLS_QUERY CALLS_QUERY(INCOMING_CONSTRAINT)
-#define INCOMING_CALLS_LIST CALLS_LIST(INCOMING_CONSTRAINT)
-#define OUTGOING_CALLS_QUERY CALLS_QUERY(OUTGOING_CONSTRAINT)
-#define OUTGOING_CALLS_LIST CALLS_LIST(OUTGOING_CONSTRAINT)
-#define COMBINED_CALLS_QUERY CALLS_QUERY(COMBINED_CONSTRAINT)
-#define COMBINED_CALLS_LIST CALLS_LIST(COMBINED_CONSTRAINT)
-#define CONTACT_FROM_CALL_QUERY CALLS_QUERY(CALL_URI_CONSTRAINT)
-
-#define CONTACTS_QUERY_FROM_URI \
-"SELECT " \
-"(SELECT GROUP_CONCAT(fn:concat(rdf:type(?aff_number)," \
-"\"\31\", nco:phoneNumber(?aff_number)), \"\30\")" \
-"WHERE {" \
-" ?_role nco:hasPhoneNumber ?aff_number" \
-"}) " \
-"nco:fullname(<%s>) " \
-"nco:nameFamily(<%s>) " \
-"nco:nameGiven(<%s>) " \
-"nco:nameAdditional(<%s>) " \
-"nco:nameHonorificPrefix(<%s>) " \
-"nco:nameHonorificSuffix(<%s>) " \
-"(SELECT GROUP_CONCAT(fn:concat(" \
-"tracker:coalesce(nco:pobox(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:extendedAddress(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:streetAddress(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:locality(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:region(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:postalcode(?aff_addr), \"\"), \"\37\"," \
-"tracker:coalesce(nco:country(?aff_addr), \"\"), " \
-"\"\31\", rdfs:label(?_role) ), " \
-"\"\30\") " \
-"WHERE {" \
-"?_role nco:hasPostalAddress ?aff_addr" \
-"}) " \
-"nco:birthDate(<%s>) " \
-"(SELECT " \
-" ?nick " \
-" WHERE { " \
-" { " \
-" ?_contact nco:nickname ?nick " \
-" } UNION { " \
-" ?_contact nco:hasAffiliation ?role . " \
-" ?role nco:hasIMAddress ?im . " \
-" ?im nco:imNickname ?nick " \
-" } " \
-" FILTER (?_contact = <%s>)" \
-" } " \
-") " \
-"(SELECT GROUP_CONCAT(fn:concat( " \
- "?url_val, \"\31\", tracker:coalesce(rdfs:label(?_role), \"\") "\
- "), \"\30\") " \
- "WHERE {" \
- "?_role nco:url ?url_val . " \
-"})" \
-"nie:url(nco:photo(<%s>)) " \
-"nco:role(?_role) " \
-"nco:contactUID(<%s>) " \
-"nco:title(?_role) " \
-"rdfs:label(?_role) " \
-"nco:fullname(nco:org(?_role))" \
-"nco:department(?_role) " \
-"(SELECT GROUP_CONCAT(fn:concat(?emailaddress,\"\31\"," \
- "tracker:coalesce(rdfs:label(?_role), \"\"))," \
- "\"\30\") " \
- "WHERE { " \
- "?_role nco:hasEmailAddress " \
- " [ nco:emailAddress ?emailaddress ] " \
- "}) " \
-"\"NOTACALL\" \"false\" \"false\" " \
-"<%s> " \
-"WHERE {" \
-" <%s> a nco:PersonContact ." \
-" OPTIONAL {<%s> nco:hasAffiliation ?_role .}" \
-"}"
-
-#define CONTACTS_OTHER_QUERY_FROM_URI \
- "SELECT fn:concat(\"TYPE_OTHER\", \"\31\", nco:phoneNumber(?t))"\
- "\"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" " \
- "\"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" " \
- " \"NOTACALL\" \"false\" \"false\" <%s> " \
- "WHERE { " \
- "<%s> a nco:Contact . " \
- "OPTIONAL { <%s> nco:hasPhoneNumber ?t . } " \
- "} "
-
-#define CONTACTS_COUNT_QUERY \
- "SELECT COUNT(?c) " \
- "WHERE {" \
- "?c a nco:PersonContact ." \
- "}"
-
-#define MISSED_CALLS_COUNT_QUERY \
- "SELECT COUNT(?call) WHERE {" \
- "?c a nco:Contact ;" \
- "nco:hasPhoneNumber ?h ." \
- "?call a nmo:Call ;" \
- "nmo:isSent false ;" \
- "nmo:from ?c ;" \
- "nmo:isAnswered false ." \
- "}"
-
-#define INCOMING_CALLS_COUNT_QUERY \
- "SELECT COUNT(?call) WHERE {" \
- "?c a nco:Contact ;" \
- "nco:hasPhoneNumber ?h ." \
- "?call a nmo:Call ;" \
- "nmo:isSent false ;" \
- "nmo:from ?c ;" \
- "nmo:isAnswered true ." \
- "}"
-
-#define OUTGOING_CALLS_COUNT_QUERY \
- "SELECT COUNT(?call) WHERE {" \
- "?c a nco:Contact ;" \
- "nco:hasPhoneNumber ?h ." \
- "?call a nmo:Call ;" \
- "nmo:isSent true ;" \
- "nmo:to ?c ." \
- "}"
-
-#define COMBINED_CALLS_COUNT_QUERY \
- "SELECT COUNT(?call) WHERE {" \
- "{" \
- "?c a nco:Contact ;" \
- "nco:hasPhoneNumber ?h ." \
- "?call a nmo:Call ;" \
- "nmo:isSent true ;" \
- "nmo:to ?c ." \
- "}UNION {" \
- "?c a nco:Contact ;" \
- "nco:hasPhoneNumber ?h ." \
- "?call a nmo:Call ;" \
- "nmo:from ?c ." \
- "}" \
- "}"
-
-#define NEW_MISSED_CALLS_COUNT_QUERY \
- "SELECT COUNT(?call) WHERE {" \
- "?c a nco:Contact ;" \
- "nco:hasPhoneNumber ?h ." \
- "?call a nmo:Call ;" \
- "nmo:isSent false ;" \
- "nmo:from ?c ;" \
- "nmo:isAnswered false ;" \
- "nmo:isRead false ." \
- "}"
-
-typedef int (*reply_list_foreach_t) (const char **reply, int num_fields,
- void *user_data);
-
-typedef void (*add_field_t) (struct phonebook_contact *contact,
- const char *value, int type);
-
-struct pending_reply {
- reply_list_foreach_t callback;
- void *user_data;
- int num_fields;
-};
-
-struct contact_data {
- char *id;
- struct phonebook_contact *contact;
-};
-
-struct phonebook_data {
- phonebook_cb cb;
- void *user_data;
- int index;
- gboolean vcardentry;
- const struct apparam_field *params;
- GSList *contacts;
- phonebook_cache_ready_cb ready_cb;
- phonebook_entry_cb entry_cb;
- int newmissedcalls;
- GCancellable *query_canc;
- char *req_name;
- int vcard_part_count;
- int tracker_index;
-};
-
-struct phonebook_index {
- GArray *phonebook;
- int index;
-};
-
-static TrackerSparqlConnection *connection = NULL;
-
-static const char *name2query(const char *name)
-{
- if (g_str_equal(name, PB_CONTACTS))
- return CONTACTS_QUERY_ALL;
- else if (g_str_equal(name, PB_CALLS_INCOMING))
- return INCOMING_CALLS_QUERY;
- else if (g_str_equal(name, PB_CALLS_OUTGOING))
- return OUTGOING_CALLS_QUERY;
- else if (g_str_equal(name, PB_CALLS_MISSED))
- return MISSED_CALLS_QUERY;
- else if (g_str_equal(name, PB_CALLS_COMBINED))
- return COMBINED_CALLS_QUERY;
-
- return NULL;
-}
-
-static const char *name2count_query(const char *name)
-{
- if (g_str_equal(name, PB_CONTACTS))
- return CONTACTS_COUNT_QUERY;
- else if (g_str_equal(name, PB_CALLS_INCOMING))
- return INCOMING_CALLS_COUNT_QUERY;
- else if (g_str_equal(name, PB_CALLS_OUTGOING))
- return OUTGOING_CALLS_COUNT_QUERY;
- else if (g_str_equal(name, PB_CALLS_MISSED))
- return MISSED_CALLS_COUNT_QUERY;
- else if (g_str_equal(name, PB_CALLS_COMBINED))
- return COMBINED_CALLS_COUNT_QUERY;
-
- return NULL;
-}
-
-static gboolean folder_is_valid(const char *folder)
-{
- if (folder == NULL)
- return FALSE;
-
- if (g_str_equal(folder, "/"))
- return TRUE;
- else if (g_str_equal(folder, PB_TELECOM_FOLDER))
- return TRUE;
- else if (g_str_equal(folder, PB_CONTACTS_FOLDER))
- return TRUE;
- else if (g_str_equal(folder, PB_CALLS_INCOMING_FOLDER))
- return TRUE;
- else if (g_str_equal(folder, PB_CALLS_OUTGOING_FOLDER))
- return TRUE;
- else if (g_str_equal(folder, PB_CALLS_MISSED_FOLDER))
- return TRUE;
- else if (g_str_equal(folder, PB_CALLS_COMBINED_FOLDER))
- return TRUE;
-
- return FALSE;
-}
-
-static const char *folder2query(const char *folder)
-{
- if (g_str_equal(folder, PB_CONTACTS_FOLDER))
- return CONTACTS_QUERY_ALL_LIST;
- else if (g_str_equal(folder, PB_CALLS_INCOMING_FOLDER))
- return INCOMING_CALLS_LIST;
- else if (g_str_equal(folder, PB_CALLS_OUTGOING_FOLDER))
- return OUTGOING_CALLS_LIST;
- else if (g_str_equal(folder, PB_CALLS_MISSED_FOLDER))
- return MISSED_CALLS_LIST;
- else if (g_str_equal(folder, PB_CALLS_COMBINED_FOLDER))
- return COMBINED_CALLS_LIST;
-
- return NULL;
-}
-
-static const char **string_array_from_cursor(TrackerSparqlCursor *cursor,
- int array_len)
-{
- const char **result;
- int i;
-
- result = g_new0(const char *, array_len);
-
- for (i = 0; i < array_len; ++i) {
- TrackerSparqlValueType type;
-
- type = tracker_sparql_cursor_get_value_type(cursor, i);
-
- if (type == TRACKER_SPARQL_VALUE_TYPE_BLANK_NODE ||
- type == TRACKER_SPARQL_VALUE_TYPE_UNBOUND)
- /* For null/unbound type filling result part with ""*/
- result[i] = "";
- else
- /* Filling with string representation of content*/
- result[i] = tracker_sparql_cursor_get_string(cursor, i,
- NULL);
- }
-
- return result;
-}
-
-static void update_cancellable(struct phonebook_data *pdata,
- GCancellable *canc)
-{
- if (pdata->query_canc)
- g_object_unref(pdata->query_canc);
-
- pdata->query_canc = canc;
-}
-
-static void async_query_cursor_next_cb(GObject *source, GAsyncResult *result,
- gpointer user_data)
-{
- struct pending_reply *pending = user_data;
- TrackerSparqlCursor *cursor = TRACKER_SPARQL_CURSOR(source);
- GCancellable *cancellable;
- GError *error = NULL;
- gboolean success;
- const char **node;
- int err;
-
- success = tracker_sparql_cursor_next_finish(
- TRACKER_SPARQL_CURSOR(source),
- result, &error);
-
- if (!success) {
- if (error) {
- DBG("cursor_next error: %s", error->message);
- g_error_free(error);
- } else
- /* When tracker_sparql_cursor_next_finish ends with
- * failure and no error is set, that means end of
- * results returned by query */
- pending->callback(NULL, 0, pending->user_data);
-
- goto failed;
- }
-
- node = string_array_from_cursor(cursor, pending->num_fields);
- err = pending->callback(node, pending->num_fields, pending->user_data);
- g_free(node);
-
- /* Fetch next result only if processing current chunk ended with
- * success. Sometimes during processing data, we are able to determine
- * if there is no need to get more data from tracker - by example
- * stored amount of data parts is big enough for sending and we might
- * want to suspend processing or just some error occurred. */
- if (!err) {
- cancellable = g_cancellable_new();
- update_cancellable(pending->user_data, cancellable);
- tracker_sparql_cursor_next_async(cursor, cancellable,
- async_query_cursor_next_cb,
- pending);
- return;
- }
-
-failed:
- g_object_unref(cursor);
- g_free(pending);
-}
-
-static int query_tracker(const char *query, int num_fields,
- reply_list_foreach_t callback, void *user_data)
-{
- struct pending_reply *pending;
- GCancellable *cancellable;
- TrackerSparqlCursor *cursor;
- GError *error = NULL;
-
- DBG("");
-
- if (connection == NULL)
- connection = tracker_sparql_connection_get_direct(
- NULL, &error);
-
- if (!connection) {
- if (error) {
- DBG("direct-connection error: %s", error->message);
- g_error_free(error);
- }
-
- return -EINTR;
- }
-
- cancellable = g_cancellable_new();
- update_cancellable(user_data, cancellable);
- cursor = tracker_sparql_connection_query(connection, query,
- cancellable, &error);
-
- if (cursor == NULL) {
- if (error) {
- DBG("connection_query error: %s", error->message);
- g_error_free(error);
- }
-
- g_object_unref(cancellable);
-
- return -EINTR;
- }
-
- pending = g_new0(struct pending_reply, 1);
- pending->callback = callback;
- pending->user_data = user_data;
- pending->num_fields = num_fields;
-
- /* Now asynchronously going through each row of results - callback
- * async_query_cursor_next_cb will be called ALWAYS, even if async
- * request was canceled */
- tracker_sparql_cursor_next_async(cursor, cancellable,
- async_query_cursor_next_cb,
- pending);
-
- return 0;
-}
-
-static char *iso8601_utc_to_localtime(const char *datetime)
-{
- time_t time;
- struct tm tm, *local;
- char localdate[32];
- int nr;
-
- memset(&tm, 0, sizeof(tm));
-
- nr = sscanf(datetime, "%04u-%02u-%02uT%02u:%02u:%02u",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
- if (nr < 6) {
- /* Invalid time format */
- error("sscanf(): %s (%d)", strerror(errno), errno);
- return g_strdup("");
- }
-
- /* Time already in localtime */
- if (!g_str_has_suffix(datetime, "Z")) {
- strftime(localdate, sizeof(localdate), "%Y%m%dT%H%M%S", &tm);
- return g_strdup(localdate);
- }
-
- tm.tm_year -= 1900; /* Year since 1900 */
- tm.tm_mon--; /* Months since January, values 0-11 */
-
- time = mktime(&tm);
- time -= timezone;
-
- local = localtime(&time);
-
- strftime(localdate, sizeof(localdate), "%Y%m%dT%H%M%S", local);
-
- return g_strdup(localdate);
-}
-
-static void set_call_type(struct phonebook_contact *contact,
- const char *datetime, const char *is_sent,
- const char *is_answered)
-{
- gboolean sent, answered;
-
- if (g_strcmp0(datetime, "NOTACALL") == 0) {
- contact->calltype = CALL_TYPE_NOT_A_CALL;
- return;
- }
-
- sent = g_str_equal(is_sent, "true");
- answered = g_str_equal(is_answered, "true");
-
- if (sent == FALSE) {
- if (answered == FALSE)
- contact->calltype = CALL_TYPE_MISSED;
- else
- contact->calltype = CALL_TYPE_INCOMING;
- } else
- contact->calltype = CALL_TYPE_OUTGOING;
-
- /* Tracker gives time in the ISO 8601 format, UTC time */
- contact->datetime = iso8601_utc_to_localtime(datetime);
-}
-
-static gboolean contact_matches(struct contact_data *c_data, const char *id,
- const char *datetime)
-{
- char *localtime;
- int cmp_ret;
-
- if (g_strcmp0(c_data->id, id) != 0)
- return FALSE;
-
- /* id is equal and not call history entry => contact matches */
- if (c_data->contact->calltype == CALL_TYPE_NOT_A_CALL)
- return TRUE;
-
- /* for call history entries have to compare also timestamps of calls */
- localtime = iso8601_utc_to_localtime(datetime);
- cmp_ret = g_strcmp0(c_data->contact->datetime, localtime);
- g_free(localtime);
-
- return (cmp_ret == 0) ? TRUE : FALSE;
-}
-
-static struct phonebook_contact *find_contact(GSList *contacts, const char *id,
- const char *datetime)
-{
- GSList *l;
-
- for (l = contacts; l; l = l->next) {
- struct contact_data *c_data = l->data;
-
- if (contact_matches(c_data, id, datetime))
- return c_data->contact;
- }
-
- return NULL;
-}
-
-static struct phonebook_field *find_field(GSList *fields, const char *value,
- int type)
-{
- GSList *l;
-
- for (l = fields; l; l = l->next) {
- struct phonebook_field *field = l->data;
- /* Returning phonebook number if phone values and type values
- * are equal */
- if (g_strcmp0(field->text, value) == 0 && field->type == type)
- return field;
- }
-
- return NULL;
-}
-
-static void add_phone_number(struct phonebook_contact *contact,
- const char *phone, int type)
-{
- struct phonebook_field *number;
-
- if (phone == NULL || strlen(phone) == 0)
- return;
-
- /* Not adding number if there is already added with the same value */
- if (find_field(contact->numbers, phone, type))
- return;
-
- number = g_new0(struct phonebook_field, 1);
- number->text = g_strdup(phone);
- number->type = type;
-
- contact->numbers = g_slist_append(contact->numbers, number);
-}
-
-static void add_email(struct phonebook_contact *contact, const char *address,
- int type)
-{
- struct phonebook_field *email;
-
- if (address == NULL || strlen(address) == 0)
- return;
-
- /* Not adding email if there is already added with the same value */
- if (find_field(contact->emails, address, type))
- return;
-
- email = g_new0(struct phonebook_field, 1);
- email->text = g_strdup(address);
- email->type = type;
-
- contact->emails = g_slist_append(contact->emails, email);
-}
-
-static gboolean addr_matches(struct phonebook_addr *a, struct phonebook_addr *b)
-{
- GSList *la, *lb;
-
- if (a->type != b->type)
- return FALSE;
-
- for (la = a->fields, lb = b->fields; la && lb;
- la = la->next, lb = lb->next) {
- char *field_a = la->data;
- char *field_b = lb->data;
-
- if (g_strcmp0(field_a, field_b) != 0)
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* generates phonebook_addr struct from tracker address data string. */
-static struct phonebook_addr *gen_addr(const char *address, int type)
-{
- struct phonebook_addr *addr;
- GSList *fields = NULL;
- char **addr_parts;
- int i;
-
- /* This test handles cases when address points to empty string
- * (or address is NULL pointer) or string containing only six
- * separators. It indicates that none of address fields is present
- * and there is no sense to create dummy phonebook_addr struct */
- if (address == NULL || strlen(address) < ADDR_FIELD_AMOUNT)
- return NULL;
-
- addr_parts = g_strsplit(address, ADDR_DELIM, ADDR_FIELD_AMOUNT);
-
- for (i = 0; i < ADDR_FIELD_AMOUNT; ++i)
- fields = g_slist_append(fields, g_strdup(addr_parts[i]));
-
- g_strfreev(addr_parts);
-
- addr = g_new0(struct phonebook_addr, 1);
- addr->fields = fields;
- addr->type = type;
-
- return addr;
-}
-
-static void add_address(struct phonebook_contact *contact,
- const char *address, int type)
-{
- struct phonebook_addr *addr;
- GSList *l;
-
- addr = gen_addr(address, type);
- if (addr == NULL)
- return;
-
- /* Not adding address if there is already added with the same value.
- * These type of checks have to be done because sometimes tracker
- * returns results for contact data in more than 1 row - then the same
- * address may be returned more than once in query results */
- for (l = contact->addresses; l; l = l->next) {
- struct phonebook_addr *tmp = l->data;
-
- if (addr_matches(tmp, addr)) {
- phonebook_addr_free(addr);
- return;
- }
- }
-
- contact->addresses = g_slist_append(contact->addresses, addr);
-}
-
-static void add_url(struct phonebook_contact *contact, const char *url_val,
- int type)
-{
- struct phonebook_field *url;
-
- if (url_val == NULL || strlen(url_val) == 0)
- return;
-
- /* Not adding url if there is already added with the same value */
- if (find_field(contact->urls, url_val, type))
- return;
-
- url = g_new0(struct phonebook_field, 1);
-
- url->text = g_strdup(url_val);
- url->type = type;
-
- contact->urls = g_slist_append(contact->urls, url);
-}
-
-static GString *gen_vcards(GSList *contacts,
- const struct apparam_field *params)
-{
- GSList *l;
- GString *vcards;
-
- vcards = g_string_new(NULL);
-
- /* Generating VCARD string from contacts and freeing used contacts */
- for (l = contacts; l; l = l->next) {
- struct contact_data *c_data = l->data;
- phonebook_add_contact(vcards, c_data->contact,
- params->filter, params->format);
- }
-
- return vcards;
-}
-
-static int pull_contacts_size(const char **reply, int num_fields,
- void *user_data)
-{
- struct phonebook_data *data = user_data;
-
- if (num_fields < 0) {
- data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
- return -EINTR;
- }
-
- if (reply != NULL) {
- data->index = atoi(reply[0]);
- return 0;
- }
-
- data->cb(NULL, 0, data->index, data->newmissedcalls, TRUE,
- data->user_data);
-
- return 0;
- /*
- * phonebook_data is freed in phonebook_req_finalize. Useful in
- * cases when call is terminated.
- */
-}
-
-static void add_affiliation(char **field, const char *value)
-{
- if (strlen(*field) > 0 || value == NULL || strlen(value) == 0)
- return;
-
- g_free(*field);
-
- *field = g_strdup(value);
-}
-
-static void contact_init(struct phonebook_contact *contact,
- const char **reply)
-{
- if (reply[COL_FAMILY_NAME][0] == '\0' &&
- reply[COL_GIVEN_NAME][0] == '\0' &&
- reply[COL_ADDITIONAL_NAME][0] == '\0' &&
- reply[COL_NAME_PREFIX][0] == '\0' &&
- reply[COL_NAME_SUFFIX][0] == '\0') {
- if (reply[COL_FULL_NAME][0] != '\0')
- contact->family = g_strdup(reply[COL_FULL_NAME]);
- else
- contact->family = g_strdup(reply[COL_NICKNAME]);
- } else {
- contact->family = g_strdup(reply[COL_FAMILY_NAME]);
- contact->given = g_strdup(reply[COL_GIVEN_NAME]);
- contact->additional = g_strdup(reply[COL_ADDITIONAL_NAME]);
- contact->prefix = g_strdup(reply[COL_NAME_PREFIX]);
- contact->suffix = g_strdup(reply[COL_NAME_SUFFIX]);
- }
- contact->fullname = g_strdup(reply[COL_FULL_NAME]);
- contact->birthday = g_strdup(reply[COL_BIRTH_DATE]);
- contact->nickname = g_strdup(reply[COL_NICKNAME]);
- contact->photo = g_strdup(reply[COL_PHOTO]);
- contact->company = g_strdup(reply[COL_ORG_NAME]);
- contact->department = g_strdup(reply[COL_ORG_DEPARTMENT]);
- contact->role = g_strdup(reply[COL_ORG_ROLE]);
- contact->uid = g_strdup(reply[COL_UID]);
- contact->title = g_strdup(reply[COL_TITLE]);
-
- set_call_type(contact, reply[COL_DATE], reply[COL_SENT],
- reply[COL_ANSWERED]);
-}
-
-static enum phonebook_number_type get_phone_type(const char *affilation)
-{
- if (g_strcmp0(AFFILATION_HOME, affilation) == 0)
- return TEL_TYPE_HOME;
- else if (g_strcmp0(AFFILATION_WORK, affilation) == 0)
- return TEL_TYPE_WORK;
-
- return TEL_TYPE_OTHER;
-}
-
-static void add_aff_number(struct phonebook_contact *contact,
- const char *pnumber, const char *aff_type)
-{
- char **num_parts;
- char *type, *number;
-
- /* For phone taken directly from contacts data, phone number string
- * is represented as number type and number string - those strings are
- * separated by SUB_DELIM string */
- num_parts = g_strsplit(pnumber, SUB_DELIM, 2);
-
- if (!num_parts)
- return;
-
- if (num_parts[0])
- type = num_parts[0];
- else
- goto failed;
-
- if (num_parts[1])
- number = num_parts[1];
- else
- goto failed;
-
- if (g_strrstr(type, FAX_NUM_TYPE))
- add_phone_number(contact, number, TEL_TYPE_FAX);
- else if (g_strrstr(type, MOBILE_NUM_TYPE))
- add_phone_number(contact, number, TEL_TYPE_MOBILE);
- else
- /* if this is no fax/mobile phone, then adding phone number
- * type based on type of the affilation field */
- add_phone_number(contact, number, get_phone_type(aff_type));
-
-failed:
- g_strfreev(num_parts);
-}
-
-static void contact_add_numbers(struct phonebook_contact *contact,
- const char **reply)
-{
- char **aff_numbers;
- int i;
-
- /* Filling phone numbers from contact's affilation */
- aff_numbers = g_strsplit(reply[COL_PHONE_AFF], MAIN_DELIM, MAX_FIELDS);
-
- if (aff_numbers)
- for (i = 0; aff_numbers[i]; ++i)
- add_aff_number(contact, aff_numbers[i],
- reply[COL_AFF_TYPE]);
-
- g_strfreev(aff_numbers);
-}
-
-static enum phonebook_field_type get_field_type(const char *affilation)
-{
- if (g_strcmp0(AFFILATION_HOME, affilation) == 0)
- return FIELD_TYPE_HOME;
- else if (g_strcmp0(AFFILATION_WORK, affilation) == 0)
- return FIELD_TYPE_WORK;
-
- return FIELD_TYPE_OTHER;
-}
-
-static void add_aff_field(struct phonebook_contact *contact,
- const char *aff_email, add_field_t add_field_cb)
-{
- char **email_parts;
- char *type, *email;
-
- /* Emails from affilation data, are represented as real email
- * string and affilation type - those strings are separated by
- * SUB_DELIM string */
- email_parts = g_strsplit(aff_email, SUB_DELIM, 2);
-
- if (!email_parts)
- return;
-
- if (email_parts[0])
- email = email_parts[0];
- else
- goto failed;
-
- if (email_parts[1])
- type = email_parts[1];
- else
- goto failed;
-
- add_field_cb(contact, email, get_field_type(type));
-
-failed:
- g_strfreev(email_parts);
-}
-
-static void contact_add_emails(struct phonebook_contact *contact,
- const char **reply)
-{
- char **aff_emails;
- int i;
-
- /* Emails from affilation */
- aff_emails = g_strsplit(reply[COL_EMAIL_AFF], MAIN_DELIM, MAX_FIELDS);
-
- if (aff_emails)
- for (i = 0; aff_emails[i] != NULL; ++i)
- add_aff_field(contact, aff_emails[i], add_email);
-
- g_strfreev(aff_emails);
-}
-
-static void contact_add_addresses(struct phonebook_contact *contact,
- const char **reply)
-{
- char **aff_addr;
- int i;
-
- /* Addresses from affilation */
- aff_addr = g_strsplit(reply[COL_ADDR_AFF], MAIN_DELIM, MAX_FIELDS);
-
- if (aff_addr)
- for (i = 0; aff_addr[i] != NULL; ++i)
- add_aff_field(contact, aff_addr[i], add_address);
-
- g_strfreev(aff_addr);
-}
-
-static void contact_add_urls(struct phonebook_contact *contact,
- const char **reply)
-{
- char **aff_url;
- int i;
-
- /* Addresses from affilation */
- aff_url = g_strsplit(reply[COL_URL], MAIN_DELIM, MAX_FIELDS);
-
- if (aff_url)
- for (i = 0; aff_url[i] != NULL; ++i)
- add_aff_field(contact, aff_url[i], add_url);
-
- g_strfreev(aff_url);
-}
-
-static void contact_add_organization(struct phonebook_contact *contact,
- const char **reply)
-{
- /* Adding fields connected by nco:hasAffiliation - they may be in
- * separate replies */
- add_affiliation(&contact->title, reply[COL_TITLE]);
- add_affiliation(&contact->company, reply[COL_ORG_NAME]);
- add_affiliation(&contact->department, reply[COL_ORG_DEPARTMENT]);
- add_affiliation(&contact->role, reply[COL_ORG_ROLE]);
-}
-
-static void free_data_contacts(struct phonebook_data *data)
-{
- GSList *l;
-
- /* freeing contacts */
- for (l = data->contacts; l; l = l->next) {
- struct contact_data *c_data = l->data;
-
- g_free(c_data->id);
- phonebook_contact_free(c_data->contact);
- g_free(c_data);
- }
-
- g_slist_free(data->contacts);
- data->contacts = NULL;
-}
-
-static void send_pull_part(struct phonebook_data *data,
- const struct apparam_field *params, gboolean lastpart)
-{
- GString *vcards;
-
- DBG("");
- vcards = gen_vcards(data->contacts, params);
- data->cb(vcards->str, vcards->len, g_slist_length(data->contacts),
- data->newmissedcalls, lastpart, data->user_data);
-
- if (!lastpart)
- free_data_contacts(data);
- g_string_free(vcards, TRUE);
-}
-
-static int pull_contacts(const char **reply, int num_fields, void *user_data)
-{
- struct phonebook_data *data = user_data;
- const struct apparam_field *params = data->params;
- struct phonebook_contact *contact;
- struct contact_data *contact_data;
- int last_index, i;
- gboolean cdata_present = FALSE, part_sent = FALSE;
- static char *temp_id = NULL;
-
- if (num_fields < 0) {
- data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
- goto fail;
- }
-
- DBG("reply %p", reply);
- data->tracker_index++;
-
- if (reply == NULL)
- goto done;
-
- /* Trying to find contact in recently added contacts. It is needed for
- * contacts that have more than one telephone number filled */
- contact = find_contact(data->contacts, reply[CONTACTS_ID_COL],
- reply[COL_DATE]);
-
- /* If contact is already created then adding only new phone numbers */
- if (contact) {
- cdata_present = TRUE;
- goto add_numbers;
- }
-
- /* We are doing a PullvCardEntry, no need for those checks */
- if (data->vcardentry)
- goto add_entry;
-
- /* Last four fields are always present, ignoring them */
- for (i = 0; i < num_fields - 4; i++) {
- if (reply[i][0] != '\0')
- break;
- }
-
- if (i == num_fields - 4 && !g_str_equal(reply[CONTACTS_ID_COL],
- TRACKER_DEFAULT_CONTACT_ME))
- return 0;
-
- if (g_strcmp0(temp_id, reply[CONTACTS_ID_COL])) {
- data->index++;
- g_free(temp_id);
- temp_id = g_strdup(reply[CONTACTS_ID_COL]);
-
- /* Incrementing counter for vcards in current part of data,
- * but only if liststartoffset has been already reached */
- if (data->index > params->liststartoffset)
- data->vcard_part_count++;
- }
-
- if (data->vcard_part_count > VCARDS_PART_COUNT) {
- DBG("Part of vcard data ready for sending...");
- data->vcard_part_count = 0;
- /* Sending part of data to PBAP core - more data can be still
- * fetched, so marking lastpart as FALSE */
- send_pull_part(data, params, FALSE);
-
- /* Later, after adding contact data, need to return -EINTR to
- * stop fetching more data for this request. Data will be
- * downloaded again from this point, when phonebook_pull_read
- * will be called again with current request as a parameter*/
- part_sent = TRUE;
- }
-
- last_index = params->liststartoffset + params->maxlistcount;
-
- if (data->index <= params->liststartoffset)
- return 0;
-
- /* max number of results achieved - need send vcards data that was
- * already collected and stop further data processing (these operations
- * will be invoked in "done" section) */
- if (data->index > last_index && params->maxlistcount > 0) {
- DBG("Maxlistcount achieved");
- goto done;
- }
-
-add_entry:
- contact = g_new0(struct phonebook_contact, 1);
- contact_init(contact, reply);
-
-add_numbers:
- contact_add_numbers(contact, reply);
- contact_add_emails(contact, reply);
- contact_add_addresses(contact, reply);
- contact_add_urls(contact, reply);
- contact_add_organization(contact, reply);
-
- DBG("contact %p", contact);
-
- /* Adding contacts data to wrapper struct - this data will be used to
- * generate vcard list */
- if (!cdata_present) {
- contact_data = g_new0(struct contact_data, 1);
- contact_data->contact = contact;
- contact_data->id = g_strdup(reply[CONTACTS_ID_COL]);
- data->contacts = g_slist_append(data->contacts, contact_data);
- }
-
- if (part_sent)
- return -EINTR;
-
- return 0;
-
-done:
- /* Processing is end, this is definitely last part of transmission
- * (marking lastpart as TRUE) */
- send_pull_part(data, params, TRUE);
-
-fail:
- g_free(temp_id);
- temp_id = NULL;
-
- return -EINTR;
- /*
- * phonebook_data is freed in phonebook_req_finalize. Useful in
- * cases when call is terminated.
- */
-}
-
-static int add_to_cache(const char **reply, int num_fields, void *user_data)
-{
- struct phonebook_data *data = user_data;
- char *formatted;
- int i;
-
- if (reply == NULL || num_fields < 0)
- goto done;
-
- /* the first element is the URI, always not empty */
- for (i = 1; i < num_fields; i++) {
- if (reply[i][0] != '\0')
- break;
- }
-
- if (i == num_fields &&
- !g_str_equal(reply[0], TRACKER_DEFAULT_CONTACT_ME))
- return 0;
-
- if (i == 7)
- formatted = g_strdup(reply[7]);
- else if (i == 6)
- formatted = g_strdup(reply[6]);
- else
- formatted = g_strdup_printf("%s;%s;%s;%s;%s",
- reply[1], reply[2], reply[3], reply[4],
- reply[5]);
-
- /* The owner vCard must have the 0 handle */
- if (strcmp(reply[0], TRACKER_DEFAULT_CONTACT_ME) == 0)
- data->entry_cb(reply[0], 0, formatted, "",
- reply[6], data->user_data);
- else
- data->entry_cb(reply[0], PHONEBOOK_INVALID_HANDLE, formatted,
- "", reply[6], data->user_data);
-
- g_free(formatted);
-
- return 0;
-
-done:
- if (num_fields <= 0)
- data->ready_cb(data->user_data);
-
- return -EINTR;
- /*
- * phonebook_data is freed in phonebook_req_finalize. Useful in
- * cases when call is terminated.
- */
-}
-
-int phonebook_init(void)
-{
- g_type_init();
-
- return 0;
-}
-
-void phonebook_exit(void)
-{
-}
-
-char *phonebook_set_folder(const char *current_folder, const char *new_folder,
- uint8_t flags, int *err)
-{
- char *tmp1, *tmp2, *base, *path = NULL;
- gboolean root, child;
- int ret = 0;
- int len;
-
- root = (g_strcmp0("/", current_folder) == 0);
- child = (new_folder && strlen(new_folder) != 0);
-
- switch (flags) {
- case 0x02:
- /* Go back to root */
- if (!child) {
- path = g_strdup("/");
- goto done;
- }
-
- path = g_build_filename(current_folder, new_folder, NULL);
- break;
- case 0x03:
- /* Go up 1 level */
- if (root) {
- /* Already root */
- path = g_strdup("/");
- 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) {
- path = base;
- goto done;
- }
-
- path = g_build_filename(base, new_folder, NULL);
- g_free(base);
-
- break;
- default:
- ret = -EBADR;
- break;
- }
-
-done:
- if (path && !folder_is_valid(path))
- ret = -ENOENT;
-
- if (ret < 0) {
- g_free(path);
- path = NULL;
- }
-
- if (err)
- *err = ret;
-
- return path;
-}
-
-static int pull_newmissedcalls(const char **reply, int num_fields,
- void *user_data)
-{
- struct phonebook_data *data = user_data;
- reply_list_foreach_t pull_cb;
- int col_amount, err;
- const char *query;
- int nmissed;
-
- if (num_fields < 0) {
- data->cb(NULL, 0, num_fields, 0, TRUE, data->user_data);
-
- return -EINTR;
- }
-
- if (reply != NULL) {
- nmissed = atoi(reply[0]);
- data->newmissedcalls =
- nmissed <= UINT8_MAX ? nmissed : UINT8_MAX;
- DBG("newmissedcalls %d", data->newmissedcalls);
-
- return 0;
- }
-
- if (data->params->maxlistcount == 0) {
- query = name2count_query(PB_CALLS_MISSED);
- col_amount = COUNT_QUERY_COL_AMOUNT;
- pull_cb = pull_contacts_size;
- } else {
- query = name2query(PB_CALLS_MISSED);
- col_amount = PULL_QUERY_COL_AMOUNT;
- pull_cb = pull_contacts;
- }
-
- err = query_tracker(query, col_amount, pull_cb, data);
- if (err < 0) {
- data->cb(NULL, 0, err, 0, TRUE, data->user_data);
-
- return -EINTR;
- }
-
- return 0;
-}
-
-void phonebook_req_finalize(void *request)
-{
- struct phonebook_data *data = request;
-
- DBG("");
-
- if (!data)
- return;
-
- /* canceling asynchronous operation on tracker if any is active */
- if (data->query_canc) {
- g_cancellable_cancel(data->query_canc);
- g_object_unref(data->query_canc);
- }
-
- free_data_contacts(data);
- g_free(data->req_name);
- g_free(data);
-}
-
-void *phonebook_pull(const char *name, const struct apparam_field *params,
- phonebook_cb cb, void *user_data, int *err)
-{
- struct phonebook_data *data;
-
- DBG("name %s", name);
-
- data = g_new0(struct phonebook_data, 1);
- data->params = params;
- data->user_data = user_data;
- data->cb = cb;
- data->req_name = g_strdup(name);
-
- if (err)
- *err = 0;
-
- return data;
-}
-
-int phonebook_pull_read(void *request)
-{
- struct phonebook_data *data = request;
- reply_list_foreach_t pull_cb;
- const char *query;
- char *offset_query;
- int col_amount;
- int ret;
-
- if (!data)
- return -ENOENT;
-
- data->newmissedcalls = 0;
-
- if (g_strcmp0(data->req_name, PB_CALLS_MISSED) == 0 &&
- data->tracker_index == 0) {
- /* new missed calls amount should be counted only once - it
- * will be done during generating first part of results of
- * missed calls history */
- query = NEW_MISSED_CALLS_COUNT_QUERY;
- col_amount = COUNT_QUERY_COL_AMOUNT;
- pull_cb = pull_newmissedcalls;
- } else if (data->params->maxlistcount == 0) {
- query = name2count_query(data->req_name);
- col_amount = COUNT_QUERY_COL_AMOUNT;
- pull_cb = pull_contacts_size;
- } else {
- query = name2query(data->req_name);
- col_amount = PULL_QUERY_COL_AMOUNT;
- pull_cb = pull_contacts;
- }
-
- if (query == NULL)
- return -ENOENT;
-
- if (pull_cb == pull_contacts && data->tracker_index > 0) {
- /* Adding offset to pull query to download next parts of data
- * from tracker (phonebook_pull_read may be called many times
- * from PBAP core to fetch data partially) */
- offset_query = g_strdup_printf(QUERY_OFFSET_FORMAT, query,
- data->tracker_index);
- ret = query_tracker(offset_query, col_amount, pull_cb, data);
-
- g_free(offset_query);
-
- return ret;
- }
-
- return query_tracker(query, col_amount, pull_cb, data);
-}
-
-void *phonebook_get_entry(const char *folder, const char *id,
- const struct apparam_field *params,
- phonebook_cb cb, void *user_data, int *err)
-{
- struct phonebook_data *data;
- char *query;
- int ret;
-
- DBG("folder %s id %s", folder, id);
-
- data = g_new0(struct phonebook_data, 1);
- data->user_data = user_data;
- data->params = params;
- data->cb = cb;
- data->vcardentry = TRUE;
-
- if (g_str_has_prefix(id, CONTACT_ID_PREFIX) == TRUE ||
- g_strcmp0(id, TRACKER_DEFAULT_CONTACT_ME) == 0)
- query = g_strdup_printf(CONTACTS_QUERY_FROM_URI, id, id, id, id,
- id, id, id, id, id, id, id, id, id);
- else if (g_str_has_prefix(id, CALL_ID_PREFIX) == TRUE)
- query = g_strdup_printf(CONTACT_FROM_CALL_QUERY, id);
- else
- query = g_strdup_printf(CONTACTS_OTHER_QUERY_FROM_URI,
- id, id, id);
-
- ret = query_tracker(query, PULL_QUERY_COL_AMOUNT, pull_contacts, data);
- if (err)
- *err = ret;
-
- g_free(query);
-
- 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)
-{
- struct phonebook_data *data;
- const char *query;
- int ret;
-
- DBG("name %s", name);
-
- query = folder2query(name);
- if (query == NULL) {
- if (err)
- *err = -ENOENT;
- return NULL;
- }
-
- data = g_new0(struct phonebook_data, 1);
- data->entry_cb = entry_cb;
- data->ready_cb = ready_cb;
- data->user_data = user_data;
-
- ret = query_tracker(query, 8, add_to_cache, data);
- if (err)
- *err = ret;
-
- return data;
-}

--
2.43.0


Subject: [PATCH BlueZ 2/9] Return at least the title attribute from player_list_metadata()

From: Sam Lantinga <[email protected]>

This fixes Bluetooth AVRCP certification test AVRCP/TG/MDI/BV-04-C,
which requires a valid response from the get_element_attributes command.
---
profiles/audio/avrcp.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/profiles/audio/avrcp.c b/profiles/audio/avrcp.c
index 439fa27a9..36ce01a14 100644
--- a/profiles/audio/avrcp.c
+++ b/profiles/audio/avrcp.c
@@ -1210,6 +1210,10 @@ static GList *player_list_metadata(struct avrcp_player *player)
GUINT_TO_POINTER(str_to_metadata(key)));
}

+ if (attrs == NULL)
+ return g_list_prepend(NULL,
+ GUINT_TO_POINTER(AVRCP_MEDIA_ATTRIBUTE_TITLE));
+
return attrs;
}


--
2.43.0