diff -Nru obexd-0.46/aclocal.m4 obexd-0.48/aclocal.m4 --- obexd-0.46/aclocal.m4 2012-05-17 17:12:32.000000000 +0200 +++ obexd-0.48/aclocal.m4 2012-11-30 08:59:27.000000000 +0100 @@ -1,4 +1,4 @@ -# generated automatically by aclocal 1.11.3 -*- Autoconf -*- +# generated automatically by aclocal 1.11.6 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, @@ -2526,17 +2526,6 @@ esac ;; -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no @@ -2653,7 +2642,7 @@ ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no @@ -3269,10 +3258,6 @@ fi ;; -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - haiku*) lt_cv_deplibs_check_method=pass_all ;; @@ -3311,7 +3296,7 @@ ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; @@ -4063,7 +4048,7 @@ ;; esac ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler @@ -4362,7 +4347,7 @@ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) @@ -6251,9 +6236,6 @@ _LT_TAGVAR(ld_shlibs, $1)=yes ;; - gnu*) - ;; - haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes @@ -6415,7 +6397,7 @@ _LT_TAGVAR(inherit_rpath, $1)=yes ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler @@ -8804,7 +8786,7 @@ [am__api_version='1.11' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.11.3], [], +m4_if([$1], [1.11.6], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -8820,7 +8802,7 @@ # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.11.3])dnl +[AM_AUTOMAKE_VERSION([1.11.6])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) diff -Nru obexd-0.46/btio/btio.c obexd-0.48/btio/btio.c --- obexd-0.46/btio/btio.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/btio/btio.c 2012-11-30 08:59:13.000000000 +0100 @@ -43,14 +43,23 @@ #endif #define ERROR_FAILED(gerr, str, err) \ - g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_FAILED, \ + g_set_error(gerr, BT_IO_ERROR, err, \ str ": %s (%d)", strerror(err), err) #define DEFAULT_DEFER_TIMEOUT 30 +typedef enum { + BT_IO_L2CAP, + BT_IO_RFCOMM, + BT_IO_SCO, + BT_IO_INVALID, +} BtIOType; + struct set_opts { bdaddr_t src; bdaddr_t dst; + BtIOType type; + uint8_t dst_type; int defer; int sec_level; uint8_t channel; @@ -84,6 +93,48 @@ GDestroyNotify destroy; }; +static BtIOType bt_io_get_type(GIOChannel *io, GError **gerr) +{ + int sk = g_io_channel_unix_get_fd(io); + int domain, proto, err; + socklen_t len; + + domain = 0; + len = sizeof(domain); + err = getsockopt(sk, SOL_SOCKET, SO_DOMAIN, &domain, &len); + if (err < 0) { + ERROR_FAILED(gerr, "getsockopt(SO_DOMAIN)", errno); + return BT_IO_INVALID; + } + + if (domain != AF_BLUETOOTH) { + g_set_error(gerr, BT_IO_ERROR, EINVAL, + "BtIO socket domain not AF_BLUETOOTH"); + return BT_IO_INVALID; + } + + proto = 0; + len = sizeof(proto); + err = getsockopt(sk, SOL_SOCKET, SO_PROTOCOL, &proto, &len); + if (err < 0) { + ERROR_FAILED(gerr, "getsockopt(SO_PROTOCOL)", errno); + return BT_IO_INVALID; + } + + switch (proto) { + case BTPROTO_RFCOMM: + return BT_IO_RFCOMM; + case BTPROTO_SCO: + return BT_IO_SCO; + case BTPROTO_L2CAP: + return BT_IO_L2CAP; + default: + g_set_error(gerr, BT_IO_ERROR, EINVAL, + "Unknown BtIO socket type"); + return BT_IO_INVALID; + } +} + static void server_remove(struct server *server) { if (server->destroy) @@ -123,19 +174,28 @@ gpointer user_data) { struct accept *accept = user_data; - GError *err = NULL; + GError *gerr = NULL; /* If the user aborted this accept attempt */ if ((cond & G_IO_NVAL) || check_nval(io)) return FALSE; - if (cond & (G_IO_HUP | G_IO_ERR)) - g_set_error(&err, BT_IO_ERROR, BT_IO_ERROR_DISCONNECTED, - "HUP or ERR on socket"); + if (cond & (G_IO_HUP | G_IO_ERR)) { + int err, sk_err, sock = g_io_channel_unix_get_fd(io); + socklen_t len = sizeof(sk_err); - accept->connect(io, err, accept->user_data); + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0) + err = -errno; + else + err = -sk_err; + + if (err < 0) + ERROR_FAILED(&gerr, "HUP or ERR on socket", -err); + } + + accept->connect(io, gerr, accept->user_data); - g_clear_error(&err); + g_clear_error(&gerr); return FALSE; } @@ -145,32 +205,26 @@ { struct connect *conn = user_data; GError *gerr = NULL; + int err, sk_err, sock; + socklen_t len = sizeof(sk_err); /* If the user aborted this connect attempt */ if ((cond & G_IO_NVAL) || check_nval(io)) return FALSE; - if (cond & G_IO_OUT) { - int err, sk_err = 0, sock = g_io_channel_unix_get_fd(io); - socklen_t len = sizeof(sk_err); + sock = g_io_channel_unix_get_fd(io); - if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0) - err = -errno; - else - err = -sk_err; + if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &sk_err, &len) < 0) + err = -errno; + else + err = -sk_err; - if (err < 0) - g_set_error(&gerr, BT_IO_ERROR, - BT_IO_ERROR_CONNECT_FAILED, "%s (%d)", - strerror(-err), -err); - } else if (cond & (G_IO_HUP | G_IO_ERR)) - g_set_error(&gerr, BT_IO_ERROR, BT_IO_ERROR_CONNECT_FAILED, - "HUP or ERR on socket"); + if (err < 0) + ERROR_FAILED(&gerr, "connect error", -err); conn->connect(io, gerr, conn->user_data); - if (gerr) - g_error_free(gerr); + g_clear_error(&gerr); return FALSE; } @@ -280,8 +334,8 @@ return 0; } -static int l2cap_connect(int sock, const bdaddr_t *dst, - uint16_t psm, uint16_t cid) +static int l2cap_connect(int sock, const bdaddr_t *dst, uint8_t dst_type, + uint16_t psm, uint16_t cid) { int err; struct sockaddr_l2 addr; @@ -294,6 +348,8 @@ else addr.l2_psm = htobs(psm); + addr.l2_bdaddr_type = dst_type; + err = connect(sock, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) return -errno; @@ -387,7 +443,7 @@ int ret; if (level < BT_SECURITY_LOW || level > BT_SECURITY_HIGH) { - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, + g_set_error(err, BT_IO_ERROR, EINVAL, "Valid security level range is %d-%d", BT_SECURITY_LOW, BT_SECURITY_HIGH); return FALSE; @@ -693,11 +749,13 @@ memset(opts, 0, sizeof(*opts)); /* Set defaults */ + opts->type = BT_IO_SCO; opts->defer = DEFAULT_DEFER_TIMEOUT; opts->master = -1; opts->mode = L2CAP_MODE_BASIC; opts->flushable = -1; opts->priority = 0; + opts->dst_type = BDADDR_BREDR; while (opt != BT_IO_OPT_INVALID) { switch (opt) { @@ -714,6 +772,9 @@ case BT_IO_OPT_DEST_BDADDR: bacpy(&opts->dst, va_arg(args, const bdaddr_t *)); break; + case BT_IO_OPT_DEST_TYPE: + opts->dst_type = va_arg(args, int); + break; case BT_IO_OPT_DEFER_TIMEOUT: opts->defer = va_arg(args, int); break; @@ -721,12 +782,15 @@ opts->sec_level = va_arg(args, int); break; case BT_IO_OPT_CHANNEL: + opts->type = BT_IO_RFCOMM; opts->channel = va_arg(args, int); break; case BT_IO_OPT_PSM: + opts->type = BT_IO_L2CAP; opts->psm = va_arg(args, int); break; case BT_IO_OPT_CID: + opts->type = BT_IO_L2CAP; opts->cid = va_arg(args, int); break; case BT_IO_OPT_MTU: @@ -757,7 +821,7 @@ opts->priority = va_arg(args, int); break; default: - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, + g_set_error(err, BT_IO_ERROR, EINVAL, "Unknown option %d", opt); return FALSE; } @@ -875,6 +939,9 @@ case BT_IO_OPT_DEST_BDADDR: bacpy(va_arg(args, bdaddr_t *), &dst.l2_bdaddr); break; + case BT_IO_OPT_DEST_TYPE: + ERROR_FAILED(err, "Not implemented", EINVAL); + return FALSE; case BT_IO_OPT_DEFER_TIMEOUT: len = sizeof(int); if (getsockopt(sock, SOL_BLUETOOTH, BT_DEFER_SETUP, @@ -950,7 +1017,7 @@ *(va_arg(args, uint32_t *)) = priority; break; default: - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, + g_set_error(err, BT_IO_ERROR, EINVAL, "Unknown option %d", opt); return FALSE; } @@ -1057,7 +1124,7 @@ memcpy(va_arg(args, uint8_t *), dev_class, 3); break; default: - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, + g_set_error(err, BT_IO_ERROR, EINVAL, "Unknown option %d", opt); return FALSE; } @@ -1140,7 +1207,7 @@ memcpy(va_arg(args, uint8_t *), dev_class, 3); break; default: - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, + g_set_error(err, BT_IO_ERROR, EINVAL, "Unknown option %d", opt); return FALSE; } @@ -1159,19 +1226,17 @@ sock = g_io_channel_unix_get_fd(io); switch (type) { - case BT_IO_L2RAW: case BT_IO_L2CAP: - case BT_IO_L2ERTM: return l2cap_get(sock, err, opt1, args); case BT_IO_RFCOMM: return rfcomm_get(sock, err, opt1, args); case BT_IO_SCO: return sco_get(sock, err, opt1, args); + default: + g_set_error(err, BT_IO_ERROR, EINVAL, + "Unknown BtIO type %d", type); + return FALSE; } - - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown BtIO type %d", type); - return FALSE; } gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data, @@ -1204,13 +1269,13 @@ return TRUE; } -gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err, - BtIOOption opt1, ...) +gboolean bt_io_set(GIOChannel *io, GError **err, BtIOOption opt1, ...) { va_list args; gboolean ret; struct set_opts opts; int sock; + BtIOType type; va_start(args, opt1); ret = parse_set_opts(&opts, err, opt1, args); @@ -1219,12 +1284,14 @@ if (!ret) return ret; + type = bt_io_get_type(io, err); + if (type == BT_IO_INVALID) + return FALSE; + sock = g_io_channel_unix_get_fd(io); switch (type) { - case BT_IO_L2RAW: case BT_IO_L2CAP: - case BT_IO_L2ERTM: return l2cap_set(sock, opts.sec_level, opts.imtu, opts.omtu, opts.mode, opts.master, opts.flushable, opts.priority, err); @@ -1232,18 +1299,23 @@ return rfcomm_set(sock, opts.sec_level, opts.master, err); case BT_IO_SCO: return sco_set(sock, opts.mtu, err); + default: + g_set_error(err, BT_IO_ERROR, EINVAL, + "Unknown BtIO type %d", type); + return FALSE; } - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown BtIO type %d", type); - return FALSE; } -gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err, - BtIOOption opt1, ...) +gboolean bt_io_get(GIOChannel *io, GError **err, BtIOOption opt1, ...) { va_list args; gboolean ret; + BtIOType type; + + type = bt_io_get_type(io, err); + if (type == BT_IO_INVALID) + return FALSE; va_start(args, opt1); ret = get_valist(io, type, err, opt1, args); @@ -1252,25 +1324,13 @@ return ret; } -static GIOChannel *create_io(BtIOType type, gboolean server, - struct set_opts *opts, GError **err) +static GIOChannel *create_io(gboolean server, struct set_opts *opts, + GError **err) { int sock; GIOChannel *io; - switch (type) { - case BT_IO_L2RAW: - sock = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP); - if (sock < 0) { - ERROR_FAILED(err, "socket(RAW, L2CAP)", errno); - return NULL; - } - if (l2cap_bind(sock, &opts->src, server ? opts->psm : 0, - opts->cid, err) < 0) - goto failed; - if (!l2cap_set(sock, opts->sec_level, 0, 0, 0, -1, -1, 0, err)) - goto failed; - break; + switch (opts->type) { case BT_IO_L2CAP: sock = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP); if (sock < 0) { @@ -1285,20 +1345,6 @@ opts->priority, err)) goto failed; break; - case BT_IO_L2ERTM: - sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_L2CAP); - if (sock < 0) { - ERROR_FAILED(err, "socket(STREAM, L2CAP)", errno); - return NULL; - } - if (l2cap_bind(sock, &opts->src, server ? opts->psm : 0, - opts->cid, err) < 0) - goto failed; - if (!l2cap_set(sock, opts->sec_level, opts->imtu, opts->omtu, - opts->mode, opts->master, opts->flushable, - opts->priority, err)) - goto failed; - break; case BT_IO_RFCOMM: sock = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); if (sock < 0) { @@ -1323,8 +1369,8 @@ goto failed; break; default: - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown BtIO type %d", type); + g_set_error(err, BT_IO_ERROR, EINVAL, + "Unknown BtIO type %d", opts->type); return NULL; } @@ -1341,9 +1387,9 @@ return NULL; } -GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect, - gpointer user_data, GDestroyNotify destroy, - GError **gerr, BtIOOption opt1, ...) +GIOChannel *bt_io_connect(BtIOConnect connect, gpointer user_data, + GDestroyNotify destroy, GError **gerr, + BtIOOption opt1, ...) { GIOChannel *io; va_list args; @@ -1358,19 +1404,16 @@ if (ret == FALSE) return NULL; - io = create_io(type, FALSE, &opts, gerr); + io = create_io(FALSE, &opts, gerr); if (io == NULL) return NULL; sock = g_io_channel_unix_get_fd(io); - switch (type) { - case BT_IO_L2RAW: - err = l2cap_connect(sock, &opts.dst, 0, opts.cid); - break; + switch (opts.type) { case BT_IO_L2CAP: - case BT_IO_L2ERTM: - err = l2cap_connect(sock, &opts.dst, opts.psm, opts.cid); + err = l2cap_connect(sock, &opts.dst, opts.dst_type, + opts.psm, opts.cid); break; case BT_IO_RFCOMM: err = rfcomm_connect(sock, &opts.dst, opts.channel); @@ -1379,14 +1422,13 @@ err = sco_connect(sock, &opts.dst); break; default: - g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Unknown BtIO type %d", type); + g_set_error(gerr, BT_IO_ERROR, EINVAL, + "Unknown BtIO type %d", opts.type); return NULL; } if (err < 0) { - g_set_error(gerr, BT_IO_ERROR, BT_IO_ERROR_CONNECT_FAILED, - "connect: %s (%d)", strerror(-err), -err); + ERROR_FAILED(gerr, "connect", -err); g_io_channel_unref(io); return NULL; } @@ -1396,10 +1438,9 @@ return io; } -GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect, - BtIOConfirm confirm, gpointer user_data, - GDestroyNotify destroy, GError **err, - BtIOOption opt1, ...) +GIOChannel *bt_io_listen(BtIOConnect connect, BtIOConfirm confirm, + gpointer user_data, GDestroyNotify destroy, + GError **err, BtIOOption opt1, ...) { GIOChannel *io; va_list args; @@ -1407,12 +1448,6 @@ int sock; gboolean ret; - if (type == BT_IO_L2RAW) { - g_set_error(err, BT_IO_ERROR, BT_IO_ERROR_INVALID_ARGS, - "Server L2CAP RAW sockets not supported"); - return NULL; - } - va_start(args, opt1); ret = parse_set_opts(&opts, err, opt1, args); va_end(args); @@ -1420,7 +1455,7 @@ if (ret == FALSE) return NULL; - io = create_io(type, TRUE, &opts, err); + io = create_io(TRUE, &opts, err); if (io == NULL) return NULL; diff -Nru obexd-0.46/btio/btio.h obexd-0.48/btio/btio.h --- obexd-0.46/btio/btio.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/btio/btio.h 2012-11-30 08:59:13.000000000 +0100 @@ -26,31 +26,17 @@ #include -typedef enum { - BT_IO_ERROR_DISCONNECTED, - BT_IO_ERROR_CONNECT_FAILED, - BT_IO_ERROR_FAILED, - BT_IO_ERROR_INVALID_ARGS, -} BtIOError; - #define BT_IO_ERROR bt_io_error_quark() GQuark bt_io_error_quark(void); typedef enum { - BT_IO_L2RAW, - BT_IO_L2CAP, - BT_IO_L2ERTM, - BT_IO_RFCOMM, - BT_IO_SCO, -} BtIOType; - -typedef enum { BT_IO_OPT_INVALID = 0, BT_IO_OPT_SOURCE, BT_IO_OPT_SOURCE_BDADDR, BT_IO_OPT_DEST, BT_IO_OPT_DEST_BDADDR, + BT_IO_OPT_DEST_TYPE, BT_IO_OPT_DEFER_TIMEOUT, BT_IO_OPT_SEC_LEVEL, BT_IO_OPT_KEY_SIZE, @@ -92,19 +78,16 @@ gboolean bt_io_accept(GIOChannel *io, BtIOConnect connect, gpointer user_data, GDestroyNotify destroy, GError **err); -gboolean bt_io_set(GIOChannel *io, BtIOType type, GError **err, - BtIOOption opt1, ...); +gboolean bt_io_set(GIOChannel *io, GError **err, BtIOOption opt1, ...); -gboolean bt_io_get(GIOChannel *io, BtIOType type, GError **err, - BtIOOption opt1, ...); +gboolean bt_io_get(GIOChannel *io, GError **err, BtIOOption opt1, ...); -GIOChannel *bt_io_connect(BtIOType type, BtIOConnect connect, +GIOChannel *bt_io_connect(BtIOConnect connect, gpointer user_data, + GDestroyNotify destroy, GError **gerr, + BtIOOption opt1, ...); + +GIOChannel *bt_io_listen(BtIOConnect connect, BtIOConfirm confirm, gpointer user_data, GDestroyNotify destroy, GError **err, BtIOOption opt1, ...); -GIOChannel *bt_io_listen(BtIOType type, BtIOConnect connect, - BtIOConfirm confirm, gpointer user_data, - GDestroyNotify destroy, GError **err, - BtIOOption opt1, ...); - #endif diff -Nru obexd-0.46/ChangeLog obexd-0.48/ChangeLog --- obexd-0.46/ChangeLog 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/ChangeLog 2012-11-30 08:59:13.000000000 +0100 @@ -1,3 +1,13 @@ +ver 0.48: + Fix issue with phonebook contacts query. + Add support for phonebook client filters. + Add support for message status handling. + Add support for OBEX application parameter API. + +ver 0.47: + Update client session API. + Change D-Bus namespace to org.bluez.obex. + ver 0.46: Update client transfer API. Fix issue with using invalid PSM numbers. diff -Nru obexd-0.46/client/agent.c obexd-0.48/client/agent.c --- obexd-0.46/client/agent.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/agent.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,252 +0,0 @@ -/* - * - * OBEX Client - * - * Copyright (C) 2007-2010 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "log.h" -#include "agent.h" - -#define AGENT_INTERFACE "org.openobex.Agent" - -struct pending_request { - DBusPendingCall *call; - DBusPendingCallNotifyFunction function; - void *data; - DBusFreeFunction destroy; -}; - -struct obc_agent { - DBusConnection *conn; - char *name; - char *path; - guint watch; - GFunc destroy; - void *data; - struct pending_request *pending; -}; - -static void pending_request_free(struct pending_request *req) -{ - if (req->call) - dbus_pending_call_unref(req->call); - - if (req->destroy) - req->destroy(req->data); - - g_free(req); -} - -void obc_agent_free(struct obc_agent *agent) -{ - if (agent->watch) - g_dbus_remove_watch(agent->conn, agent->watch); - - if (agent->pending) { - if (agent->pending->call) - dbus_pending_call_cancel(agent->pending->call); - pending_request_free(agent->pending); - } - - dbus_connection_unref(agent->conn); - g_free(agent->name); - g_free(agent->path); - g_free(agent); -} - -static void agent_disconnected(DBusConnection *connection, void *user_data) -{ - struct obc_agent *agent = user_data; - - agent->watch = 0; - - if (agent->destroy) - agent->destroy(agent, agent->data); - - obc_agent_free(agent); -} - -struct obc_agent *obc_agent_create(DBusConnection *conn, const char *name, - const char *path, GFunc destroy, - void *user_data) -{ - struct obc_agent *agent; - - agent = g_new0(struct obc_agent, 1); - agent->conn = dbus_connection_ref(conn); - agent->name = g_strdup(name); - agent->path = g_strdup(path); - agent->destroy = destroy; - agent->data = user_data; - - agent->watch = g_dbus_add_disconnect_watch(conn, name, - agent_disconnected, - agent, NULL); - - return agent; -} - -static void agent_request_reply(DBusPendingCall *call, void *user_data) -{ - struct obc_agent *agent = user_data; - struct pending_request *req = agent->pending; - - agent->pending = NULL; - - if (req->function) - req->function(call, req->data); - - pending_request_free(req); -} - -int obc_agent_request(struct obc_agent *agent, const char *path, - DBusPendingCallNotifyFunction function, - void *user_data, DBusFreeFunction destroy) -{ - struct pending_request *req; - DBusMessage *message; - - if (agent->pending) - return -EBUSY; - - DBG("%s", path); - - message = dbus_message_new_method_call(agent->name, - agent->path, AGENT_INTERFACE, "Request"); - - dbus_message_append_args(message, - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - - req = g_new0(struct pending_request, 1); - req->function = function; - req->destroy = destroy; - req->data = user_data; - - if (!dbus_connection_send_with_reply(agent->conn, message, - &req->call, -1)) { - g_free(req); - dbus_message_unref(message); - return -ENOMEM; - } - - agent->pending = req; - - dbus_message_unref(message); - - dbus_pending_call_set_notify(req->call, agent_request_reply, - agent, NULL); - - return 0; -} - -void obc_agent_notify_progress(struct obc_agent *agent, const char *path, - guint64 transferred) -{ - DBusMessage *message; - - DBG("%s", path); - - message = dbus_message_new_method_call(agent->name, - agent->path, AGENT_INTERFACE, "Progress"); - if (message == NULL) - return; - - dbus_message_set_no_reply(message, TRUE); - - dbus_message_append_args(message, - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_UINT64, &transferred, - DBUS_TYPE_INVALID); - - g_dbus_send_message(agent->conn, message); -} - -void obc_agent_notify_complete(struct obc_agent *agent, const char *path) -{ - DBusMessage *message; - - DBG("%s", path); - - message = dbus_message_new_method_call(agent->name, - agent->path, AGENT_INTERFACE, "Complete"); - if (message == NULL) - return; - - dbus_message_set_no_reply(message, TRUE); - - dbus_message_append_args(message, - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - - g_dbus_send_message(agent->conn, message); -} - -void obc_agent_notify_error(struct obc_agent *agent, const char *path, - const char *err) -{ - DBusMessage *message; - - DBG("%s", path); - - message = dbus_message_new_method_call(agent->name, - agent->path, AGENT_INTERFACE, "Error"); - if (message == NULL) - return; - - dbus_message_set_no_reply(message, TRUE); - - dbus_message_append_args(message, - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_STRING, &err, - DBUS_TYPE_INVALID); - - g_dbus_send_message(agent->conn, message); -} - -void obc_agent_release(struct obc_agent *agent) -{ - DBusMessage *message; - - DBG(""); - - message = dbus_message_new_method_call(agent->name, - agent->path, AGENT_INTERFACE, "Release"); - - dbus_message_set_no_reply(message, TRUE); - - g_dbus_send_message(agent->conn, message); -} - -const char *obc_agent_get_name(struct obc_agent *agent) -{ - return agent->name; -} - -const char *obc_agent_get_path(struct obc_agent *agent) -{ - return agent->path; -} diff -Nru obexd-0.46/client/agent.h obexd-0.48/client/agent.h --- obexd-0.46/client/agent.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/agent.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,43 +0,0 @@ -/* - * - * OBEX Client - * - * Copyright (C) 2007-2010 Intel Corporation - * Copyright (C) 2007-2010 Marcel Holtmann - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include - -struct obc_agent; - -struct obc_agent *obc_agent_create(DBusConnection *conn, const char *name, - const char *path, GFunc destroy, - void *user_data); -void obc_agent_free(struct obc_agent *agent); -const char *obc_agent_get_name(struct obc_agent *agent); -const char *obc_agent_get_path(struct obc_agent *agent); -int obc_agent_request(struct obc_agent *agent, const char *path, - DBusPendingCallNotifyFunction function, - void *user_data, DBusFreeFunction destroy); -void obc_agent_notify_progress(struct obc_agent *agent, const char *path, - guint64 transferred); -void obc_agent_notify_complete(struct obc_agent *agent, const char *path); -void obc_agent_notify_error(struct obc_agent *agent, const char *path, - const char *err); -void obc_agent_release(struct obc_agent *agent); diff -Nru obexd-0.46/client/bluetooth.c obexd-0.48/client/bluetooth.c --- obexd-0.46/client/bluetooth.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/bluetooth.c 2012-11-30 08:59:13.000000000 +0100 @@ -116,6 +116,8 @@ session->pending_calls = g_slist_prepend(session->pending_calls, call); + dbus_message_unref(msg); + return 0; } @@ -158,6 +160,9 @@ g_io_channel_unref(session->io); } + if (session->sdp) + sdp_close(session->sdp); + if (session->conn) dbus_connection_unref(session->conn); @@ -189,7 +194,7 @@ DBG("port %u", port); if (port > 31) { - io = bt_io_connect(BT_IO_L2CAP, function, user_data, + io = bt_io_connect(function, user_data, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, src, BT_IO_OPT_DEST_BDADDR, dst, @@ -200,7 +205,7 @@ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); } else { - io = bt_io_connect(BT_IO_RFCOMM, function, user_data, + io = bt_io_connect(function, user_data, NULL, &err, BT_IO_OPT_SOURCE_BDADDR, src, BT_IO_OPT_DEST_BDADDR, dst, @@ -576,6 +581,7 @@ session->id = ++id; session->func = func; + session->port = port; session->user_data = user_data; session->conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL); @@ -629,7 +635,7 @@ if (type != SOCK_SEQPACKET) return -EINVAL; - if (!bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_OMTU, &omtu, + if (!bt_io_get(io, NULL, BT_IO_OPT_OMTU, &omtu, BT_IO_OPT_IMTU, &imtu, BT_IO_OPT_INVALID)) return -EINVAL; diff -Nru obexd-0.46/client/dbus.c obexd-0.48/client/dbus.c --- obexd-0.46/client/dbus.c 1970-01-01 01:00:00.000000000 +0100 +++ obexd-0.48/client/dbus.c 2012-07-26 19:09:25.000000000 +0200 @@ -0,0 +1,256 @@ +/* + * + * OBEX Client + * + * Copyright (C) 2008-2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "log.h" +#include "dbus.h" + +static void append_variant(DBusMessageIter *iter, + int type, void *value) +{ + char sig[2]; + DBusMessageIter valueiter; + + sig[0] = type; + sig[1] = 0; + + dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, + sig, &valueiter); + + dbus_message_iter_append_basic(&valueiter, type, value); + + dbus_message_iter_close_container(iter, &valueiter); +} + +void obex_dbus_dict_append(DBusMessageIter *dict, + const char *key, int type, void *value) +{ + DBusMessageIter keyiter; + + if (type == DBUS_TYPE_STRING) { + const char *str = *((const char **) value); + if (str == NULL) + return; + } + + dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, + NULL, &keyiter); + + dbus_message_iter_append_basic(&keyiter, DBUS_TYPE_STRING, &key); + + append_variant(&keyiter, type, value); + + dbus_message_iter_close_container(dict, &keyiter); +} + +static void append_array_variant(DBusMessageIter *iter, int type, void *val) +{ + DBusMessageIter variant, array; + char typesig[2]; + char arraysig[3]; + const char **str_array = *(const char ***) val; + int i; + + arraysig[0] = DBUS_TYPE_ARRAY; + arraysig[1] = typesig[0] = type; + arraysig[2] = typesig[1] = '\0'; + + dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, + arraysig, &variant); + + dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, + typesig, &array); + + for (i = 0; str_array[i]; i++) + dbus_message_iter_append_basic(&array, type, + &(str_array[i])); + + dbus_message_iter_close_container(&variant, &array); + + dbus_message_iter_close_container(iter, &variant); +} + +void obex_dbus_dict_append_array(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); + + append_array_variant(&entry, type, val); + + dbus_message_iter_close_container(dict, &entry); +} + +static void append_dict_variant(DBusMessageIter *iter, int type, void *val) +{ + DBusMessageIter variant, array, entry; + char typesig[5]; + char arraysig[6]; + const void **val_array = *(const void ***) val; + int i; + + arraysig[0] = DBUS_TYPE_ARRAY; + arraysig[1] = typesig[0] = DBUS_DICT_ENTRY_BEGIN_CHAR; + arraysig[2] = typesig[1] = DBUS_TYPE_STRING; + arraysig[3] = typesig[2] = type; + arraysig[4] = typesig[3] = DBUS_DICT_ENTRY_END_CHAR; + arraysig[5] = typesig[4] = '\0'; + + dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, + arraysig, &variant); + + dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, + typesig, &array); + + for (i = 0; val_array[i]; i += 2) { + dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, + NULL, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, + &(val_array[i + 0])); + + /* + * D-Bus expects a char** or uint8* depending on the type + * given. Since we are dealing with an array through a void** + * (and thus val_array[i] is a pointer) we need to + * differentiate DBUS_TYPE_STRING from the others. The other + * option would be the user to pass the exact type to this + * function, instead of a pointer to it. However in this case + * a cast from type to void* would be needed, which is not + * good. + */ + if (type == DBUS_TYPE_STRING) { + dbus_message_iter_append_basic(&entry, type, + &(val_array[i + 1])); + } else { + dbus_message_iter_append_basic(&entry, type, + val_array[i + 1]); + } + + dbus_message_iter_close_container(&array, &entry); + } + + dbus_message_iter_close_container(&variant, &array); + + dbus_message_iter_close_container(iter, &variant); +} + +void obex_dbus_dict_append_dict(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); + + append_dict_variant(&entry, type, val); + + dbus_message_iter_close_container(dict, &entry); +} + +int obex_dbus_signal_property_changed(DBusConnection *conn, + const char *path, + const char *interface, + const char *name, + int type, void *value) +{ + DBusMessage *signal; + DBusMessageIter iter; + + signal = dbus_message_new_signal(path, interface, "PropertyChanged"); + if (signal == NULL) { + error("Unable to allocate new %s.PropertyChanged signal", + interface); + return -1; + } + + dbus_message_iter_init_append(signal, &iter); + + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name); + + append_variant(&iter, type, value); + + return g_dbus_send_message(conn, signal); +} + +int obex_dbus_signal_array_property_changed(DBusConnection *conn, + const char *path, + const char *interface, + const char *name, + int type, void *value) + +{ + DBusMessage *signal; + DBusMessageIter iter; + + signal = dbus_message_new_signal(path, interface, "PropertyChanged"); + if (signal == NULL) { + error("Unable to allocate new %s.PropertyChanged signal", + interface); + return -1; + } + + dbus_message_iter_init_append(signal, &iter); + + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name); + + append_array_variant(&iter, type, value); + + return g_dbus_send_message(conn, signal); +} + +int obex_dbus_signal_dict_property_changed(DBusConnection *conn, + const char *path, + const char *interface, + const char *name, + int type, void *value) + +{ + DBusMessage *signal; + DBusMessageIter iter; + + signal = dbus_message_new_signal(path, interface, "PropertyChanged"); + if (signal == NULL) { + error("Unable to allocate new %s.PropertyChanged signal", + interface); + return -1; + } + + dbus_message_iter_init_append(signal, &iter); + + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name); + + append_dict_variant(&iter, type, value); + + return g_dbus_send_message(conn, signal); +} diff -Nru obexd-0.46/client/dbus.h obexd-0.48/client/dbus.h --- obexd-0.46/client/dbus.h 1970-01-01 01:00:00.000000000 +0100 +++ obexd-0.48/client/dbus.h 2012-07-26 19:09:25.000000000 +0200 @@ -0,0 +1,66 @@ +/* + * + * OBEX Client + * + * Copyright (C) 2008-2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __OBEX_DBUS_H +#define __OBEX_DBUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Essentially a{sv} */ +#define OBC_PROPERTIES_ARRAY_SIGNATURE DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING \ + DBUS_TYPE_STRING_AS_STRING \ + DBUS_TYPE_VARIANT_AS_STRING \ + DBUS_DICT_ENTRY_END_CHAR_AS_STRING + +void obex_dbus_dict_append(DBusMessageIter *dict, const char *key, int type, + void *value); + +void obex_dbus_dict_append_array(DBusMessageIter *dict, const char *key, + int type, void *val); + +void obex_dbus_dict_append_dict(DBusMessageIter *dict, const char *key, + int type, void *val); + +int obex_dbus_signal_property_changed(DBusConnection *conn, const char *path, + const char *interface, const char *name, + int type, void *value); + +int obex_dbus_signal_array_property_changed(DBusConnection *conn, + const char *path, + const char *interface, + const char *name, int type, + void *value); + +int obex_dbus_signal_dict_property_changed(DBusConnection *conn, + const char *path, + const char *interface, + const char *name, int type, + void *value); + +#ifdef __cplusplus +} +#endif + +#endif /* __OBEX_DBUS_H */ diff -Nru obexd-0.46/client/ftp.c obexd-0.48/client/ftp.c --- obexd-0.46/client/ftp.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/ftp.c 2012-07-26 19:09:25.000000000 +0200 @@ -30,6 +30,7 @@ #include +#include "dbus.h" #include "log.h" #include "transfer.h" @@ -41,7 +42,8 @@ "\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09" #define OBEX_FTP_UUID_LEN 16 -#define FTP_INTERFACE "org.openobex.FileTransfer" +#define FTP_INTERFACE "org.bluez.obex.FileTransfer" +#define ERROR_INTERFACE "org.bluez.obex.Error" #define FTP_UUID "00001106-0000-1000-8000-00805f9b34fb" #define PCSUITE_UUID "00005005-0000-1000-8000-0002ee000001" @@ -57,7 +59,7 @@ DBusMessage *reply, *msg = user_data; if (err != NULL) - reply = g_dbus_create_error(msg, "org.openobex.Error.Failed", + reply = g_dbus_create_error(msg, ERROR_INTERFACE ".Failed", "%s", err->message); else reply = dbus_message_new_method_return(msg); @@ -78,13 +80,13 @@ DBUS_TYPE_STRING, &folder, DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); obc_session_setpath(session, folder, async_cb, message, &err); if (err != NULL) { DBusMessage *reply; reply = g_dbus_create_error(message, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".Failed", "%s", err->message); g_error_free(err); return reply; @@ -95,39 +97,6 @@ return NULL; } -static void append_variant(DBusMessageIter *iter, int type, void *val) -{ - DBusMessageIter value; - char sig[2] = { type, '\0' }; - - dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, sig, &value); - - dbus_message_iter_append_basic(&value, type, val); - - dbus_message_iter_close_container(iter, &value); -} - -static void dict_append_entry(DBusMessageIter *dict, - const char *key, int type, void *val) -{ - DBusMessageIter entry; - - if (type == DBUS_TYPE_STRING) { - const char *str = *((const char **) val); - if (str == NULL) - return; - } - - dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, - NULL, &entry); - - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); - - append_variant(&entry, type, val); - - dbus_message_iter_close_container(dict, &entry); -} - static void xml_element(GMarkupParseContext *ctxt, const gchar *element, const gchar **names, @@ -147,7 +116,7 @@ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - dict_append_entry(&dict, "Type", DBUS_TYPE_STRING, &element); + obex_dbus_dict_append(&dict, "Type", DBUS_TYPE_STRING, &element); /* FIXME: User, Group, Other permission must be reviewed */ @@ -157,9 +126,11 @@ if (g_str_equal("Size", key) == TRUE) { guint64 size; size = g_ascii_strtoll(values[i], NULL, 10); - dict_append_entry(&dict, key, DBUS_TYPE_UINT64, &size); + obex_dbus_dict_append(&dict, key, DBUS_TYPE_UINT64, + &size); } else - dict_append_entry(&dict, key, DBUS_TYPE_STRING, &values[i]); + obex_dbus_dict_append(&dict, key, DBUS_TYPE_STRING, + &values[i]); } dbus_message_iter_close_container(iter, &dict); @@ -173,24 +144,6 @@ NULL }; -static void get_file_callback(struct obc_session *session, - struct obc_transfer *transfer, - GError *err, void *user_data) -{ - DBusMessage *msg = user_data; - DBusMessage *reply; - - if (err) - reply = g_dbus_create_error(msg, - "org.openobex.Error.Failed", - "%s", err->message); - else - reply = dbus_message_new_method_return(msg); - - g_dbus_send_message(conn, reply); - dbus_message_unref(msg); -} - static void list_folder_callback(struct obc_session *session, struct obc_transfer *transfer, GError *err, void *user_data) @@ -236,13 +189,13 @@ DBUS_TYPE_STRING, &folder, DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); obc_session_mkdir(session, folder, async_cb, message, &err); if (err != NULL) { DBusMessage *reply; reply = g_dbus_create_error(message, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".Failed", "%s", err->message); g_error_free(err); return reply; @@ -273,7 +226,7 @@ } fail: - reply = g_dbus_create_error(message, "org.openobex.Error.Failed", "%s", + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", err->message); g_error_free(err); return reply; @@ -294,20 +247,19 @@ DBUS_TYPE_STRING, &source_file, DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); transfer = obc_transfer_get(NULL, source_file, target_file, &err); if (transfer == NULL) goto fail; - if (obc_session_queue(session, transfer, get_file_callback, message, - &err)) { - dbus_message_ref(message); - return NULL; - } + if (!obc_session_queue(session, transfer, NULL, NULL, &err)) + goto fail; + + return obc_transfer_create_dbus_reply(transfer, message); fail: - reply = g_dbus_create_error(message, "org.openobex.Error.Failed", "%s", + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", err->message); g_error_free(err); return reply; @@ -328,7 +280,7 @@ DBUS_TYPE_STRING, &targetfile, DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", + ERROR_INTERFACE ".InvalidArguments", "Invalid arguments in method call"); transfer = obc_transfer_put(NULL, targetfile, sourcefile, NULL, 0, @@ -336,11 +288,13 @@ if (transfer == NULL) goto fail; - if (obc_session_queue(session, transfer, NULL, NULL, &err)) - return dbus_message_new_method_return(message); + if (!obc_session_queue(session, transfer, NULL, NULL, &err)) + goto fail; + + return obc_transfer_create_dbus_reply(transfer, message); fail: - reply = g_dbus_create_error(message, "org.openobex.Error.Failed", "%s", + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", err->message); g_error_free(err); return reply; @@ -359,14 +313,13 @@ DBUS_TYPE_STRING, &destname, DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); obc_session_copy(session, filename, destname, async_cb, message, &err); if (err != NULL) { DBusMessage *reply; - reply = g_dbus_create_error(message, - "org.openobex.Error.Failed", - "%s", err->message); + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", + "%s", err->message); g_error_free(err); return reply; } @@ -389,14 +342,13 @@ DBUS_TYPE_STRING, &destname, DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); obc_session_move(session, filename, destname, async_cb, message, &err); if (err != NULL) { DBusMessage *reply; - reply = g_dbus_create_error(message, - "org.openobex.Error.Failed", - "%s", err->message); + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", + "%s", err->message); g_error_free(err); return reply; } @@ -418,14 +370,13 @@ DBUS_TYPE_STRING, &file, DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); obc_session_delete(session, file, async_cb, message, &err); if (err != NULL) { DBusMessage *reply; - reply = g_dbus_create_error(message, - "org.openobex.Error.Failed", - "%s", err->message); + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", + "%s", err->message); g_error_free(err); return reply; } @@ -435,23 +386,29 @@ return NULL; } -static GDBusMethodTable ftp_methods[] = { - { "ChangeFolder", "s", "", change_folder, - G_DBUS_METHOD_FLAG_ASYNC }, - { "CreateFolder", "s", "", create_folder, - G_DBUS_METHOD_FLAG_ASYNC }, - { "ListFolder", "", "aa{sv}", list_folder, - G_DBUS_METHOD_FLAG_ASYNC }, - { "GetFile", "ss", "", get_file, - G_DBUS_METHOD_FLAG_ASYNC }, - { "PutFile", "ss", "", put_file, - G_DBUS_METHOD_FLAG_ASYNC }, - { "CopyFile", "ss", "", copy_file, - G_DBUS_METHOD_FLAG_ASYNC }, - { "MoveFile", "ss", "", move_file, - G_DBUS_METHOD_FLAG_ASYNC }, - { "Delete", "s", "", delete, - G_DBUS_METHOD_FLAG_ASYNC }, +static const GDBusMethodTable ftp_methods[] = { + { GDBUS_ASYNC_METHOD("ChangeFolder", + GDBUS_ARGS({ "folder", "s" }), NULL, change_folder) }, + { GDBUS_ASYNC_METHOD("CreateFolder", + GDBUS_ARGS({ "folder", "s" }), NULL, create_folder) }, + { GDBUS_ASYNC_METHOD("ListFolder", + NULL, GDBUS_ARGS({ "folderinfo", "aa{sv}" }), list_folder) }, + { GDBUS_METHOD("GetFile", + GDBUS_ARGS({ "targetfile", "s" }, { "sourcefile", "s" }), + GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }), + get_file) }, + { GDBUS_METHOD("PutFile", + GDBUS_ARGS({ "sourcefile", "s" }, { "targetfile", "s" }), + GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }), + put_file) }, + { GDBUS_ASYNC_METHOD("CopyFile", + GDBUS_ARGS({ "sourcefile", "s" }, { "targetfile", "s" }), NULL, + copy_file) }, + { GDBUS_ASYNC_METHOD("MoveFile", + GDBUS_ARGS({ "sourcefile", "s" }, { "targetfile", "s" }), NULL, + move_file) }, + { GDBUS_ASYNC_METHOD("Delete", + GDBUS_ARGS({ "file", "s" }), NULL, delete) }, { } }; diff -Nru obexd-0.46/client/manager.c obexd-0.48/client/manager.c --- obexd-0.46/client/manager.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/manager.c 2012-07-26 19:09:25.000000000 +0200 @@ -45,18 +45,15 @@ #include "sync.h" #include "map.h" -#define CLIENT_SERVICE "org.openobex.client" +#define CLIENT_SERVICE "org.bluez.obex.client" -#define CLIENT_INTERFACE "org.openobex.Client" -#define CLIENT_PATH "/" +#define CLIENT_INTERFACE "org.bluez.obex.Client" +#define ERROR_INTERFACE "org.bluez.obex.Error" +#define CLIENT_PATH "/" struct send_data { DBusConnection *connection; DBusMessage *message; - gchar *sender; - gchar *agent; - char *filename; - GPtrArray *files; }; static GSList *sessions = NULL; @@ -84,65 +81,32 @@ GError *err, void *user_data) { struct send_data *data = user_data; - unsigned int i; + const char *path; if (err != NULL) { DBusMessage *error = g_dbus_create_error(data->message, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".Failed", "%s", err->message); g_dbus_send_message(data->connection, error); shutdown_session(session); goto done; } - if (obc_session_get_target(session) != NULL) { - const char *path; - path = obc_session_register(session, unregister_session); + path = obc_session_register(session, unregister_session); - g_dbus_send_reply(data->connection, data->message, + g_dbus_send_reply(data->connection, data->message, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); - goto done; - } - - g_dbus_send_reply(data->connection, data->message, DBUS_TYPE_INVALID); - - obc_session_set_agent(session, data->sender, data->agent); - - for (i = 0; i < data->files->len; i++) { - const gchar *filename = g_ptr_array_index(data->files, i); - gchar *basename = g_path_get_basename(filename); - struct obc_transfer *transfer; - - transfer = obc_transfer_put(NULL, basename, filename, NULL, 0, - NULL); - - g_free(basename); - if (transfer == NULL) - break; - - if (!obc_session_queue(session, transfer, NULL, NULL, NULL)) - break; - } - - /* No need to keep a reference for SendFiles */ - sessions = g_slist_remove(sessions, session); - obc_session_unref(session); done: - if (data->files) - g_ptr_array_free(data->files, TRUE); dbus_message_unref(data->message); dbus_connection_unref(data->connection); - g_free(data->sender); - g_free(data->agent); g_free(data); } static int parse_device_dict(DBusMessageIter *iter, - const char **source, const char **dest, const char **target, - uint8_t *channel) + const char **source, const char **target, uint8_t *channel) { while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_DICT_ENTRY) { DBusMessageIter entry, value; @@ -158,8 +122,6 @@ case DBUS_TYPE_STRING: if (g_str_equal(key, "Source") == TRUE) dbus_message_iter_get_basic(&value, source); - else if (g_str_equal(key, "Destination") == TRUE) - dbus_message_iter_get_basic(&value, dest); else if (g_str_equal(key, "Target") == TRUE) dbus_message_iter_get_basic(&value, target); break; @@ -175,205 +137,6 @@ return 0; } -static DBusMessage *send_files(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - DBusMessageIter iter, array; - struct obc_session *session; - GPtrArray *files; - struct send_data *data; - const char *agent, *source = NULL, *dest = NULL, *target = NULL; - const char *sender; - uint8_t channel = 0; - - dbus_message_iter_init(message, &iter); - dbus_message_iter_recurse(&iter, &array); - - parse_device_dict(&array, &source, &dest, &target, &channel); - if (dest == NULL) - return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); - - dbus_message_iter_next(&iter); - dbus_message_iter_recurse(&iter, &array); - - files = g_ptr_array_new(); - if (files == NULL) - return g_dbus_create_error(message, - "org.openobex.Error.NoMemory", NULL); - - while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { - char *value; - - dbus_message_iter_get_basic(&array, &value); - g_ptr_array_add(files, value); - - dbus_message_iter_next(&array); - } - - dbus_message_iter_next(&iter); - dbus_message_iter_get_basic(&iter, &agent); - - if (files->len == 0) { - g_ptr_array_free(files, TRUE); - return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); - } - - sender = dbus_message_get_sender(message); - - data = g_try_malloc0(sizeof(*data)); - if (data == NULL) { - g_ptr_array_free(files, TRUE); - return g_dbus_create_error(message, - "org.openobex.Error.NoMemory", NULL); - } - - data->connection = dbus_connection_ref(connection); - data->message = dbus_message_ref(message); - data->sender = g_strdup(sender); - data->agent = g_strdup(agent); - data->files = files; - - session = obc_session_create(source, dest, "OPP", channel, sender, - create_callback, data); - if (session != NULL) { - sessions = g_slist_append(sessions, session); - return NULL; - } - - g_ptr_array_free(data->files, TRUE); - dbus_message_unref(data->message); - dbus_connection_unref(data->connection); - g_free(data->sender); - g_free(data->agent); - g_free(data); - - return g_dbus_create_error(message, "org.openobex.Error.Failed", NULL); -} - -static void pull_complete_callback(struct obc_session *session, - struct obc_transfer *transfer, - GError *err, void *user_data) -{ - struct send_data *data = user_data; - - if (err != NULL) { - DBusMessage *error = g_dbus_create_error(data->message, - "org.openobex.Error.Failed", - "%s", err->message); - g_dbus_send_message(data->connection, error); - goto done; - } - - g_dbus_send_reply(data->connection, data->message, DBUS_TYPE_INVALID); - -done: - shutdown_session(session); - dbus_message_unref(data->message); - dbus_connection_unref(data->connection); - g_free(data->filename); - g_free(data->sender); - g_free(data); -} - -static void pull_obc_session_callback(struct obc_session *session, - struct obc_transfer *transfer, - GError *err, void *user_data) -{ - struct send_data *data = user_data; - struct obc_transfer *pull; - DBusMessage *reply; - GError *gerr = NULL; - - if (err != NULL) { - reply = g_dbus_create_error(data->message, - "org.openobex.Error.Failed", - "%s", err->message); - goto fail; - } - - pull = obc_transfer_get("text/x-vcard", NULL, data->filename, &gerr); - - if (!obc_session_queue(session, pull, pull_complete_callback, data, - &gerr)) { - reply = g_dbus_create_error(data->message, - "org.openobex.Error.Failed", - "%s", gerr->message); - g_error_free(gerr); - goto fail; - } - - return; - -fail: - g_dbus_send_message(data->connection, reply); - shutdown_session(session); - dbus_message_unref(data->message); - dbus_connection_unref(data->connection); - g_free(data->filename); - g_free(data->sender); - g_free(data); -} - -static DBusMessage *pull_business_card(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - DBusMessageIter iter, dict; - struct obc_session *session; - struct send_data *data; - const char *source = NULL, *dest = NULL, *target = NULL; - const char *name = NULL; - uint8_t channel = 0; - - dbus_message_iter_init(message, &iter); - dbus_message_iter_recurse(&iter, &dict); - - parse_device_dict(&dict, &source, &dest, &target, &channel); - if (dest == NULL) - return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); - - dbus_message_iter_next(&iter); - - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) - return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); - - dbus_message_iter_get_basic(&iter, &name); - - data = g_try_malloc0(sizeof(*data)); - if (data == NULL) - return g_dbus_create_error(message, - "org.openobex.Error.NoMemory", NULL); - - data->connection = dbus_connection_ref(connection); - data->message = dbus_message_ref(message); - data->sender = g_strdup(dbus_message_get_sender(message)); - data->filename = g_strdup(name); - - session = obc_session_create(source, dest, "OPP", channel, data->sender, - pull_obc_session_callback, data); - if (session != NULL) { - sessions = g_slist_append(sessions, session); - return NULL; - } - - dbus_message_unref(data->message); - dbus_connection_unref(data->connection); - g_free(data->sender); - g_free(data->filename); - g_free(data); - - return g_dbus_create_error(message, "org.openobex.Error.Failed", NULL); -} - -static DBusMessage *exchange_business_cards(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - return g_dbus_create_error(message, "org.openobex.Error.Failed", NULL); -} - static struct obc_session *find_session(const char *path) { GSList *l; @@ -398,24 +161,35 @@ uint8_t channel = 0; dbus_message_iter_init(message, &iter); + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + + dbus_message_iter_get_basic(&iter, &dest); + dbus_message_iter_next(&iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + dbus_message_iter_recurse(&iter, &dict); - parse_device_dict(&dict, &source, &dest, &target, &channel); + parse_device_dict(&dict, &source, &target, &channel); if (dest == NULL || target == NULL) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); data = g_try_malloc0(sizeof(*data)); if (data == NULL) return g_dbus_create_error(message, - "org.openobex.Error.NoMemory", NULL); + ERROR_INTERFACE ".Error.NoMemory", NULL); data->connection = dbus_connection_ref(connection); data->message = dbus_message_ref(message); - data->sender = g_strdup(dbus_message_get_sender(message)); - session = obc_session_create(source, dest, target, channel, data->sender, - create_callback, data); + session = obc_session_create(source, dest, target, channel, + dbus_message_get_sender(message), + create_callback, data); if (session != NULL) { sessions = g_slist_append(sessions, session); return NULL; @@ -423,10 +197,9 @@ dbus_message_unref(data->message); dbus_connection_unref(data->connection); - g_free(data->sender); g_free(data); - return g_dbus_create_error(message, "org.openobex.Error.Failed", NULL); + return g_dbus_create_error(message, ERROR_INTERFACE ".Failed", NULL); } static DBusMessage *remove_session(DBusConnection *connection, @@ -439,17 +212,17 @@ DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); session = find_session(path); if (session == NULL) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); sender = dbus_message_get_sender(message); if (g_str_equal(sender, obc_session_get_owner(session)) == FALSE) return g_dbus_create_error(message, - "org.openobex.Error.NotAuthorized", + ERROR_INTERFACE ".NotAuthorized", "Not Authorized"); shutdown_session(session); @@ -457,143 +230,12 @@ return dbus_message_new_method_return(message); } -static void capabilities_complete_callback(struct obc_session *session, - struct obc_transfer *transfer, - GError *err, void *user_data) -{ - struct send_data *data = user_data; - char *contents; - size_t size; - int perr; - - if (err != NULL) { - DBusMessage *error = g_dbus_create_error(data->message, - "org.openobex.Error.Failed", - "%s", err->message); - g_dbus_send_message(data->connection, error); - goto done; - } - - perr = obc_transfer_get_contents(transfer, &contents, &size); - if (perr < 0) { - DBusMessage *error = g_dbus_create_error(data->message, - "org.openobex.Error.Failed", - "Error reading contents: %s", - strerror(-perr)); - g_dbus_send_message(data->connection, error); - goto done; - } - - g_dbus_send_reply(data->connection, data->message, - DBUS_TYPE_STRING, &contents, - DBUS_TYPE_INVALID); - g_free(contents); - -done: - - shutdown_session(session); - dbus_message_unref(data->message); - dbus_connection_unref(data->connection); - g_free(data->sender); - g_free(data); -} - -static void capability_obc_session_callback(struct obc_session *session, - struct obc_transfer *transfer, - GError *err, void *user_data) -{ - struct send_data *data = user_data; - struct obc_transfer *pull; - DBusMessage *reply; - GError *gerr = NULL; - - if (err != NULL) { - reply = g_dbus_create_error(data->message, - "org.openobex.Error.Failed", - "%s", err->message); - goto fail; - } - - pull = obc_transfer_get("x-obex/capability", NULL, data->filename, - &gerr); - - if (!obc_session_queue(session, pull, capabilities_complete_callback, - data, &gerr)) { - reply = g_dbus_create_error(data->message, - "org.openobex.Error.Failed", - "%s", gerr->message); - g_error_free(gerr); - goto fail; - } - - return; - -fail: - g_dbus_send_message(data->connection, reply); - shutdown_session(session); - dbus_message_unref(data->message); - dbus_connection_unref(data->connection); - g_free(data->sender); - g_free(data); -} - -static DBusMessage *get_capabilities(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - DBusMessageIter iter, dict; - struct obc_session *session; - struct send_data *data; - const char *source = NULL, *dest = NULL, *target = NULL; - uint8_t channel = 0; - - dbus_message_iter_init(message, &iter); - dbus_message_iter_recurse(&iter, &dict); - - parse_device_dict(&dict, &source, &dest, &target, &channel); - if (dest == NULL) - return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); - - data = g_try_malloc0(sizeof(*data)); - if (data == NULL) - return g_dbus_create_error(message, - "org.openobex.Error.NoMemory", NULL); - - data->connection = dbus_connection_ref(connection); - data->message = dbus_message_ref(message); - data->sender = g_strdup(dbus_message_get_sender(message)); - - if (!target) - target = "OPP"; - - session = obc_session_create(source, dest, target, channel, data->sender, - capability_obc_session_callback, data); - if (session != NULL) { - sessions = g_slist_append(sessions, session); - return NULL; - } - - dbus_message_unref(data->message); - dbus_connection_unref(data->connection); - g_free(data->sender); - g_free(data); - - return g_dbus_create_error(message, "org.openobex.Error.Failed", NULL); -} - -static GDBusMethodTable client_methods[] = { - { "SendFiles", "a{sv}aso", "", send_files, - G_DBUS_METHOD_FLAG_ASYNC }, - { "PullBusinessCard", "a{sv}s", "", pull_business_card, - G_DBUS_METHOD_FLAG_ASYNC }, - { "ExchangeBusinessCards", "a{sv}ss", "", exchange_business_cards, - G_DBUS_METHOD_FLAG_ASYNC }, - { "CreateSession", "a{sv}", "o", create_session, - G_DBUS_METHOD_FLAG_ASYNC }, - { "RemoveSession", "o", "", remove_session, - G_DBUS_METHOD_FLAG_ASYNC }, - { "GetCapabilities", "a{sv}", "s", get_capabilities, - G_DBUS_METHOD_FLAG_ASYNC }, +static const GDBusMethodTable client_methods[] = { + { GDBUS_ASYNC_METHOD("CreateSession", + GDBUS_ARGS({ "destination", "s" }, { "args", "a{sv}" }), + GDBUS_ARGS({ "session", "o" }), create_session) }, + { GDBUS_ASYNC_METHOD("RemoveSession", + GDBUS_ARGS({ "session", "o" }), NULL, remove_session) }, { } }; diff -Nru obexd-0.46/client/map.c obexd-0.48/client/map.c --- obexd-0.46/client/map.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/map.c 2012-11-30 08:59:13.000000000 +0100 @@ -26,10 +26,15 @@ #include #include +#include #include #include +#include + +#include "dbus.h" #include "log.h" +#include "map_ap.h" #include "map.h" #include "transfer.h" @@ -40,12 +45,75 @@ "\xBB\x58\x2B\x40\x42\x0C\x11\xDB\xB0\xDE\x08\x00\x20\x0C\x9A\x66" #define OBEX_MAS_UUID_LEN 16 -#define MAP_INTERFACE "org.openobex.MessageAccess" +#define MAP_INTERFACE "org.bluez.obex.MessageAccess" +#define MAP_MSG_INTERFACE "org.bluez.obex.Message" +#define ERROR_INTERFACE "org.bluez.obex.Error" #define MAS_UUID "00001132-0000-1000-8000-00805f9b34fb" +#define DEFAULT_COUNT 1024 +#define DEFAULT_OFFSET 0 + +#define CHARSET_UTF8 1 + +static const char * const filter_list[] = { + "subject", + "timestamp", + "sender", + "sender-address", + "recipient", + "recipient-address", + "type", + "size", + "status", + "text", + "attachment", + "priority", + "read", + "sent", + "protected", + "replyto", + NULL +}; + +#define FILTER_BIT_MAX 15 +#define FILTER_ALL 0xFF + +#define STATUS_READ 0 +#define STATUS_DELETE 1 +#define FILLER_BYTE 0x30 + struct map_data { struct obc_session *session; DBusMessage *msg; + GHashTable *messages; +}; + +#define MAP_MSG_FLAG_PRIORITY 0x01 +#define MAP_MSG_FLAG_READ 0x02 +#define MAP_MSG_FLAG_SENT 0x04 +#define MAP_MSG_FLAG_PROTECTED 0x08 + +struct map_msg { + struct map_data *data; + char *path; + char *handle; + char *subject; + char *timestamp; + char *sender; + char *sender_address; + char *replyto; + char *recipient; + char *recipient_address; + char *type; + uint64_t size; + char *status; + uint8_t flags; + DBusMessage *msg; +}; + +struct map_parser { + struct map_data *data; + DBusMessageIter *iter; }; static DBusConnection *conn = NULL; @@ -59,7 +127,7 @@ if (err != NULL) reply = g_dbus_create_error(map->msg, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".Failed", "%s", err->message); else reply = dbus_message_new_method_return(map->msg); @@ -78,14 +146,14 @@ if (dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &folder, DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", + ERROR_INTERFACE ".InvalidArguments", NULL); obc_session_setpath(map->session, folder, simple_cb, map, &err); if (err != NULL) { DBusMessage *reply; reply = g_dbus_create_error(message, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".Failed", "%s", err->message); g_error_free(err); return reply; @@ -96,19 +164,54 @@ return NULL; } -static void buffer_cb(struct obc_session *session, +static void folder_element(GMarkupParseContext *ctxt, const gchar *element, + const gchar **names, const gchar **values, + gpointer user_data, GError **gerr) +{ + DBusMessageIter dict, *iter = user_data; + const gchar *key; + gint i; + + if (strcasecmp("folder", element) != 0) + return; + + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + + for (i = 0, key = names[i]; key; key = names[++i]) { + if (strcasecmp("name", key) == 0) + obex_dbus_dict_append(&dict, "Name", DBUS_TYPE_STRING, + &values[i]); + } + + dbus_message_iter_close_container(iter, &dict); +} + +static const GMarkupParser folder_parser = { + folder_element, + NULL, + NULL, + NULL, + NULL +}; + +static void folder_listing_cb(struct obc_session *session, struct obc_transfer *transfer, GError *err, void *user_data) { struct map_data *map = user_data; + GMarkupParseContext *ctxt; DBusMessage *reply; + DBusMessageIter iter, array; char *contents; size_t size; int perr; if (err != NULL) { reply = g_dbus_create_error(map->msg, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".Failed", "%s", err->message); goto done; } @@ -116,94 +219,1123 @@ perr = obc_transfer_get_contents(transfer, &contents, &size); if (perr < 0) { reply = g_dbus_create_error(map->msg, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".Failed", "Error reading contents: %s", strerror(-perr)); goto done; } - reply = g_dbus_create_reply(map->msg, DBUS_TYPE_STRING, &contents, - DBUS_TYPE_INVALID); - + reply = dbus_message_new_method_return(map->msg); + if (reply == NULL) + return; + + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array); + ctxt = g_markup_parse_context_new(&folder_parser, 0, &array, NULL); + g_markup_parse_context_parse(ctxt, contents, size, NULL); + g_markup_parse_context_free(ctxt); + dbus_message_iter_close_container(&iter, &array); g_free(contents); + done: g_dbus_send_message(conn, reply); dbus_message_unref(map->msg); } -static DBusMessage *map_get_folder_listing(DBusConnection *connection, - DBusMessage *message, void *user_data) +static DBusMessage *get_folder_listing(struct map_data *map, + DBusMessage *message, + GObexApparam *apparam) { - struct map_data *map = user_data; struct obc_transfer *transfer; GError *err = NULL; DBusMessage *reply; transfer = obc_transfer_get("x-obex/folder-listing", NULL, NULL, &err); - if (transfer == NULL) + if (transfer == NULL) { + g_obex_apparam_free(apparam); goto fail; + } + + obc_transfer_set_apparam(transfer, apparam); - if (obc_session_queue(map->session, transfer, buffer_cb, map, &err)) { + if (obc_session_queue(map->session, transfer, folder_listing_cb, map, + &err)) { map->msg = dbus_message_ref(message); return NULL; } fail: - reply = g_dbus_create_error(message, "org.openobex.Error.Failed", "%s", + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", err->message); g_error_free(err); return reply; } -static DBusMessage *map_get_message_listing(DBusConnection *connection, +static GObexApparam *parse_offset(GObexApparam *apparam, DBusMessageIter *iter) +{ + guint16 num; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16) + return NULL; + + dbus_message_iter_get_basic(iter, &num); + + return g_obex_apparam_set_uint16(apparam, MAP_AP_STARTOFFSET, num); +} + +static GObexApparam *parse_max_count(GObexApparam *apparam, + DBusMessageIter *iter) +{ + guint16 num; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16) + return NULL; + + dbus_message_iter_get_basic(iter, &num); + + return g_obex_apparam_set_uint16(apparam, MAP_AP_MAXLISTCOUNT, num); +} + +static GObexApparam *parse_folder_filters(GObexApparam *apparam, + DBusMessageIter *iter) +{ + DBusMessageIter array; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return NULL; + + dbus_message_iter_recurse(iter, &array); + + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) { + const char *key; + DBusMessageIter value, entry; + + dbus_message_iter_recurse(&array, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + + if (strcasecmp(key, "Offset") == 0) { + if (parse_offset(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "MaxCount") == 0) { + if (parse_max_count(apparam, &value) == NULL) + return NULL; + } + + dbus_message_iter_next(&array); + } + + return apparam; +} + +static DBusMessage *map_list_folders(DBusConnection *connection, DBusMessage *message, void *user_data) { struct map_data *map = user_data; + GObexApparam *apparam; + DBusMessageIter args; + + dbus_message_iter_init(message, &args); + + apparam = g_obex_apparam_set_uint16(NULL, MAP_AP_MAXLISTCOUNT, + DEFAULT_COUNT); + apparam = g_obex_apparam_set_uint16(apparam, MAP_AP_STARTOFFSET, + DEFAULT_OFFSET); + + if (parse_folder_filters(apparam, &args) == NULL) { + g_obex_apparam_free(apparam); + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + } + + return get_folder_listing(map, message, apparam); +} + +static void map_msg_free(void *data) +{ + struct map_msg *msg = data; + + g_free(msg->path); + g_free(msg->subject); + g_free(msg->handle); + g_free(msg->timestamp); + g_free(msg->sender); + g_free(msg->sender_address); + g_free(msg->replyto); + g_free(msg->recipient); + g_free(msg->recipient_address); + g_free(msg->type); + g_free(msg->status); + g_free(msg); +} + +static DBusMessage *map_msg_get(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct map_msg *msg = user_data; struct obc_transfer *transfer; - const char *folder; - DBusMessageIter msg_iter; + const char *target_file; + gboolean attachment; GError *err = NULL; DBusMessage *reply; + GObexApparam *apparam; + + if (dbus_message_get_args(message, NULL, + DBUS_TYPE_STRING, &target_file, + DBUS_TYPE_BOOLEAN, &attachment, + DBUS_TYPE_INVALID) == FALSE) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); - dbus_message_iter_init(message, &msg_iter); + transfer = obc_transfer_get("x-bt/message", msg->handle, target_file, + &err); + if (transfer == NULL) + goto fail; + + apparam = g_obex_apparam_set_uint8(NULL, MAP_AP_ATTACHMENT, + attachment); + apparam = g_obex_apparam_set_uint8(apparam, MAP_AP_CHARSET, + CHARSET_UTF8); + + obc_transfer_set_apparam(transfer, apparam); + + if (!obc_session_queue(msg->data->session, transfer, NULL, NULL, &err)) + goto fail; + + return obc_transfer_create_dbus_reply(transfer, message); + +fail: + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", + err->message); + g_error_free(err); + return reply; +} - if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_STRING) +static void set_message_status_cb(struct obc_session *session, + struct obc_transfer *transfer, + GError *err, void *user_data) +{ + struct map_msg *msg = user_data; + DBusMessage *reply; + + if (err != NULL) { + reply = g_dbus_create_error(msg->msg, + ERROR_INTERFACE ".Failed", + "%s", err->message); + goto done; + } + + reply = dbus_message_new_method_return(msg->msg); + if (reply == NULL) { + reply = g_dbus_create_error(msg->msg, + ERROR_INTERFACE ".Failed", + "%s", err->message); + } + +done: + g_dbus_send_message(conn, reply); + dbus_message_unref(msg->msg); + msg->msg = NULL; +} + +static DBusMessage *map_msg_set_property(DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + struct map_msg *msg = user_data; + struct obc_transfer *transfer; + char *property; + gboolean status; + GError *err = NULL; + DBusMessage *reply; + GObexApparam *apparam; + char contents[2]; + int op; + DBusMessageIter args, variant; + + dbus_message_iter_init(message, &args); + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + + dbus_message_iter_get_basic(&args, &property); + dbus_message_iter_next(&args); + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_VARIANT) return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); - dbus_message_iter_get_basic(&msg_iter, &folder); + dbus_message_iter_recurse(&args, &variant); + if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_BOOLEAN) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); - transfer = obc_transfer_get("x-bt/MAP-msg-listing", folder, NULL, &err); + dbus_message_iter_get_basic(&variant, &status); + + /* MAP supports modifying only these two properties. */ + if (property && strcasecmp(property, "Read") == 0) { + op = STATUS_READ; + if (status) + msg->flags |= MAP_MSG_FLAG_READ; + else + msg->flags &= ~MAP_MSG_FLAG_READ; + } else if (property && strcasecmp(property, "Deleted") == 0) + op = STATUS_DELETE; + else { + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + } + + contents[0] = FILLER_BYTE; + contents[1] = '\0'; + + transfer = obc_transfer_put("x-bt/messageStatus", msg->handle, NULL, + contents, + sizeof(contents), &err); if (transfer == NULL) goto fail; - if (obc_session_queue(map->session, transfer, buffer_cb, map, &err)) { + apparam = g_obex_apparam_set_uint8(NULL, MAP_AP_STATUSINDICATOR, + op); + apparam = g_obex_apparam_set_uint8(apparam, MAP_AP_STATUSVALUE, + status); + obc_transfer_set_apparam(transfer, apparam); + + if (!obc_session_queue(msg->data->session, transfer, + set_message_status_cb, msg, &err)) + goto fail; + + msg->msg = dbus_message_ref(message); + return NULL; + +fail: + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", + err->message); + g_error_free(err); + return reply; +} + +static DBusMessage *map_msg_get_properties(DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + struct map_msg *msg = user_data; + GError *err = NULL; + DBusMessage *reply; + DBusMessageIter iter, data_array; + gboolean flag; + + reply = dbus_message_new_method_return(message); + if (reply == NULL) { + reply = g_dbus_create_error(message, + ERROR_INTERFACE ".Failed", + NULL); + goto done; + } + + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &data_array); + + + obex_dbus_dict_append(&data_array, "Subject", + DBUS_TYPE_STRING, &msg->subject); + obex_dbus_dict_append(&data_array, "Timestamp", + DBUS_TYPE_STRING, &msg->timestamp); + obex_dbus_dict_append(&data_array, "Sender", + DBUS_TYPE_STRING, &msg->sender); + obex_dbus_dict_append(&data_array, "SenderAddress", + DBUS_TYPE_STRING, &msg->sender_address); + obex_dbus_dict_append(&data_array, "ReplyTo", + DBUS_TYPE_STRING, &msg->replyto); + obex_dbus_dict_append(&data_array, "Recipient", + DBUS_TYPE_STRING, &msg->recipient); + obex_dbus_dict_append(&data_array, "RecipientAddress", + DBUS_TYPE_STRING, &msg->recipient_address); + obex_dbus_dict_append(&data_array, "Type", + DBUS_TYPE_STRING, &msg->type); + obex_dbus_dict_append(&data_array, "Status", + DBUS_TYPE_STRING, &msg->status); + obex_dbus_dict_append(&data_array, "Size", + DBUS_TYPE_UINT64, &msg->size); + + flag = (msg->flags & MAP_MSG_FLAG_PRIORITY) != 0; + obex_dbus_dict_append(&data_array, "Priority", + DBUS_TYPE_BOOLEAN, &flag); + + flag = (msg->flags & MAP_MSG_FLAG_READ) != 0; + obex_dbus_dict_append(&data_array, "Read", + DBUS_TYPE_BOOLEAN, &flag); + + flag = (msg->flags & MAP_MSG_FLAG_SENT) != 0; + obex_dbus_dict_append(&data_array, "Sent", + DBUS_TYPE_BOOLEAN, &flag); + + flag = (msg->flags & MAP_MSG_FLAG_PROTECTED) != 0; + obex_dbus_dict_append(&data_array, "Protected", + DBUS_TYPE_BOOLEAN, &flag); + + dbus_message_iter_close_container(&iter, &data_array); + + +done: + if (err) + g_error_free(err); + + return reply; +} + +static const GDBusMethodTable map_msg_methods[] = { + { GDBUS_METHOD("Get", + GDBUS_ARGS({ "targetfile", "s" }, + { "attachment", "b" }), + GDBUS_ARGS({ "transfer", "o" }, + { "properties", "a{sv}" }), + map_msg_get) }, + { GDBUS_METHOD("GetProperties", + NULL, + GDBUS_ARGS({ "properties", "a{sv}" }), + map_msg_get_properties) }, + { GDBUS_ASYNC_METHOD("SetProperty", + GDBUS_ARGS({ "property", "sv" }), NULL, + map_msg_set_property) }, + { } +}; + +static struct map_msg *map_msg_create(struct map_data *data, const char *handle) +{ + struct map_msg *msg; + + msg = g_new0(struct map_msg, 1); + msg->data = data; + msg->path = g_strdup_printf("%s/message%s", + obc_session_get_path(data->session), + handle); + + if (!g_dbus_register_interface(conn, msg->path, MAP_MSG_INTERFACE, + map_msg_methods, NULL, NULL, + msg, map_msg_free)) { + map_msg_free(msg); + return NULL; + } + + msg->handle = g_strdup(handle); + g_hash_table_insert(data->messages, msg->handle, msg); + + return msg; +} + +static void parse_subject(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + g_free(msg->subject); + msg->subject = g_strdup(value); + obex_dbus_dict_append(iter, "Subject", DBUS_TYPE_STRING, &value); +} + +static void parse_datetime(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + g_free(msg->timestamp); + msg->timestamp = g_strdup(value); + obex_dbus_dict_append(iter, "Timestamp", DBUS_TYPE_STRING, &value); +} + +static void parse_sender(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + g_free(msg->sender); + msg->sender = g_strdup(value); + obex_dbus_dict_append(iter, "Sender", DBUS_TYPE_STRING, &value); +} + +static void parse_sender_address(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + g_free(msg->sender_address); + msg->sender_address = g_strdup(value); + obex_dbus_dict_append(iter, "SenderAddress", DBUS_TYPE_STRING, + &value); +} + +static void parse_replyto(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + g_free(msg->replyto); + msg->replyto = g_strdup(value); + obex_dbus_dict_append(iter, "ReplyTo", DBUS_TYPE_STRING, &value); +} + +static void parse_recipient(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + g_free(msg->recipient); + msg->recipient = g_strdup(value); + obex_dbus_dict_append(iter, "Recipient", DBUS_TYPE_STRING, &value); +} + +static void parse_recipient_address(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + g_free(msg->recipient_address); + msg->recipient_address = g_strdup(value); + obex_dbus_dict_append(iter, "RecipientAddress", DBUS_TYPE_STRING, + &value); +} + +static void parse_type(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + g_free(msg->type); + msg->type = g_strdup(value); + obex_dbus_dict_append(iter, "Type", DBUS_TYPE_STRING, &value); +} + +static void parse_status(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + g_free(msg->status); + msg->status = g_strdup(value); + obex_dbus_dict_append(iter, "Status", DBUS_TYPE_STRING, &value); +} + +static void parse_size(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + msg->size = g_ascii_strtoll(value, NULL, 10); + obex_dbus_dict_append(iter, "Size", DBUS_TYPE_UINT64, &msg->size); +} + +static void parse_priority(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + gboolean flag = strcasecmp(value, "no") != 0; + + if (flag) + msg->flags |= MAP_MSG_FLAG_PRIORITY; + else + msg->flags &= ~MAP_MSG_FLAG_PRIORITY; + + obex_dbus_dict_append(iter, "Priority", DBUS_TYPE_BOOLEAN, &flag); +} + +static void parse_read(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + gboolean flag = strcasecmp(value, "no") != 0; + + if (flag) + msg->flags |= MAP_MSG_FLAG_READ; + else + msg->flags &= ~MAP_MSG_FLAG_READ; + + obex_dbus_dict_append(iter, "Read", DBUS_TYPE_BOOLEAN, &flag); +} + +static void parse_sent(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + gboolean flag = strcasecmp(value, "no") != 0; + + if (flag) + msg->flags |= MAP_MSG_FLAG_SENT; + else + msg->flags &= ~MAP_MSG_FLAG_SENT; + + obex_dbus_dict_append(iter, "Sent", DBUS_TYPE_BOOLEAN, &flag); +} + +static void parse_protected(struct map_msg *msg, const char *value, + DBusMessageIter *iter) +{ + gboolean flag = strcasecmp(value, "no") != 0; + + if (flag) + msg->flags |= MAP_MSG_FLAG_PROTECTED; + else + msg->flags &= ~MAP_MSG_FLAG_PROTECTED; + + obex_dbus_dict_append(iter, "Protected", DBUS_TYPE_BOOLEAN, &flag); +} + +static struct map_msg_parser { + const char *name; + void (*func) (struct map_msg *msg, const char *value, + DBusMessageIter *iter); +} msg_parsers[] = { + { "subject", parse_subject }, + { "datetime", parse_datetime }, + { "sender_name", parse_sender }, + { "sender_addressing", parse_sender_address }, + { "replyto_addressing", parse_replyto }, + { "recipient_name", parse_recipient }, + { "recipient_addressing", parse_recipient_address }, + { "type", parse_type }, + { "reception_status", parse_status }, + { "size", parse_size }, + { "priority", parse_priority }, + { "read", parse_read }, + { "sent", parse_sent }, + { "protected", parse_protected }, + { } +}; + +static void msg_element(GMarkupParseContext *ctxt, const gchar *element, + const gchar **names, const gchar **values, + gpointer user_data, GError **gerr) +{ + struct map_parser *parser = user_data; + struct map_data *data = parser->data; + DBusMessageIter entry, dict, *iter = parser->iter; + struct map_msg *msg; + const gchar *key; + gint i; + + if (strcasecmp("msg", element) != 0) + return; + + for (i = 0, key = names[i]; key; key = names[++i]) { + if (strcasecmp(key, "handle") == 0) + break; + } + + msg = g_hash_table_lookup(data->messages, values[i]); + if (msg == NULL) { + msg = map_msg_create(data, values[i]); + if (msg == NULL) + return; + } + + dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL, + &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH, + &msg->path); + + dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &dict); + + for (i = 0, key = names[i]; key; key = names[++i]) { + struct map_msg_parser *parser; + + for (parser = msg_parsers; parser && parser->name; parser++) { + if (strcasecmp(key, parser->name) == 0) { + parser->func(msg, values[i], &dict); + break; + } + } + } + + dbus_message_iter_close_container(&entry, &dict); + dbus_message_iter_close_container(iter, &entry); +} + +static const GMarkupParser msg_parser = { + msg_element, + NULL, + NULL, + NULL, + NULL +}; + +static void message_listing_cb(struct obc_session *session, + struct obc_transfer *transfer, + GError *err, void *user_data) +{ + struct map_data *map = user_data; + struct map_parser *parser; + GMarkupParseContext *ctxt; + DBusMessage *reply; + DBusMessageIter iter, array; + char *contents; + size_t size; + int perr; + + if (err != NULL) { + reply = g_dbus_create_error(map->msg, + ERROR_INTERFACE ".Failed", + "%s", err->message); + goto done; + } + + perr = obc_transfer_get_contents(transfer, &contents, &size); + if (perr < 0) { + reply = g_dbus_create_error(map->msg, + ERROR_INTERFACE ".Failed", + "Error reading contents: %s", + strerror(-perr)); + goto done; + } + + reply = dbus_message_new_method_return(map->msg); + if (reply == NULL) + return; + + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_OBJECT_PATH_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &array); + + parser = g_new(struct map_parser, 1); + parser->data = map; + parser->iter = &array; + + ctxt = g_markup_parse_context_new(&msg_parser, 0, parser, NULL); + g_markup_parse_context_parse(ctxt, contents, size, NULL); + g_markup_parse_context_free(ctxt); + dbus_message_iter_close_container(&iter, &array); + g_free(contents); + g_free(parser); + +done: + g_dbus_send_message(conn, reply); + dbus_message_unref(map->msg); +} + +static DBusMessage *get_message_listing(struct map_data *map, + DBusMessage *message, + const char *folder, + GObexApparam *apparam) +{ + struct obc_transfer *transfer; + GError *err = NULL; + DBusMessage *reply; + + transfer = obc_transfer_get("x-bt/MAP-msg-listing", folder, NULL, &err); + if (transfer == NULL) { + g_obex_apparam_free(apparam); + goto fail; + } + + obc_transfer_set_apparam(transfer, apparam); + + if (obc_session_queue(map->session, transfer, message_listing_cb, map, + &err)) { map->msg = dbus_message_ref(message); return NULL; } fail: - reply = g_dbus_create_error(message, "org.openobex.Error.Failed", "%s", + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", err->message); g_error_free(err); return reply; } -static GDBusMethodTable map_methods[] = { - { "SetFolder", "s", "", map_setpath, - G_DBUS_METHOD_FLAG_ASYNC }, - { "GetFolderListing", "a{ss}", "s", map_get_folder_listing, - G_DBUS_METHOD_FLAG_ASYNC }, - { "GetMessageListing", "sa{ss}", "s", map_get_message_listing, - G_DBUS_METHOD_FLAG_ASYNC }, +static uint64_t get_filter_mask(const char *filterstr) +{ + int i; + + if (!filterstr) + return 0; + + if (!g_ascii_strcasecmp(filterstr, "ALL")) + return FILTER_ALL; + + for (i = 0; filter_list[i] != NULL; i++) + if (!g_ascii_strcasecmp(filterstr, filter_list[i])) + return 1ULL << i; + + return 0; +} + +static int set_field(guint32 *filter, const char *filterstr) +{ + guint64 mask; + + mask = get_filter_mask(filterstr); + + if (mask == 0) + return -EINVAL; + + *filter |= mask; + return 0; +} + +static GObexApparam *parse_fields(GObexApparam *apparam, DBusMessageIter *iter) +{ + DBusMessageIter array; + guint32 filter = 0; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return NULL; + + dbus_message_iter_recurse(iter, &array); + + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { + const char *string; + + dbus_message_iter_get_basic(&array, &string); + + if (set_field(&filter, string) < 0) + return NULL; + + dbus_message_iter_next(&array); + } + + return g_obex_apparam_set_uint32(apparam, MAP_AP_PARAMETERMASK, + filter); +} + +static GObexApparam *parse_filter_type(GObexApparam *apparam, + DBusMessageIter *iter) +{ + DBusMessageIter array; + guint8 types = 0; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return NULL; + + dbus_message_iter_recurse(iter, &array); + + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { + const char *string; + + dbus_message_iter_get_basic(&array, &string); + + if (!g_ascii_strcasecmp(string, "sms")) + types |= 0x03; /* SMS_GSM and SMS_CDMA */ + else if (!g_ascii_strcasecmp(string, "email")) + types |= 0x04; /* EMAIL */ + else if (!g_ascii_strcasecmp(string, "mms")) + types |= 0x08; /* MMS */ + else + return NULL; + } + + return g_obex_apparam_set_uint8(apparam, MAP_AP_FILTERMESSAGETYPE, + types); +} + +static GObexApparam *parse_period_begin(GObexApparam *apparam, + DBusMessageIter *iter) +{ + const char *string; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) + return NULL; + + dbus_message_iter_get_basic(iter, &string); + + return g_obex_apparam_set_string(apparam, MAP_AP_FILTERPERIODBEGIN, + string); +} + +static GObexApparam *parse_period_end(GObexApparam *apparam, + DBusMessageIter *iter) +{ + const char *string; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) + return NULL; + + dbus_message_iter_get_basic(iter, &string); + + return g_obex_apparam_set_string(apparam, MAP_AP_FILTERPERIODEND, + string); +} + +static GObexApparam *parse_filter_read(GObexApparam *apparam, + DBusMessageIter *iter) +{ + guint8 status = 0; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN) + return NULL; + + dbus_message_iter_get_basic(iter, &status); + + status = (status) ? 0x01 : 0x02; + + return g_obex_apparam_set_uint8(apparam, MAP_AP_FILTERREADSTATUS, + status); +} + +static GObexApparam *parse_filter_recipient(GObexApparam *apparam, + DBusMessageIter *iter) +{ + const char *string; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) + return NULL; + + dbus_message_iter_get_basic(iter, &string); + + return g_obex_apparam_set_string(apparam, MAP_AP_FILTERRECIPIENT, + string); +} + +static GObexApparam *parse_filter_sender(GObexApparam *apparam, + DBusMessageIter *iter) +{ + const char *string; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) + return NULL; + + dbus_message_iter_get_basic(iter, &string); + + return g_obex_apparam_set_string(apparam, MAP_AP_FILTERORIGINATOR, + string); +} + +static GObexApparam *parse_filter_priority(GObexApparam *apparam, + DBusMessageIter *iter) +{ + guint8 priority; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_BOOLEAN) + return NULL; + + dbus_message_iter_get_basic(iter, &priority); + + priority = (priority) ? 0x01 : 0x02; + + return g_obex_apparam_set_uint8(apparam, MAP_AP_FILTERPRIORITY, + priority); +} + +static GObexApparam *parse_message_filters(GObexApparam *apparam, + DBusMessageIter *iter) +{ + DBusMessageIter array; + + DBG(""); + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return NULL; + + dbus_message_iter_recurse(iter, &array); + + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) { + const char *key; + DBusMessageIter value, entry; + + dbus_message_iter_recurse(&array, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + + if (strcasecmp(key, "Offset") == 0) { + if (parse_offset(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "MaxCount") == 0) { + if (parse_max_count(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Fields") == 0) { + if (parse_fields(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Types") == 0) { + if (parse_filter_type(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "PeriodBegin") == 0) { + if (parse_period_begin(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "PeriodEnd") == 0) { + if (parse_period_end(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Read") == 0) { + if (parse_filter_read(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Recipient") == 0) { + if (parse_filter_recipient(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Sender") == 0) { + if (parse_filter_sender(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Priority") == 0) { + if (parse_filter_priority(apparam, &value) == NULL) + return NULL; + } + + dbus_message_iter_next(&array); + } + + return apparam; +} + +static DBusMessage *map_list_messages(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct map_data *map = user_data; + const char *folder; + GObexApparam *apparam; + DBusMessageIter args; + + dbus_message_iter_init(message, &args); + + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + + dbus_message_iter_get_basic(&args, &folder); + + apparam = g_obex_apparam_set_uint16(NULL, MAP_AP_MAXLISTCOUNT, + DEFAULT_COUNT); + apparam = g_obex_apparam_set_uint16(apparam, MAP_AP_STARTOFFSET, + DEFAULT_OFFSET); + + dbus_message_iter_next(&args); + + if (parse_message_filters(apparam, &args) == NULL) { + g_obex_apparam_free(apparam); + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + } + + return get_message_listing(map, message, folder, apparam); +} + +static gchar **get_filter_strs(uint64_t filter, gint *size) +{ + gchar **list, **item; + gint i; + + list = g_malloc0(sizeof(gchar **) * (FILTER_BIT_MAX + 2)); + + item = list; + + for (i = 0; filter_list[i] != NULL; i++) + if (filter & (1ULL << i)) + *(item++) = g_strdup(filter_list[i]); + + *item = NULL; + *size = item - list; + return list; +} + +static DBusMessage *map_list_filter_fields(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + gchar **filters = NULL; + gint size; + DBusMessage *reply; + + filters = get_filter_strs(FILTER_ALL, &size); + reply = dbus_message_new_method_return(message); + dbus_message_append_args(reply, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING, &filters, size, + DBUS_TYPE_INVALID); + + g_strfreev(filters); + return reply; +} + +static void update_inbox_cb(struct obc_session *session, + struct obc_transfer *transfer, + GError *err, void *user_data) +{ + struct map_data *map = user_data; + DBusMessage *reply; + + if (err != NULL) { + reply = g_dbus_create_error(map->msg, + ERROR_INTERFACE ".Failed", + "%s", err->message); + goto done; + } + + reply = dbus_message_new_method_return(map->msg); + +done: + g_dbus_send_message(conn, reply); + dbus_message_unref(map->msg); +} + +static DBusMessage *map_update_inbox(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct map_data *map = user_data; + DBusMessage *reply; + char contents[2]; + struct obc_transfer *transfer; + GError *err = NULL; + + contents[0] = FILLER_BYTE; + contents[1] = '\0'; + + transfer = obc_transfer_put("x-bt/MAP-messageUpdate", NULL, NULL, + contents, sizeof(contents), + &err); + if (transfer == NULL) + goto fail; + + if (!obc_session_queue(map->session, transfer, update_inbox_cb, + map, &err)) + goto fail; + + map->msg = dbus_message_ref(message); + + return NULL; + +fail: + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", + err->message); + g_error_free(err); + return reply; +} + +static const GDBusMethodTable map_methods[] = { + { GDBUS_ASYNC_METHOD("SetFolder", + GDBUS_ARGS({ "name", "s" }), NULL, + map_setpath) }, + { GDBUS_ASYNC_METHOD("ListFolders", + GDBUS_ARGS({ "filters", "a{sv}" }), + GDBUS_ARGS({ "content", "aa{sv}" }), + map_list_folders) }, + { GDBUS_ASYNC_METHOD("ListMessages", + GDBUS_ARGS({ "folder", "s" }, { "filter", "a{sv}" }), + GDBUS_ARGS({ "messages", "a{oa{sv}}" }), + map_list_messages) }, + { GDBUS_METHOD("ListFilterFields", + NULL, + GDBUS_ARGS({ "fields", "as" }), + map_list_filter_fields) }, + { GDBUS_ASYNC_METHOD("UpdateInbox", + NULL, + NULL, + map_update_inbox) }, { } }; +static void map_msg_remove(void *data) +{ + struct map_msg *msg = data; + char *path; + + path = msg->path; + msg->path = NULL; + g_dbus_unregister_interface(conn, path, MAP_MSG_INTERFACE); + g_free(path); +} + static void map_free(void *data) { struct map_data *map = data; obc_session_unref(map->session); + g_hash_table_unref(map->messages); g_free(map); } @@ -221,6 +1353,8 @@ return -ENOMEM; map->session = obc_session_ref(session); + map->messages = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, + map_msg_remove); if (!g_dbus_register_interface(conn, path, MAP_INTERFACE, map_methods, NULL, NULL, map, map_free)) { diff -Nru obexd-0.46/client/obex-client.service.in obexd-0.48/client/obex-client.service.in --- obexd-0.46/client/obex-client.service.in 2008-10-04 15:11:13.000000000 +0200 +++ obexd-0.48/client/obex-client.service.in 2012-07-26 19:09:25.000000000 +0200 @@ -1,3 +1,3 @@ [D-BUS Service] -Name=org.openobex.client +Name=org.bluez.obex.client Exec=@libexecdir@/obex-client diff -Nru obexd-0.46/client/opp.c obexd-0.48/client/opp.c --- obexd-0.46/client/opp.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/opp.c 2012-07-26 19:09:25.000000000 +0200 @@ -25,6 +25,7 @@ #include #endif +#include #include #include "log.h" @@ -35,22 +36,179 @@ #include "opp.h" #define OPP_UUID "00001105-0000-1000-8000-00805f9b34fb" +#define OPP_INTERFACE "org.bluez.obex.ObjectPush" +#define ERROR_INTERFACE "org.bluez.obex.Error" + +struct opp_data { + struct obc_session *session; +}; + +static DBusConnection *conn = NULL; + +static DBusMessage *opp_send_file(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct opp_data *opp = user_data; + struct obc_transfer *transfer; + DBusMessage *reply; + char *filename; + char *basename; + GError *err = NULL; + + if (dbus_message_get_args(message, NULL, + DBUS_TYPE_STRING, &filename, + DBUS_TYPE_INVALID) == FALSE) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + + basename = g_path_get_basename(filename); + + transfer = obc_transfer_put(NULL, basename, filename, NULL, 0, &err); + + g_free(basename); + + if (transfer == NULL) + goto fail; + + if (!obc_session_queue(opp->session, transfer, NULL, NULL, &err)) + goto fail; + + return obc_transfer_create_dbus_reply(transfer, message); + +fail: + reply = g_dbus_create_error(message, + ERROR_INTERFACE ".Failed", "%s", err->message); + g_error_free(err); + return reply; +} + +static DBusMessage *opp_pull_business_card(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct opp_data *opp = user_data; + struct obc_transfer *pull; + DBusMessage *reply; + const char *filename = NULL; + GError *err = NULL; + + if (dbus_message_get_args(message, NULL, + DBUS_TYPE_STRING, &filename, + DBUS_TYPE_INVALID) == FALSE) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + + pull = obc_transfer_get("text/x-vcard", NULL, filename, &err); + if (pull == NULL) + goto fail; + + if (!obc_session_queue(opp->session, pull, NULL, NULL, &err)) + goto fail; + + return obc_transfer_create_dbus_reply(pull, message); + +fail: + reply = g_dbus_create_error(message, + ERROR_INTERFACE ".Failed", "%s", err->message); + g_error_free(err); + return reply; +} + +static DBusMessage *opp_exchange_business_cards(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + return g_dbus_create_error(message, ERROR_INTERFACE ".Failed", NULL); +} + +static const GDBusMethodTable opp_methods[] = { + { GDBUS_METHOD("SendFile", + GDBUS_ARGS({ "sourcefile", "s" }), + GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }), + opp_send_file) }, + { GDBUS_METHOD("PullBusinessCard", + GDBUS_ARGS({ "targetfile", "s" }), + GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }), + opp_pull_business_card) }, + { GDBUS_METHOD("ExchangeBusinessCards", + GDBUS_ARGS({ "clientfile", "s" }, { "targetfile", "s" }), + GDBUS_ARGS({ "transfer", "o" }, { "properties", "a{sv}" }), + opp_exchange_business_cards) }, + { } +}; + +static void opp_free(void *data) +{ + struct opp_data *opp = data; + + obc_session_unref(opp->session); + g_free(opp); +} + +static int opp_probe(struct obc_session *session) +{ + struct opp_data *opp; + const char *path; + + path = obc_session_get_path(session); + + DBG("%s", path); + + opp = g_try_new0(struct opp_data, 1); + if (!opp) + return -ENOMEM; + + opp->session = obc_session_ref(session); + + if (!g_dbus_register_interface(conn, path, OPP_INTERFACE, opp_methods, + NULL, NULL, opp, opp_free)) { + opp_free(opp); + return -ENOMEM; + } + + return 0; +} + +static void opp_remove(struct obc_session *session) +{ + const char *path = obc_session_get_path(session); + + DBG("%s", path); + + g_dbus_unregister_interface(conn, path, OPP_INTERFACE); +} static struct obc_driver opp = { .service = "OPP", .uuid = OPP_UUID, + .probe = opp_probe, + .remove = opp_remove }; int opp_init(void) { + int err; + DBG(""); - return obc_driver_register(&opp); + conn = dbus_bus_get(DBUS_BUS_SESSION, NULL); + if (!conn) + return -EIO; + + err = obc_driver_register(&opp); + if (err < 0) { + dbus_connection_unref(conn); + conn = NULL; + return err; + } + + return 0; } void opp_exit(void) { DBG(""); + dbus_connection_unref(conn); + conn = NULL; + obc_driver_unregister(&opp); } diff -Nru obexd-0.46/client/pbap.c obexd-0.48/client/pbap.c --- obexd-0.46/client/pbap.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/pbap.c 2012-11-30 08:59:13.000000000 +0100 @@ -33,6 +33,7 @@ #include #include +#include #include "log.h" @@ -45,8 +46,6 @@ "\x79\x61\x35\xF0\xF0\xC5\x11\xD8\x09\x66\x08\x00\x20\x0C\x9A\x66" #define OBEX_PBAP_UUID_LEN 16 -#define ERROR_INF PBAP_INTERFACE ".Error" - #define FORMAT_VCARD21 0x0 #define FORMAT_VCARD30 0x1 @@ -74,18 +73,6 @@ #define PHONEBOOKSIZE_TAG 0X08 #define NEWMISSEDCALLS_TAG 0X09 -/* The following length is in the unit of byte */ -#define ORDER_LEN 1 -#define SEARCHATTRIB_LEN 1 -#define MAXLISTCOUNT_LEN 2 -#define LISTSTARTOFFSET_LEN 2 -#define FILTER_LEN 8 -#define FORMAT_LEN 1 -#define PHONEBOOKSIZE_LEN 2 -#define NEWMISSEDCALLS_LEN 1 - -#define get_be16(val) GUINT16_FROM_BE(bt_get_unaligned((guint16 *) val)) - static const char *filter_list[] = { "VERSION", "FN", @@ -122,15 +109,13 @@ #define FILTER_BIT_MAX 63 #define FILTER_ALL 0xFFFFFFFFFFFFFFFFULL -#define PBAP_INTERFACE "org.openobex.PhonebookAccess" +#define PBAP_INTERFACE "org.bluez.obex.PhonebookAccess" +#define ERROR_INTERFACE "org.bluez.obex.Error" #define PBAP_UUID "0000112f-0000-1000-8000-00805f9b34fb" struct pbap_data { struct obc_session *session; char *path; - guint8 format; - guint8 order; - uint64_t filter; }; struct pending_request { @@ -138,38 +123,6 @@ DBusMessage *msg; }; -struct pullphonebook_apparam { - uint8_t filter_tag; - uint8_t filter_len; - uint64_t filter; - uint8_t format_tag; - uint8_t format_len; - uint8_t format; - uint8_t maxlistcount_tag; - uint8_t maxlistcount_len; - uint16_t maxlistcount; - uint8_t liststartoffset_tag; - uint8_t liststartoffset_len; - uint16_t liststartoffset; -} __attribute__ ((packed)); - -struct pullvcardentry_apparam { - uint8_t filter_tag; - uint8_t filter_len; - uint64_t filter; - uint8_t format_tag; - uint8_t format_len; - uint8_t format; -} __attribute__ ((packed)); - -struct apparam_hdr { - uint8_t tag; - uint8_t len; - uint8_t val[0]; -} __attribute__ ((packed)); - -#define APPARAM_HDR_SIZE 2 - static DBusConnection *conn = NULL; static struct pending_request *pending_request_new(struct pbap_data *pbap, @@ -233,14 +186,14 @@ if (!g_ascii_strcasecmp(location, "INT") || !g_ascii_strcasecmp(location, "INTERNAL")) - path = g_strdup("telecom"); + path = g_strdup("/telecom"); else if (!g_ascii_strncasecmp(location, "SIM", 3)) { if (strlen(location) == 3) tmp = g_strdup("SIM1"); else tmp = g_ascii_strup(location, 4); - path = g_build_filename(tmp, "telecom", NULL); + path = g_build_filename("/", tmp, "telecom", NULL); g_free(tmp); } else return NULL; @@ -284,8 +237,8 @@ if (err) { DBusMessage *reply = g_dbus_create_error(request->msg, - ERROR_INF ".Failed", - "%s", err->message); + ERROR_INTERFACE ".Failed", + "%s", err->message); g_dbus_send_message(conn, reply); } else g_dbus_send_reply(conn, request->msg, DBUS_TYPE_INVALID); @@ -296,87 +249,19 @@ static void read_return_apparam(struct obc_transfer *transfer, guint16 *phone_book_size, guint8 *new_missed_calls) { - const struct apparam_hdr *hdr; - size_t size; + GObexApparam *apparam; *phone_book_size = 0; *new_missed_calls = 0; - hdr = obc_transfer_get_params(transfer, &size); - if (hdr == NULL) + apparam = obc_transfer_get_apparam(transfer); + if (apparam == NULL) return; - if (size < APPARAM_HDR_SIZE) - return; - - while (size > APPARAM_HDR_SIZE) { - if (hdr->len > size - APPARAM_HDR_SIZE) { - error("Unexpected PBAP pullphonebook app" - " length, tag %d, len %d", - hdr->tag, hdr->len); - return; - } - - switch (hdr->tag) { - case PHONEBOOKSIZE_TAG: - if (hdr->len == PHONEBOOKSIZE_LEN) { - guint16 val; - memcpy(&val, hdr->val, sizeof(val)); - *phone_book_size = get_be16(&val); - } - break; - case NEWMISSEDCALLS_TAG: - if (hdr->len == NEWMISSEDCALLS_LEN) - *new_missed_calls = hdr->val[0]; - break; - default: - error("Unexpected PBAP pullphonebook app" - " parameter, tag %d, len %d", - hdr->tag, hdr->len); - } - - size -= APPARAM_HDR_SIZE + hdr->len; - hdr += APPARAM_HDR_SIZE + hdr->len; - } -} - -static void pull_phonebook_callback(struct obc_session *session, - struct obc_transfer *transfer, - GError *err, void *user_data) -{ - struct pending_request *request = user_data; - DBusMessage *reply; - char *contents; - size_t size; - int perr; - - if (err) { - reply = g_dbus_create_error(request->msg, - "org.openobex.Error.Failed", - "%s", err->message); - goto send; - } - - perr = obc_transfer_get_contents(transfer, &contents, &size); - if (perr < 0) { - reply = g_dbus_create_error(request->msg, - "org.openobex.Error.Failed", - "Error reading contents: %s", - strerror(-perr)); - goto send; - } - - reply = dbus_message_new_method_return(request->msg); - - dbus_message_append_args(reply, - DBUS_TYPE_STRING, &contents, - DBUS_TYPE_INVALID); - - g_free(contents); - -send: - g_dbus_send_message(conn, reply); - pending_request_free(request); + g_obex_apparam_get_uint16(apparam, PHONEBOOKSIZE_TAG, + phone_book_size); + g_obex_apparam_get_uint8(apparam, NEWMISSEDCALLS_TAG, + new_missed_calls); } static void phonebook_size_callback(struct obc_session *session, @@ -390,7 +275,7 @@ if (err) { reply = g_dbus_create_error(request->msg, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".Failed", "%s", err->message); goto send; } @@ -422,7 +307,7 @@ if (err) { reply = g_dbus_create_error(request->msg, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".Failed", "%s", err->message); goto send; } @@ -430,7 +315,7 @@ perr = obc_transfer_get_contents(transfer, &contents, &size); if (perr < 0) { reply = g_dbus_create_error(request->msg, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".Failed", "Error reading contents: %s", strerror(-perr)); goto send; @@ -454,165 +339,75 @@ pending_request_free(request); } -static DBusMessage *pull_phonebook(struct pbap_data *pbap, - DBusMessage *message, guint8 type, - const char *name, uint64_t filter, - guint8 format, guint16 maxlistcount, - guint16 liststartoffset) +static GObexApparam *parse_format(GObexApparam *apparam, DBusMessageIter *iter) { - struct pending_request *request; - struct pullphonebook_apparam apparam; - struct obc_transfer *transfer; - session_callback_t func; - GError *err = NULL; - DBusMessage *reply; - - transfer = obc_transfer_get("x-bt/phonebook", name, NULL, &err); - if (transfer == NULL) - goto fail; - - apparam.filter_tag = FILTER_TAG; - apparam.filter_len = FILTER_LEN; - apparam.filter = GUINT64_TO_BE(filter); - apparam.format_tag = FORMAT_TAG; - apparam.format_len = FORMAT_LEN; - apparam.format = format; - apparam.maxlistcount_tag = MAXLISTCOUNT_TAG; - apparam.maxlistcount_len = MAXLISTCOUNT_LEN; - apparam.maxlistcount = GUINT16_TO_BE(maxlistcount); - apparam.liststartoffset_tag = LISTSTARTOFFSET_TAG; - apparam.liststartoffset_len = LISTSTARTOFFSET_LEN; - apparam.liststartoffset = GUINT16_TO_BE(liststartoffset); + const char *string; + guint8 format; - switch (type) { - case PULLPHONEBOOK: - func = pull_phonebook_callback; - break; - case GETPHONEBOOKSIZE: - func = phonebook_size_callback; - break; - default: - error("Unexpected type : 0x%2x", type); + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) return NULL; - } - - request = pending_request_new(pbap, message); - obc_transfer_set_params(transfer, &apparam, sizeof(apparam)); + dbus_message_iter_get_basic(iter, &string); - if (obc_session_queue(pbap->session, transfer, func, request, &err)) + if (!string || g_str_equal(string, "")) + format = FORMAT_VCARD21; + else if (!g_ascii_strcasecmp(string, "vcard21")) + format = FORMAT_VCARD21; + else if (!g_ascii_strcasecmp(string, "vcard30")) + format = FORMAT_VCARD30; + else return NULL; - pending_request_free(request); - -fail: - reply = g_dbus_create_error(message, "org.openobex.Error.Failed", "%s", - err->message); - g_error_free(err); - return reply; + return g_obex_apparam_set_uint8(apparam, FORMAT_TAG, format); } -static guint8 *fill_apparam(guint8 *dest, void *buf, guint8 tag, guint8 len) +static GObexApparam *parse_order(GObexApparam *apparam, DBusMessageIter *iter) { - if (dest && buf) { - *dest++ = tag; - *dest++ = len; - memcpy(dest, buf, len); - dest += len; - } - - return dest; -} - -static DBusMessage *pull_vcard_listing(struct pbap_data *pbap, - DBusMessage *message, const char *name, - guint8 order, char *searchval, guint8 attrib, - guint16 count, guint16 offset) -{ - struct pending_request *request; - struct obc_transfer *transfer; - guint8 *p, apparam[272]; - gint apparam_size; - GError *err = NULL; - DBusMessage *reply; - - transfer = obc_transfer_get("x-bt/vcard-listing", name, NULL, &err); - if (transfer == NULL) - goto fail; - - /* trunc the searchval string if it's length exceed the max value of guint8 */ - if (strlen(searchval) > 254) - searchval[255] = '\0'; - - apparam_size = APPARAM_HDR_SIZE + ORDER_LEN + - (APPARAM_HDR_SIZE + strlen(searchval) + 1) + - (APPARAM_HDR_SIZE + SEARCHATTRIB_LEN) + - (APPARAM_HDR_SIZE + MAXLISTCOUNT_LEN) + - (APPARAM_HDR_SIZE + LISTSTARTOFFSET_LEN); - - p = apparam; - - p = fill_apparam(p, &order, ORDER_TAG, ORDER_LEN); - p = fill_apparam(p, searchval, SEARCHVALUE_TAG, strlen(searchval) + 1); - p = fill_apparam(p, &attrib, SEARCHATTRIB_TAG, SEARCHATTRIB_LEN); - - count = GUINT16_TO_BE(count); - p = fill_apparam(p, &count, MAXLISTCOUNT_TAG, MAXLISTCOUNT_LEN); - - offset = GUINT16_TO_BE(offset); - p = fill_apparam(p, &offset, LISTSTARTOFFSET_TAG, LISTSTARTOFFSET_LEN); + const char *string; + guint8 order; - request = pending_request_new(pbap, message); + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRING) + return NULL; - obc_transfer_set_params(transfer, apparam, apparam_size); + dbus_message_iter_get_basic(iter, &string); - if (obc_session_queue(pbap->session, transfer, - pull_vcard_listing_callback, request, &err)) + if (!string || g_str_equal(string, "")) + order = ORDER_INDEXED; + else if (!g_ascii_strcasecmp(string, "indexed")) + order = ORDER_INDEXED; + else if (!g_ascii_strcasecmp(string, "alphanumeric")) + order = ORDER_ALPHANUMERIC; + else if (!g_ascii_strcasecmp(string, "phonetic")) + order = ORDER_PHONETIC; + else return NULL; - pending_request_free(request); - -fail: - reply = g_dbus_create_error(message, "org.openobex.Error.Failed", "%s", - err->message); - g_error_free(err); - return reply; + return g_obex_apparam_set_uint8(apparam, ORDER_TAG, order); } -static int set_format(struct pbap_data *pbap, const char *formatstr) +static GObexApparam *parse_offset(GObexApparam *apparam, DBusMessageIter *iter) { - if (!formatstr || g_str_equal(formatstr, "")) { - pbap->format = FORMAT_VCARD21; - return 0; - } + guint16 num; - if (!g_ascii_strcasecmp(formatstr, "vcard21")) - pbap->format = FORMAT_VCARD21; - else if (!g_ascii_strcasecmp(formatstr, "vcard30")) - pbap->format = FORMAT_VCARD30; - else - return -EINVAL; + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16) + return NULL; - return 0; + dbus_message_iter_get_basic(iter, &num); + + return g_obex_apparam_set_uint16(apparam, LISTSTARTOFFSET_TAG, num); } -static int set_order(struct pbap_data *pbap, const char *orderstr) +static GObexApparam *parse_max_count(GObexApparam *apparam, + DBusMessageIter *iter) { - if (!orderstr || g_str_equal(orderstr, "")) { - pbap->order = ORDER_INDEXED; - return 0; - } + guint16 num; - if (!g_ascii_strcasecmp(orderstr, "indexed")) - pbap->order = ORDER_INDEXED; - else if (!g_ascii_strcasecmp(orderstr, "alphanumeric")) - pbap->order = ORDER_ALPHANUMERIC; - else if (!g_ascii_strcasecmp(orderstr, "phonetic")) - pbap->order = ORDER_PHONETIC; - else - return -EINVAL; + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16) + return NULL; - return 0; + dbus_message_iter_get_basic(iter, &num); + + return g_obex_apparam_set_uint16(apparam, MAXLISTCOUNT_TAG, num); } static uint64_t get_filter_mask(const char *filterstr) @@ -640,56 +435,174 @@ return 0; } -static int add_filter(struct pbap_data *pbap, const char *filterstr) +static int set_field(guint64 *filter, const char *filterstr) { - uint64_t mask; + guint64 mask; mask = get_filter_mask(filterstr); if (mask == 0) return -EINVAL; - pbap->filter |= mask; + *filter |= mask; return 0; } -static int remove_filter(struct pbap_data *pbap, const char *filterstr) +static GObexApparam *parse_fields(GObexApparam *apparam, DBusMessageIter *iter) { - uint64_t mask; + DBusMessageIter array; + guint64 filter = 0; - mask = get_filter_mask(filterstr); + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return NULL; - if (mask == 0) - return -EINVAL; + dbus_message_iter_recurse(iter, &array); - pbap->filter &= ~mask; - return 0; + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { + const char *string; + + dbus_message_iter_get_basic(&array, &string); + + if (set_field(&filter, string) < 0) + return NULL; + + dbus_message_iter_next(&array); + } + + return g_obex_apparam_set_uint64(apparam, FILTER_TAG, filter); } -static gchar **get_filter_strs(uint64_t filter, gint *size) +static GObexApparam *parse_filters(GObexApparam *apparam, + DBusMessageIter *iter) { - gchar **list, **item; - gint i; - gint filter_list_size = sizeof(filter_list) / sizeof(filter_list[0]) - 1; + DBusMessageIter array; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return NULL; + + dbus_message_iter_recurse(iter, &array); + + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) { + const char *key; + DBusMessageIter value, entry; + + dbus_message_iter_recurse(&array, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &value); + + if (strcasecmp(key, "Format") == 0) { + if (parse_format(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Order") == 0) { + if (parse_order(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Offset") == 0) { + if (parse_offset(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "MaxCount") == 0) { + if (parse_max_count(apparam, &value) == NULL) + return NULL; + } else if (strcasecmp(key, "Fields") == 0) { + if (parse_fields(apparam, &value) == NULL) + return NULL; + } - list = g_try_malloc0(sizeof(gchar **) * (FILTER_BIT_MAX + 2)); + dbus_message_iter_next(&array); + } - if (!list) + return apparam; +} + +static DBusMessage *pull_phonebook(struct pbap_data *pbap, + DBusMessage *message, + guint8 type, + const char *targetfile, + GObexApparam *apparam) +{ + struct pending_request *request; + struct obc_transfer *transfer; + char *name; + session_callback_t func; + DBusMessage *reply; + GError *err = NULL; + + name = g_strconcat(g_path_skip_root(pbap->path), ".vcf", NULL); + + transfer = obc_transfer_get("x-bt/phonebook", name, targetfile, &err); + if (transfer == NULL) { + g_obex_apparam_free(apparam); + goto fail; + } + + switch (type) { + case PULLPHONEBOOK: + func = NULL; + request = NULL; + break; + case GETPHONEBOOKSIZE: + func = phonebook_size_callback; + request = pending_request_new(pbap, message); + break; + default: + error("Unexpected type : 0x%2x", type); return NULL; + } - item = list; + obc_transfer_set_apparam(transfer, apparam); - for (i = 0; i < filter_list_size; i++) - if (filter & (1ULL << i)) - *(item++) = g_strdup(filter_list[i]); + if (!obc_session_queue(pbap->session, transfer, func, request, &err)) { + if (request != NULL) + pending_request_free(request); - for (i = filter_list_size; i <= FILTER_BIT_MAX; i++) - if (filter & (1ULL << i)) - *(item++) = g_strdup_printf("%s%d", "BIT", i); + goto fail; + } - *item = NULL; - *size = item - list; - return list; + g_free(name); + + if (targetfile == NULL) + return NULL; + + return obc_transfer_create_dbus_reply(transfer, message); + +fail: + g_free(name); + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", + err->message); + g_error_free(err); + return reply; +} + +static DBusMessage *pull_vcard_listing(struct pbap_data *pbap, + DBusMessage *message, const char *name, + GObexApparam *apparam) +{ + struct pending_request *request; + struct obc_transfer *transfer; + GError *err = NULL; + DBusMessage *reply; + + transfer = obc_transfer_get("x-bt/vcard-listing", name, NULL, &err); + if (transfer == NULL) { + g_obex_apparam_free(apparam); + goto fail; + } + + obc_transfer_set_apparam(transfer, apparam); + + request = pending_request_new(pbap, message); + if (obc_session_queue(pbap->session, transfer, + pull_vcard_listing_callback, request, &err)) + return NULL; + + pending_request_free(request); + +fail: + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", + err->message); + g_error_free(err); + return reply; } static DBusMessage *pbap_select(DBusConnection *connection, @@ -706,12 +619,13 @@ DBUS_TYPE_STRING, &item, DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); path = build_phonebook_path(location, item); if (path == NULL) return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", "Invalid path"); + ERROR_INTERFACE ".InvalidArguments", + "Invalid path"); if (pbap->path != NULL && g_str_equal(pbap->path, path)) { g_free(path); @@ -724,7 +638,7 @@ &err); if (err != NULL) { DBusMessage *reply; - reply = g_dbus_create_error(message, ERROR_INF ".Failed", + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", err->message); g_error_free(err); g_free(path); @@ -742,102 +656,141 @@ DBusMessage *message, void *user_data) { struct pbap_data *pbap = user_data; - DBusMessage * err; - char *name; + const char *targetfile; + GObexApparam *apparam; + DBusMessageIter args; if (!pbap->path) return g_dbus_create_error(message, - ERROR_INF ".Forbidden", "Call Select first of all"); + ERROR_INTERFACE ".Forbidden", + "Call Select first of all"); - name = g_strconcat(pbap->path, ".vcf", NULL); + dbus_message_iter_init(message, &args); - err = pull_phonebook(pbap, message, PULLPHONEBOOK, name, - pbap->filter, pbap->format, - DEFAULT_COUNT, DEFAULT_OFFSET); - g_free(name); - return err; -} + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); -static DBusMessage *pbap_pull_vcard(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - struct pbap_data *pbap = user_data; - struct pullvcardentry_apparam apparam; - const char *name; - struct pending_request *request; - struct obc_transfer *transfer; - GError *err = NULL; - DBusMessage *reply; + dbus_message_iter_get_basic(&args, &targetfile); + dbus_message_iter_next(&args); - if (!pbap->path) - return g_dbus_create_error(message, - ERROR_INF ".Forbidden", - "Call Select first of all"); + apparam = g_obex_apparam_set_uint16(NULL, MAXLISTCOUNT_TAG, + DEFAULT_COUNT); + apparam = g_obex_apparam_set_uint16(apparam, LISTSTARTOFFSET_TAG, + DEFAULT_OFFSET); - if (dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID) == FALSE) + if (parse_filters(apparam, &args) == NULL) { + g_obex_apparam_free(apparam); return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); + } - transfer = obc_transfer_get("x-bt/vcard", name, NULL, &err); - if (transfer == NULL) - goto fail; + return pull_phonebook(pbap, message, PULLPHONEBOOK, targetfile, + apparam); +} - apparam.filter_tag = FILTER_TAG; - apparam.filter_len = FILTER_LEN; - apparam.filter = GUINT64_TO_BE(pbap->filter); - apparam.format_tag = FORMAT_TAG; - apparam.format_len = FORMAT_LEN; - apparam.format = pbap->format; +static DBusMessage *pull_vcard(struct pbap_data *pbap, DBusMessage *message, + const char *name, const char *targetfile, + GObexApparam *apparam) +{ + struct obc_transfer *transfer; + DBusMessage *reply; + GError *err = NULL; - request = pending_request_new(pbap, message); + transfer = obc_transfer_get("x-bt/vcard", name, targetfile, &err); + if (transfer == NULL) { + g_obex_apparam_free(apparam); + goto fail; + } - obc_transfer_set_params(transfer, &apparam, sizeof(apparam)); + obc_transfer_set_apparam(transfer, apparam); - if (obc_session_queue(pbap->session, transfer, pull_phonebook_callback, - request, &err)) - return NULL; + if (!obc_session_queue(pbap->session, transfer, NULL, NULL, &err)) + goto fail; - pending_request_free(request); + return obc_transfer_create_dbus_reply(transfer, message); fail: - reply = g_dbus_create_error(message, "org.openobex.Error.Failed", "%s", + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", err->message); g_error_free(err); return reply; } -static DBusMessage *pbap_list(DBusConnection *connection, +static DBusMessage *pbap_pull_vcard(DBusConnection *connection, DBusMessage *message, void *user_data) { struct pbap_data *pbap = user_data; + GObexApparam *apparam; + const char *name, *targetfile; + DBusMessageIter args; if (!pbap->path) return g_dbus_create_error(message, - ERROR_INF ".Forbidden", "Call Select first of all"); + ERROR_INTERFACE ".Forbidden", + "Call Select first of all"); + + dbus_message_iter_init(message, &args); + + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + + dbus_message_iter_get_basic(&args, &name); + dbus_message_iter_next(&args); + + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + + dbus_message_iter_get_basic(&args, &targetfile); + dbus_message_iter_next(&args); + + apparam = g_obex_apparam_set_uint16(NULL, MAXLISTCOUNT_TAG, + DEFAULT_COUNT); + apparam = g_obex_apparam_set_uint16(apparam, LISTSTARTOFFSET_TAG, + DEFAULT_OFFSET); - return pull_vcard_listing(pbap, message, "", pbap->order, "", - ATTRIB_NAME, DEFAULT_COUNT, DEFAULT_OFFSET); + if (parse_filters(apparam, &args) == NULL) { + g_obex_apparam_free(apparam); + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); + } + + return pull_vcard(pbap, message, name, targetfile, apparam); } -static DBusMessage *pbap_search(DBusConnection *connection, +static DBusMessage *pbap_list(DBusConnection *connection, DBusMessage *message, void *user_data) { struct pbap_data *pbap = user_data; - char *field, *value; - guint8 attrib; + GObexApparam *apparam; + DBusMessageIter args; - if (dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &field, - DBUS_TYPE_STRING, &value, - DBUS_TYPE_INVALID) == FALSE) + if (!pbap->path) return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", NULL); + ERROR_INTERFACE ".Forbidden", + "Call Select first of all"); - if (!pbap->path) + dbus_message_iter_init(message, &args); + + apparam = g_obex_apparam_set_uint16(NULL, MAXLISTCOUNT_TAG, + DEFAULT_COUNT); + apparam = g_obex_apparam_set_uint16(apparam, LISTSTARTOFFSET_TAG, + DEFAULT_OFFSET); + + if (parse_filters(apparam, &args) == NULL) { + g_obex_apparam_free(apparam); return g_dbus_create_error(message, - ERROR_INF ".Forbidden", "Call Select first of all"); + ERROR_INTERFACE ".InvalidArguments", NULL); + } + + return pull_vcard_listing(pbap, message, "", apparam); +} + +static GObexApparam *parse_attribute(GObexApparam *apparam, const char *field) +{ + guint8 attrib; if (!field || g_str_equal(field, "")) attrib = ATTRIB_NAME; @@ -848,119 +801,101 @@ else if (!g_ascii_strcasecmp(field, "sound")) attrib = ATTRIB_SOUND; else - return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", NULL); + return NULL; - return pull_vcard_listing(pbap, message, "", pbap->order, value, - attrib, DEFAULT_COUNT, DEFAULT_OFFSET); + return g_obex_apparam_set_uint8(apparam, SEARCHATTRIB_TAG, attrib); } -static DBusMessage *pbap_get_size(DBusConnection *connection, +static DBusMessage *pbap_search(DBusConnection *connection, DBusMessage *message, void *user_data) { struct pbap_data *pbap = user_data; - DBusMessage * err; - char *name; + char *field, *value; + GObexApparam *apparam; + DBusMessageIter args; if (!pbap->path) return g_dbus_create_error(message, - ERROR_INF ".Forbidden", "Call Select first of all"); + ERROR_INTERFACE ".Forbidden", + "Call Select first of all"); - name = g_strconcat(pbap->path, ".vcf", NULL); + dbus_message_iter_init(message, &args); - err = pull_phonebook(pbap, message, GETPHONEBOOKSIZE, name, - pbap->filter, pbap->format, 0, - DEFAULT_OFFSET); - g_free(name); - return err; -} + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) + return g_dbus_create_error(message, + ERROR_INTERFACE ".InvalidArguments", NULL); -static DBusMessage *pbap_set_format(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - struct pbap_data *pbap = user_data; - const char *format; + dbus_message_iter_get_basic(&args, &field); + dbus_message_iter_next(&args); - if (dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &format, - DBUS_TYPE_INVALID) == FALSE) + apparam = parse_attribute(NULL, field); + if (apparam == NULL) return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", NULL); + ERROR_INTERFACE ".InvalidArguments", NULL); - if (set_format(pbap, format) < 0) + if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", "InvalidFormat"); - - return dbus_message_new_method_return(message); -} + ERROR_INTERFACE ".InvalidArguments", NULL); -static DBusMessage *pbap_set_order(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - struct pbap_data *pbap = user_data; - const char *order; + dbus_message_iter_get_basic(&args, &value); + dbus_message_iter_next(&args); - if (dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &order, - DBUS_TYPE_INVALID) == FALSE) - return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", NULL); + apparam = g_obex_apparam_set_uint16(apparam, MAXLISTCOUNT_TAG, + DEFAULT_COUNT); + apparam = g_obex_apparam_set_uint16(apparam, LISTSTARTOFFSET_TAG, + DEFAULT_OFFSET); + apparam = g_obex_apparam_set_string(apparam, SEARCHVALUE_TAG, value); - if (set_order(pbap, order) < 0) + if (parse_filters(apparam, &args) == NULL) { + g_obex_apparam_free(apparam); return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", "InvalidFilter"); + ERROR_INTERFACE ".InvalidArguments", NULL); + } - return dbus_message_new_method_return(message); + return pull_vcard_listing(pbap, message, "", apparam); } -static DBusMessage *pbap_set_filter(DBusConnection *connection, +static DBusMessage *pbap_get_size(DBusConnection *connection, DBusMessage *message, void *user_data) { struct pbap_data *pbap = user_data; - char **filters, **item; - gint size; - uint64_t oldfilter = pbap->filter; + GObexApparam *apparam; + DBusMessageIter args; - if (dbus_message_get_args(message, NULL, DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING, &filters, &size, - DBUS_TYPE_INVALID) == FALSE) + if (!pbap->path) return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", NULL); + ERROR_INTERFACE ".Forbidden", + "Call Select first of all"); - remove_filter(pbap, "ALL"); - if (size == 0) - goto done; - - for (item = filters; *item; item++) { - if (add_filter(pbap, *item) < 0) { - pbap->filter = oldfilter; - g_strfreev(filters); - return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", "InvalidFilters"); - } - } + dbus_message_iter_init(message, &args); -done: - g_strfreev(filters); - return dbus_message_new_method_return(message); + apparam = g_obex_apparam_set_uint16(NULL, MAXLISTCOUNT_TAG, 0); + apparam = g_obex_apparam_set_uint16(apparam, LISTSTARTOFFSET_TAG, + DEFAULT_OFFSET); + + return pull_phonebook(pbap, message, GETPHONEBOOKSIZE, NULL, apparam); } -static DBusMessage *pbap_get_filter(DBusConnection *connection, - DBusMessage *message, void *user_data) +static gchar **get_filter_strs(uint64_t filter, gint *size) { - struct pbap_data *pbap = user_data; - gchar **filters = NULL; - gint size; - DBusMessage *reply; + gchar **list, **item; + gint i; - filters = get_filter_strs(pbap->filter, &size); - reply = dbus_message_new_method_return(message); - dbus_message_append_args(reply, DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING, &filters, size, - DBUS_TYPE_INVALID); + list = g_malloc0(sizeof(gchar **) * (FILTER_BIT_MAX + 2)); - g_strfreev(filters); - return reply; + item = list; + + for (i = 0; filter_list[i] != NULL; i++) + if (filter & (1ULL << i)) + *(item++) = g_strdup(filter_list[i]); + + for (; i <= FILTER_BIT_MAX; i++) + if (filter & (1ULL << i)) + *(item++) = g_strdup_printf("%s%d", "BIT", i); + + *item = NULL; + *size = item - list; + return list; } static DBusMessage *pbap_list_filter_fields(DBusConnection *connection, @@ -980,24 +915,37 @@ return reply; } -static GDBusMethodTable pbap_methods[] = { - { "Select", "ss", "", pbap_select, - G_DBUS_METHOD_FLAG_ASYNC }, - { "PullAll", "", "s", pbap_pull_all, - G_DBUS_METHOD_FLAG_ASYNC }, - { "Pull", "s", "s", pbap_pull_vcard, - G_DBUS_METHOD_FLAG_ASYNC }, - { "List", "", "a(ss)", pbap_list, - G_DBUS_METHOD_FLAG_ASYNC }, - { "Search", "ss", "a(ss)", pbap_search, - G_DBUS_METHOD_FLAG_ASYNC }, - { "GetSize", "", "q", pbap_get_size, - G_DBUS_METHOD_FLAG_ASYNC }, - { "SetFormat", "s", "", pbap_set_format }, - { "SetOrder", "s", "", pbap_set_order }, - { "SetFilter", "as", "", pbap_set_filter }, - { "GetFilter", "", "as", pbap_get_filter }, - { "ListFilterFields", "", "as", pbap_list_filter_fields }, +static const GDBusMethodTable pbap_methods[] = { + { GDBUS_ASYNC_METHOD("Select", + GDBUS_ARGS({ "location", "s" }, { "phonebook", "s" }), + NULL, pbap_select) }, + { GDBUS_METHOD("PullAll", + GDBUS_ARGS({ "targetfile", "s" }, + { "filters", "a{sv}" }), + GDBUS_ARGS({ "transfer", "o" }, + { "properties", "a{sv}" }), + pbap_pull_all) }, + { GDBUS_METHOD("Pull", + GDBUS_ARGS({ "vcard", "s" }, { "targetfile", "s" }, + { "filters", "a{sv}" }), + GDBUS_ARGS({ "transfer", "o" }, + { "properties", "a{sv}" }), + pbap_pull_vcard) }, + { GDBUS_ASYNC_METHOD("List", + GDBUS_ARGS({ "filters", "a{sv}" }), + GDBUS_ARGS({ "vcard_listing", "a(ss)" }), + pbap_list) }, + { GDBUS_ASYNC_METHOD("Search", + GDBUS_ARGS({ "field", "s" }, { "value", "s" }, + { "filters", "a{sv}" }), + GDBUS_ARGS({ "vcard_listing", "a(ss)" }), + pbap_search) }, + { GDBUS_ASYNC_METHOD("GetSize", + NULL, GDBUS_ARGS({ "size", "q" }), + pbap_get_size) }, + { GDBUS_METHOD("ListFilterFields", + NULL, GDBUS_ARGS({ "fields", "as" }), + pbap_list_filter_fields) }, { } }; diff -Nru obexd-0.46/client/session.c obexd-0.48/client/session.c --- obexd-0.46/client/session.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/session.c 2012-07-26 19:09:25.000000000 +0200 @@ -3,6 +3,7 @@ * OBEX Client * * Copyright (C) 2007-2010 Marcel Holtmann + * Copyright (C) 2011-2012 BMW Car IT GmbH. All rights reserved. * * * This program is free software; you can redistribute it and/or modify @@ -37,15 +38,16 @@ #include #include +#include "dbus.h" #include "log.h" #include "transfer.h" #include "session.h" -#include "agent.h" #include "driver.h" #include "transport.h" -#define SESSION_INTERFACE "org.openobex.Session" -#define SESSION_BASEPATH "/org/openobex" +#define SESSION_INTERFACE "org.bluez.obex.Session" +#define ERROR_INTERFACE "org.bluez.obex.Error" +#define SESSION_BASEPATH "/org/bluez/obex" #define OBEX_IO_ERROR obex_io_error_quark() #define OBEX_IO_ERROR_FIRST (0xff + 1) @@ -68,7 +70,6 @@ guint req_id; struct obc_session *session; struct obc_transfer *transfer; - GFunc auth_complete; session_callback_t func; void *data; }; @@ -91,22 +92,21 @@ gchar *path; /* Session path */ DBusConnection *conn; GObex *obex; - struct obc_agent *agent; struct pending_request *p; gchar *owner; /* Session owner */ guint watch; GQueue *queue; + guint queue_complete_id; }; static GSList *sessions = NULL; -static void session_start_transfer(gpointer data, gpointer user_data); +static void session_process_queue(struct obc_session *session); static void session_terminate_transfer(struct obc_session *session, struct obc_transfer *transfer, GError *gerr); -static void transfer_progress(struct obc_transfer *transfer, - gint64 transferred, GError *err, - void *user_data); +static void transfer_complete(struct obc_transfer *transfer, + GError *err, void *user_data); static GQuark obex_io_error_quark(void) { @@ -141,7 +141,6 @@ static struct pending_request *pending_request_new(struct obc_session *session, struct obc_transfer *transfer, - GFunc auth_complete, session_callback_t func, void *data) { @@ -152,7 +151,6 @@ p->id = ++id; p->session = obc_session_ref(session); p->transfer = transfer; - p->auth_complete = auth_complete; p->func = func; p->data = data; @@ -174,10 +172,8 @@ { DBG("%p", session); - if (session->agent) { - obc_agent_release(session->agent); - obc_agent_free(session->agent); - } + if (session->queue_complete_id != 0) + g_source_remove(session->queue_complete_id); if (session->queue) { g_queue_foreach(session->queue, (GFunc) pending_request_free, @@ -528,94 +524,6 @@ obc_session_unref(session); } -static DBusMessage *assign_agent(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - struct obc_session *session = user_data; - const gchar *sender, *path; - - if (dbus_message_get_args(message, NULL, - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID) == FALSE) - return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", - "Invalid arguments in method call"); - - sender = dbus_message_get_sender(message); - - if (obc_session_set_agent(session, sender, path) < 0) - return g_dbus_create_error(message, - "org.openobex.Error.AlreadyExists", - "Already exists"); - - return dbus_message_new_method_return(message); -} - -static DBusMessage *release_agent(DBusConnection *connection, - DBusMessage *message, void *user_data) -{ - struct obc_session *session = user_data; - struct obc_agent *agent = session->agent; - const gchar *sender; - gchar *path; - - if (dbus_message_get_args(message, NULL, - DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID) == FALSE) - return g_dbus_create_error(message, - "org.openobex.Error.InvalidArguments", - "Invalid arguments in method call"); - - sender = dbus_message_get_sender(message); - - if (agent == NULL) - return dbus_message_new_method_return(message); - - if (g_str_equal(sender, obc_agent_get_name(agent)) == FALSE || - g_str_equal(path, obc_agent_get_path(agent)) == FALSE) - return g_dbus_create_error(message, - "org.openobex.Error.NotAuthorized", - "Not Authorized"); - - obc_agent_free(agent); - - return dbus_message_new_method_return(message); -} - -static void append_entry(DBusMessageIter *dict, - const char *key, int type, void *val) -{ - DBusMessageIter entry, value; - const char *signature; - - dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, - NULL, &entry); - - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); - - switch (type) { - case DBUS_TYPE_STRING: - signature = DBUS_TYPE_STRING_AS_STRING; - break; - case DBUS_TYPE_BYTE: - signature = DBUS_TYPE_BYTE_AS_STRING; - break; - case DBUS_TYPE_UINT64: - signature = DBUS_TYPE_UINT64_AS_STRING; - break; - default: - signature = DBUS_TYPE_VARIANT_AS_STRING; - break; - } - - dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, - signature, &value); - dbus_message_iter_append_basic(&value, type, val); - dbus_message_iter_close_container(&entry, &value); - - dbus_message_iter_close_container(dict, &entry); -} - static DBusMessage *session_get_properties(DBusConnection *connection, DBusMessage *message, void *user_data) { @@ -635,114 +543,103 @@ DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); if (session->source != NULL) - append_entry(&dict, "Source", DBUS_TYPE_STRING, + obex_dbus_dict_append(&dict, "Source", DBUS_TYPE_STRING, &session->source); - append_entry(&dict, "Destination", DBUS_TYPE_STRING, + obex_dbus_dict_append(&dict, "Destination", DBUS_TYPE_STRING, &session->destination); - append_entry(&dict, "Channel", DBUS_TYPE_BYTE, &session->channel); + obex_dbus_dict_append(&dict, "Channel", DBUS_TYPE_BYTE, + &session->channel); dbus_message_iter_close_container(&iter, &dict); return reply; } -static GDBusMethodTable session_methods[] = { - { "GetProperties", "", "a{sv}", session_get_properties }, - { "AssignAgent", "o", "", assign_agent }, - { "ReleaseAgent", "o", "", release_agent }, - { } -}; - -static void session_request_reply(DBusPendingCall *call, gpointer user_data) +static void capabilities_complete_callback(struct obc_session *session, + struct obc_transfer *transfer, + GError *err, void *user_data) { - struct obc_session *session = user_data; - struct pending_request *p = session->p; - struct obc_transfer *transfer = p->transfer; - DBusMessage *reply = dbus_pending_call_steal_reply(call); - const char *name; - DBusError derr; - int err; - - dbus_error_init(&derr); - if (dbus_set_error_from_message(&derr, reply)) { - GError *gerr = NULL; + DBusMessage *message = user_data; + char *contents; + size_t size; + int perr; - error("Replied with an error: %s, %s", - derr.name, derr.message); - dbus_error_free(&derr); - dbus_message_unref(reply); - - g_set_error(&gerr, OBEX_IO_ERROR, -ECANCELED, "%s", - derr.message); - session_terminate_transfer(session, transfer, gerr); - g_clear_error(&gerr); + if (err != NULL) { + DBusMessage *error = g_dbus_create_error(message, + ERROR_INTERFACE ".Failed", + "%s", err->message); + g_dbus_send_message(session->conn, error); + goto done; + } - return; + perr = obc_transfer_get_contents(transfer, &contents, &size); + if (perr < 0) { + DBusMessage *error = g_dbus_create_error(message, + ERROR_INTERFACE ".Failed", + "Error reading contents: %s", + strerror(-perr)); + g_dbus_send_message(session->conn, error); + goto done; } - dbus_message_get_args(reply, NULL, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID); + g_dbus_send_reply(session->conn, message, + DBUS_TYPE_STRING, &contents, + DBUS_TYPE_INVALID); + g_free(contents); - DBG("Agent.Request() reply: %s", name); +done: + dbus_message_unref(message); +} - if (strlen(name) == 0) - goto done; +static DBusMessage *get_capabilities(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct obc_session *session = user_data; + struct obc_transfer *pull; + DBusMessage *reply; + GError *gerr = NULL; - if (obc_transfer_get_operation(transfer) == G_OBEX_OP_PUT) { - obc_transfer_set_name(transfer, name); - goto done; - } + pull = obc_transfer_get("x-obex/capability", NULL, NULL, &gerr); + if (pull == NULL) + goto fail; - err = obc_transfer_set_filename(transfer, name); - if (err < 0) { - GError *gerr = NULL; + if (!obc_session_queue(session, pull, capabilities_complete_callback, + message, &gerr)) + goto fail; - g_set_error(&gerr, OBEX_IO_ERROR, err, - "Unable to set filename"); - session_terminate_transfer(session, transfer, gerr); - g_clear_error(&gerr); - return; - } + dbus_message_ref(message); -done: - if (p->auth_complete) - p->auth_complete(session, transfer); + return NULL; - dbus_message_unref(reply); +fail: + reply = g_dbus_create_error(message, ERROR_INTERFACE ".Failed", "%s", + gerr->message); + g_error_free(gerr); + return reply; - return; } -static gboolean session_request_proceed(gpointer data) +static const GDBusMethodTable session_methods[] = { + { GDBUS_METHOD("GetProperties", + NULL, GDBUS_ARGS({ "properties", "a{sv}" }), + session_get_properties) }, + { GDBUS_ASYNC_METHOD("GetCapabilities", + NULL, GDBUS_ARGS({ "capabilities", "s" }), + get_capabilities) }, + { } +}; + +static gboolean session_queue_complete(gpointer data) { struct obc_session *session = data; - struct pending_request *p = session->p; - struct obc_transfer *transfer = p->transfer; - - if (p->auth_complete) - p->auth_complete(p->session, transfer); - - return FALSE; -} -static int pending_request_auth(struct pending_request *p) -{ - struct obc_session *session = p->session; - struct obc_agent *agent = session->agent; - const char *path; + session_process_queue(session); - path = obc_transfer_get_path(p->transfer); + session->queue_complete_id = 0; - if (agent == NULL || path == NULL) { - g_idle_add(session_request_proceed, session); - return 0; - } - - return obc_agent_request(agent, path, session_request_reply, session, - NULL); + return FALSE; } guint obc_session_queue(struct obc_session *session, @@ -751,8 +648,6 @@ GError **err) { struct pending_request *p; - const char *agent; - int perr; if (session->obex == NULL) { obc_transfer_unregister(transfer); @@ -761,33 +656,20 @@ return 0; } - if (session->agent) - agent = obc_agent_get_name(session->agent); - else - agent = NULL; - - if (!obc_transfer_register(transfer, session->conn, agent, err)) { + if (!obc_transfer_register(transfer, session->conn, session->path, + session->owner, err)) { obc_transfer_unregister(transfer); return 0; } - obc_transfer_set_callback(transfer, transfer_progress, session); + obc_transfer_set_callback(transfer, transfer_complete, session); - p = pending_request_new(session, transfer, session_start_transfer, - func, user_data); - if (session->p) { - g_queue_push_tail(session->queue, p); - return p->id; - } - - perr = pending_request_auth(p); - if (perr < 0) { - g_set_error(err, OBEX_IO_ERROR, perr, "Authorization failed"); - pending_request_free(p); - return 0; - } + p = pending_request_new(session, transfer, func, user_data); + g_queue_push_tail(session->queue, p); - session->p = p; + if (session->queue_complete_id == 0) + session->queue_complete_id = g_idle_add( + session_queue_complete, session); return p->id; } @@ -805,22 +687,19 @@ obc_session_ref(session); while ((p = g_queue_pop_head(session->queue))) { - int err; + GError *gerr = NULL; - err = pending_request_auth(p); - if (err == 0) { + DBG("Transfer(%p) started", p->transfer); + + if (obc_transfer_start(p->transfer, session->obex, &gerr)) { session->p = p; break; } - if (p->func) { - GError *gerr = NULL; - - g_set_error(&gerr, OBEX_IO_ERROR, err, - "Authorization failed"); + if (p->func) p->func(session, p->transfer, gerr, p->data); - g_error_free(gerr); - } + + g_clear_error(&gerr); pending_request_free(p); } @@ -874,18 +753,6 @@ static void session_notify_complete(struct obc_session *session, struct obc_transfer *transfer) { - struct obc_agent *agent = session->agent; - const char *path; - - path = obc_transfer_get_path(transfer); - - if (agent == NULL || path == NULL) - goto done; - - obc_agent_notify_complete(agent, path); - -done: - DBG("Transfer(%p) complete", transfer); session_terminate_transfer(session, transfer, NULL); @@ -895,52 +762,20 @@ struct obc_transfer *transfer, GError *err) { - struct obc_agent *agent = session->agent; - const char *path; - - path = obc_transfer_get_path(transfer); - if (agent == NULL || path == NULL) - goto done; - - obc_agent_notify_error(agent, path, err->message); - -done: error("Transfer(%p) Error: %s", transfer, err->message); session_terminate_transfer(session, transfer, err); } -static void session_notify_progress(struct obc_session *session, - struct obc_transfer *transfer, - gint64 transferred) -{ - struct obc_agent *agent = session->agent; - const char *path; - - path = obc_transfer_get_path(transfer); - if (agent == NULL || path == NULL) - goto done; - - obc_agent_notify_progress(agent, path, transferred); - -done: - DBG("Transfer(%p) progress: %ld bytes", transfer, - (long int ) transferred); - - if (transferred == obc_transfer_get_size(transfer)) - session_notify_complete(session, transfer); -} - -static void transfer_progress(struct obc_transfer *transfer, - gint64 transferred, GError *err, - void *user_data) +static void transfer_complete(struct obc_transfer *transfer, + GError *err, void *user_data) { struct obc_session *session = user_data; if (err != 0) goto fail; - session_notify_progress(session, transfer, transferred); + session_notify_complete(session, transfer); return; @@ -948,21 +783,6 @@ session_notify_error(session, transfer, err); } -static void session_start_transfer(gpointer data, gpointer user_data) -{ - struct obc_session *session = data; - struct obc_transfer *transfer = user_data; - GError *err = NULL; - - if (!obc_transfer_start(transfer, session->obex, &err)) { - session_notify_error(session, transfer, err); - g_clear_error(&err); - return; - } - - DBG("Transfer(%p) started", transfer); -} - const char *obc_session_register(struct obc_session *session, GDBusDestroyFunction destroy) { @@ -993,49 +813,6 @@ return NULL; } -static void agent_destroy(gpointer data, gpointer user_data) -{ - struct obc_session *session = user_data; - - session->agent = NULL; -} - -int obc_session_set_agent(struct obc_session *session, const char *name, - const char *path) -{ - struct obc_agent *agent; - - if (session == NULL) - return -EINVAL; - - if (session->agent) - return -EALREADY; - - agent = obc_agent_create(session->conn, name, path, agent_destroy, - session); - - if (session->watch == 0) - obc_session_set_owner(session, name, owner_disconnected); - - session->agent = agent; - - return 0; -} - -const char *obc_session_get_agent(struct obc_session *session) -{ - struct obc_agent *agent; - - if (session == NULL) - return NULL; - - agent = session->agent; - if (agent == NULL) - return NULL; - - return obc_agent_get_name(session->agent); -} - const char *obc_session_get_owner(struct obc_session *session) { if (session == NULL) @@ -1140,7 +917,7 @@ data->user_data = user_data; data->remaining = g_strsplit(path, "/", 3); - p = pending_request_new(session, NULL, NULL, setpath_complete, data); + p = pending_request_new(session, NULL, setpath_complete, data); /* Relative path */ if (path[0] != '/') { @@ -1215,7 +992,7 @@ } - p = pending_request_new(session, NULL, NULL, func, user_data); + p = pending_request_new(session, NULL, func, user_data); p->req_id = g_obex_mkdir(session->obex, folder, async_cb, p, err); if (*err != NULL) { @@ -1244,7 +1021,7 @@ return 0; } - p = pending_request_new(session, NULL, NULL, func, user_data); + p = pending_request_new(session, NULL, func, user_data); p->req_id = g_obex_copy(session->obex, srcname, destname, async_cb, p, err); @@ -1274,7 +1051,7 @@ return 0; } - p = pending_request_new(session, NULL, NULL, func, user_data); + p = pending_request_new(session, NULL, func, user_data); p->req_id = g_obex_move(session->obex, srcname, destname, async_cb, p, err); @@ -1304,7 +1081,7 @@ return 0; } - p = pending_request_new(session, NULL, NULL, func, user_data); + p = pending_request_new(session, NULL, func, user_data); p->req_id = g_obex_delete(session->obex, file, async_cb, p, err); if (*err != NULL) { diff -Nru obexd-0.46/client/session.h obexd-0.48/client/session.h --- obexd-0.46/client/session.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/session.h 2012-07-26 19:09:25.000000000 +0200 @@ -3,6 +3,7 @@ * OBEX Client * * Copyright (C) 2007-2010 Marcel Holtmann + * Copyright (C) 2011-2012 BMW Car IT GmbH. All rights reserved. * * * This program is free software; you can redistribute it and/or modify @@ -47,10 +48,6 @@ GDBusWatchFunction func); const char *obc_session_get_owner(struct obc_session *session); -int obc_session_set_agent(struct obc_session *session, const char *name, - const char *path); -const char *obc_session_get_agent(struct obc_session *session); - const char *obc_session_get_path(struct obc_session *session); const char *obc_session_get_target(struct obc_session *session); diff -Nru obexd-0.46/client/sync.c obexd-0.48/client/sync.c --- obexd-0.46/client/sync.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/sync.c 2012-07-26 19:09:25.000000000 +0200 @@ -42,7 +42,7 @@ #define OBEX_SYNC_UUID "IRMC-SYNC" #define OBEX_SYNC_UUID_LEN 9 -#define SYNC_INTERFACE "org.openobex.Synchronization" +#define SYNC_INTERFACE "org.bluez.obex.Synchronization" #define ERROR_INF SYNC_INTERFACE ".Error" #define SYNC_UUID "00001104-0000-1000-8000-00805f9b34fb" @@ -84,53 +84,22 @@ return dbus_message_new_method_return(message); } -static void sync_getphonebook_callback(struct obc_session *session, - struct obc_transfer *transfer, - GError *err, void *user_data) -{ - struct sync_data *sync = user_data; - DBusMessage *reply; - char *contents; - size_t size; - int perr; - - if (err) { - reply = g_dbus_create_error(sync->msg, - "org.openobex.Error.Failed", - "%s", err->message); - goto send; - } - - perr = obc_transfer_get_contents(transfer, &contents, &size); - if (perr < 0) { - reply = g_dbus_create_error(sync->msg, - "org.openobex.Error.Failed", - "Error reading contents: %s", - strerror(-perr)); - goto send; - } - - reply = dbus_message_new_method_return(sync->msg); - - dbus_message_append_args(reply, DBUS_TYPE_STRING, &contents, - DBUS_TYPE_INVALID); - - g_free(contents); - -send: - g_dbus_send_message(conn, reply); - dbus_message_unref(sync->msg); - sync->msg = NULL; -} - static DBusMessage *sync_getphonebook(DBusConnection *connection, DBusMessage *message, void *user_data) { struct sync_data *sync = user_data; struct obc_transfer *transfer; + const char *target_file; GError *err = NULL; DBusMessage *reply; + if (dbus_message_get_args(message, NULL, + DBUS_TYPE_STRING, &target_file, + DBUS_TYPE_INVALID) == FALSE) + return g_dbus_create_error(message, + ERROR_INF ".InvalidArguments", + "Invalid arguments in method call"); + if (sync->msg) return g_dbus_create_error(message, ERROR_INF ".InProgress", "Transfer in progress"); @@ -139,17 +108,15 @@ if (!sync->phonebook_path) sync->phonebook_path = g_strdup("telecom/pb.vcf"); - transfer = obc_transfer_get("phonebook", sync->phonebook_path, NULL, - &err); + transfer = obc_transfer_get("phonebook", sync->phonebook_path, + target_file, &err); if (transfer == NULL) goto fail; - if (obc_session_queue(sync->session, transfer, - sync_getphonebook_callback, - sync, &err)) { - sync->msg = dbus_message_ref(message); - return NULL; - } + if (!obc_session_queue(sync->session, transfer, NULL, NULL, &err)) + goto fail; + + return obc_transfer_create_dbus_reply(transfer, message); fail: reply = g_dbus_create_error(message, ERROR_INF ".Failed", "%s", @@ -163,27 +130,30 @@ { struct sync_data *sync = user_data; struct obc_transfer *transfer; - const char *buf; + const char *source_file; GError *err = NULL; DBusMessage *reply; if (dbus_message_get_args(message, NULL, - DBUS_TYPE_STRING, &buf, - DBUS_TYPE_INVALID) == FALSE) + DBUS_TYPE_STRING, &source_file, + DBUS_TYPE_INVALID) == FALSE) return g_dbus_create_error(message, - ERROR_INF ".InvalidArguments", NULL); + ERROR_INF ".InvalidArguments", + "Invalid arguments in method call"); /* set default phonebook_path to memory internal phonebook */ if (!sync->phonebook_path) sync->phonebook_path = g_strdup("telecom/pb.vcf"); - transfer = obc_transfer_put(NULL, sync->phonebook_path, NULL, buf, - strlen(buf), &err); + transfer = obc_transfer_put(NULL, sync->phonebook_path, source_file, + NULL, 0, &err); if (transfer == NULL) goto fail; - if (obc_session_queue(sync->session, transfer, NULL, NULL, &err)) - return dbus_message_new_method_return(message); + if (!obc_session_queue(sync->session, transfer, NULL, NULL, &err)) + goto fail; + + return obc_transfer_create_dbus_reply(transfer, message); fail: reply = g_dbus_create_error(message, ERROR_INF ".Failed", "%s", @@ -192,13 +162,21 @@ return reply; } -static GDBusMethodTable sync_methods[] = { - { "SetLocation", "s", "", sync_setlocation }, - { "GetPhonebook", "", "s", sync_getphonebook, - G_DBUS_METHOD_FLAG_ASYNC }, - { "PutPhonebook", "s", "", sync_putphonebook, - G_DBUS_METHOD_FLAG_ASYNC }, - {} +static const GDBusMethodTable sync_methods[] = { + { GDBUS_METHOD("SetLocation", + GDBUS_ARGS({ "location", "s" }), NULL, + sync_setlocation) }, + { GDBUS_METHOD("GetPhonebook", + GDBUS_ARGS({ "targetfile", "s" }), + GDBUS_ARGS({ "transfer", "o" }, + { "properties", "a{sv}" }), + sync_getphonebook) }, + { GDBUS_METHOD("PutPhonebook", + GDBUS_ARGS({ "sourcefile", "s" }), + GDBUS_ARGS({ "transfer", "o" }, + { "properties", "a{sv}" }), + sync_putphonebook) }, + { } }; static void sync_free(void *data) diff -Nru obexd-0.46/client/transfer.c obexd-0.48/client/transfer.c --- obexd-0.46/client/transfer.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/transfer.c 2012-11-30 08:59:13.000000000 +0100 @@ -3,6 +3,7 @@ * OBEX Client * * Copyright (C) 2007-2010 Marcel Holtmann + * Copyright (C) 2011-2012 BMW Car IT GmbH. All rights reserved. * * * This program is free software; you can redistribute it and/or modify @@ -38,14 +39,17 @@ #include #include +#include "dbus.h" #include "log.h" #include "transfer.h" -#define TRANSFER_INTERFACE "org.openobex.Transfer" -#define TRANSFER_BASEPATH "/org/openobex" +#define TRANSFER_INTERFACE "org.bluez.obex.Transfer" +#define ERROR_INTERFACE "org.bluez.obex.Error" #define OBC_TRANSFER_ERROR obc_transfer_error_quark() +#define FIRST_PACKET_TIMEOUT 60 + static guint64 counter = 0; struct transfer_callback { @@ -53,19 +57,14 @@ void *data; }; -struct obc_transfer_params { - void *data; - size_t size; -}; - struct obc_transfer { GObex *obex; + GObexApparam *apparam; guint8 op; - struct obc_transfer_params *params; struct transfer_callback *callback; DBusConnection *conn; DBusMessage *msg; - char *agent; /* Transfer agent */ + char *owner; /* Transfer initiator */ char *path; /* Transfer path */ gchar *filename; /* Transfer file location */ char *name; /* Transfer object name */ @@ -74,6 +73,8 @@ guint xfer; gint64 size; gint64 transferred; + gint64 progress; + guint progress_id; }; static GQuark obc_transfer_error_quark(void) @@ -81,38 +82,19 @@ return g_quark_from_static_string("obc-transfer-error-quark"); } -static void append_entry(DBusMessageIter *dict, - const char *key, int type, void *val) +static void obc_transfer_append_dbus_properties(struct obc_transfer *transfer, + DBusMessageIter *dict) { - DBusMessageIter entry, value; - const char *signature; + obex_dbus_dict_append(dict, "Name", DBUS_TYPE_STRING, &transfer->name); + obex_dbus_dict_append(dict, "Size", DBUS_TYPE_UINT64, &transfer->size); - dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, - NULL, &entry); - - dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); - - switch (type) { - case DBUS_TYPE_STRING: - signature = DBUS_TYPE_STRING_AS_STRING; - break; - case DBUS_TYPE_BYTE: - signature = DBUS_TYPE_BYTE_AS_STRING; - break; - case DBUS_TYPE_UINT64: - signature = DBUS_TYPE_UINT64_AS_STRING; - break; - default: - signature = DBUS_TYPE_VARIANT_AS_STRING; - break; - } - - dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, - signature, &value); - dbus_message_iter_append_basic(&value, type, val); - dbus_message_iter_close_container(&entry, &value); - - dbus_message_iter_close_container(dict, &entry); + if (transfer->filename != NULL) + obex_dbus_dict_append(dict, "Filename", DBUS_TYPE_STRING, + &transfer->filename); + + if (transfer->obex != NULL) + obex_dbus_dict_append(dict, "Progress", DBUS_TYPE_UINT64, + &transfer->progress); } static DBusMessage *obc_transfer_get_properties(DBusConnection *connection, @@ -127,21 +109,51 @@ return NULL; dbus_message_iter_init_append(reply, &iter); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, - DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING - DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); - - append_entry(&dict, "Name", DBUS_TYPE_STRING, &transfer->name); - append_entry(&dict, "Size", DBUS_TYPE_UINT64, &transfer->size); - append_entry(&dict, "Filename", DBUS_TYPE_STRING, &transfer->filename); + OBC_PROPERTIES_ARRAY_SIGNATURE, + &dict); + + obc_transfer_append_dbus_properties(transfer, &dict); dbus_message_iter_close_container(&iter, &dict); return reply; } +static void obc_transfer_append_dbus_data(struct obc_transfer *transfer, + DBusMessageIter *iter) +{ + const char *path = transfer->path; + DBusMessageIter entry, dict; + + dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY, + OBC_PROPERTIES_ARRAY_SIGNATURE, + &dict); + + obc_transfer_append_dbus_properties(transfer, &dict); + + dbus_message_iter_close_container(&entry, &dict); + dbus_message_iter_close_container(iter, &entry); +} + +DBusMessage *obc_transfer_create_dbus_reply(struct obc_transfer *transfer, + DBusMessage *message) +{ + DBusMessage *reply; + DBusMessageIter iter; + + reply = dbus_message_new_method_return(message); + if (reply == NULL) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + obc_transfer_append_dbus_data(transfer, &iter); + + return reply; +} + static void abort_complete(GObex *obex, GError *err, gpointer user_data) { struct obc_transfer *transfer = user_data; @@ -161,28 +173,17 @@ return; if (err) { - callback->func(transfer, transfer->transferred, err, - callback->data); + callback->func(transfer, err, callback->data); } else { GError *abort_err; abort_err = g_error_new(OBC_TRANSFER_ERROR, -ECANCELED, "%s", "Transfer cancelled by user"); - callback->func(transfer, transfer->transferred, abort_err, - callback->data); + callback->func(transfer, abort_err, callback->data); g_error_free(abort_err); } } -static gboolean obc_transfer_abort(struct obc_transfer *transfer) -{ - if (transfer->xfer == 0) - return FALSE; - - return g_obex_cancel_transfer(transfer->xfer, abort_complete, - transfer); -} - static DBusMessage *obc_transfer_cancel(DBusConnection *connection, DBusMessage *message, void *user_data) { @@ -190,14 +191,39 @@ const gchar *sender; sender = dbus_message_get_sender(message); - if (g_strcmp0(transfer->agent, sender) != 0) + if (g_strcmp0(transfer->owner, sender) != 0) return g_dbus_create_error(message, - "org.openobex.Error.NotAuthorized", + ERROR_INTERFACE ".NotAuthorized", "Not Authorized"); - if (!obc_transfer_abort(transfer)) + if (transfer->msg != NULL) return g_dbus_create_error(message, - "org.openobex.Error.Failed", + ERROR_INTERFACE ".InProgress", + "Cancellation already in progress"); + + if (transfer->xfer == 0) { + struct transfer_callback *callback = transfer->callback; + + if (callback != NULL) { + GError *err; + + err = g_error_new(OBC_TRANSFER_ERROR, -ECANCELED, "%s", + "Transfer cancelled by user"); + callback->func(transfer, err, callback->data); + g_error_free(err); + } + + return dbus_message_new_method_return(message); + } + + if (transfer->progress_id != 0) { + g_source_remove(transfer->progress_id); + transfer->progress_id = 0; + } + + if (!g_obex_cancel_transfer(transfer->xfer, abort_complete, transfer)) + return g_dbus_create_error(message, + ERROR_INTERFACE ".Failed", "Failed"); transfer->msg = dbus_message_ref(message); @@ -205,9 +231,21 @@ return NULL; } -static GDBusMethodTable obc_transfer_methods[] = { - { "GetProperties", "", "a{sv}", obc_transfer_get_properties }, - { "Cancel", "", "", obc_transfer_cancel, G_DBUS_METHOD_FLAG_ASYNC }, +static const GDBusMethodTable obc_transfer_methods[] = { + { GDBUS_METHOD("GetProperties", + NULL, GDBUS_ARGS({ "properties", "a{sv}" }), + obc_transfer_get_properties) }, + { GDBUS_ASYNC_METHOD("Cancel", NULL, NULL, + obc_transfer_cancel) }, + { } +}; + +static const GDBusSignalTable obc_transfer_signals[] = { + { GDBUS_SIGNAL("PropertyChanged", + GDBUS_ARGS({ "name", "s" }, { "value", "v" })) }, + { GDBUS_SIGNAL("Complete", NULL) }, + { GDBUS_SIGNAL("Error", + GDBUS_ARGS({ "code", "s" }, { "message", "s" })) }, { } }; @@ -218,6 +256,11 @@ if (transfer->xfer) g_obex_cancel_transfer(transfer->xfer, NULL, NULL); + if (transfer->progress_id != 0) { + g_source_remove(transfer->progress_id); + transfer->progress_id = 0; + } + if (transfer->op == G_OBEX_OP_GET && transfer->transferred != transfer->size) remove(transfer->filename); @@ -225,10 +268,8 @@ if (transfer->fd > 0) close(transfer->fd); - if (transfer->params != NULL) { - g_free(transfer->params->data); - g_free(transfer->params); - } + if (transfer->apparam != NULL) + g_obex_apparam_free(transfer->apparam); if (transfer->conn) dbus_connection_unref(transfer->conn); @@ -240,7 +281,7 @@ g_obex_unref(transfer->obex); g_free(transfer->callback); - g_free(transfer->agent); + g_free(transfer->owner); g_free(transfer->filename); g_free(transfer->name); g_free(transfer->type); @@ -266,21 +307,15 @@ gboolean obc_transfer_register(struct obc_transfer *transfer, DBusConnection *conn, - const char *agent, + const char *path, + const char *owner, GError **err) { - /* for OBEX specific mime types we don't need to register a transfer */ - if (transfer->type != NULL && - (strncmp(transfer->type, "x-obex/", 7) == 0 || - strncmp(transfer->type, "x-bt/", 5) == 0)) - goto done; - - transfer->agent = g_strdup(agent); + transfer->owner = g_strdup(owner); - transfer->path = g_strdup_printf("%s/transfer%ju", - TRANSFER_BASEPATH, counter++); + transfer->path = g_strdup_printf("%s/transfer%ju", path, counter++); - transfer->conn = dbus_bus_get(DBUS_BUS_SESSION, NULL); + transfer->conn = dbus_connection_ref(conn); if (transfer->conn == NULL) { g_set_error(err, OBC_TRANSFER_ERROR, -EFAULT, "Unable to connect to D-Bus"); @@ -289,14 +324,13 @@ if (g_dbus_register_interface(transfer->conn, transfer->path, TRANSFER_INTERFACE, - obc_transfer_methods, NULL, NULL, - transfer, NULL) == FALSE) { + obc_transfer_methods, obc_transfer_signals, + NULL, transfer, NULL) == FALSE) { g_set_error(err, OBC_TRANSFER_ERROR, -EFAULT, "Unable to register to D-Bus"); return FALSE; } -done: DBG("%p registered %s", transfer, transfer->path); return TRUE; @@ -306,8 +340,9 @@ mode_t mode, GError **err) { int fd; + char *filename; - if (transfer->filename != NULL) { + if (transfer->filename != NULL && strcmp(transfer->filename, "") != 0) { fd = open(transfer->filename, flags, mode); if (fd < 0) { error("open(): %s(%d)", strerror(errno), errno); @@ -318,13 +353,19 @@ goto done; } - fd = g_file_open_tmp("obex-clientXXXXXX", &transfer->filename, err); + fd = g_file_open_tmp("obex-clientXXXXXX", &filename, err); if (fd < 0) { error("g_file_open_tmp(): %s", (*err)->message); return FALSE; } - remove(transfer->filename); + if (transfer->filename == NULL) { + remove(filename); /* remove always only if NULL was given */ + g_free(filename); + } else { + g_free(transfer->filename); + transfer->filename = filename; + } done: transfer->fd = fd; @@ -357,6 +398,13 @@ struct stat st; int perr; + if ((filename == NULL || strcmp(filename, "") == 0) && + contents == NULL) { + g_set_error(err, OBC_TRANSFER_ERROR, -EINVAL, + "Invalid filename given"); + return NULL; + } + transfer = obc_transfer_create(G_OBEX_OP_PUT, filename, name, type); if (contents != NULL) { @@ -367,23 +415,27 @@ w = write(transfer->fd, contents, size); if (w < 0) { - error("write(): %s(%d)", strerror(errno), errno); - perr = -errno; + perr = errno; + error("write(): %s(%d)", strerror(perr), perr); + g_set_error(err, OBC_TRANSFER_ERROR, -perr, + "Writing to file failed"); goto fail; } else if ((size_t) w != size) { error("Unable to write all contents to file"); - perr = -EFAULT; + g_set_error(err, OBC_TRANSFER_ERROR, -EFAULT, + "Writing all contents to file failed"); goto fail; } + lseek(transfer->fd, 0, SEEK_SET); } else { if (!transfer_open(transfer, O_RDONLY, 0, err)) goto fail; } - perr = fstat(transfer->fd, &st); - if (perr < 0) { - error("fstat(): %s(%d)", strerror(errno), errno); - g_set_error(err, OBC_TRANSFER_ERROR, -errno, + if (fstat(transfer->fd, &st) < 0) { + perr = errno; + error("fstat(): %s(%d)", strerror(perr), perr); + g_set_error(err, OBC_TRANSFER_ERROR, -perr, "Unable to get file status"); goto fail; } @@ -413,7 +465,6 @@ gpointer user_data) { struct obc_transfer *transfer = user_data; - struct transfer_callback *callback = transfer->callback; if (transfer->fd > 0) { gint w; @@ -425,10 +476,6 @@ transfer->transferred += w; } - if (callback && transfer->transferred != transfer->size) - callback->func(transfer, transfer->transferred, NULL, - callback->data); - return TRUE; } @@ -439,14 +486,36 @@ transfer->xfer = 0; - if (err) - goto done; + if (transfer->progress_id != 0) { + g_source_remove(transfer->progress_id); + transfer->progress_id = 0; + } - transfer->size = transfer->transferred; + if (err == NULL) { + transfer->size = transfer->transferred; + + if (transfer->path != NULL) + g_dbus_emit_signal(transfer->conn, transfer->path, + TRANSFER_INTERFACE, "Complete", + DBUS_TYPE_INVALID); + } else { + const char *code = ERROR_INTERFACE ".Failed"; + + if (transfer->op == G_OBEX_OP_GET && transfer->filename != NULL) + remove(transfer->filename); + + if (transfer->path != NULL) + g_dbus_emit_signal(transfer->conn, transfer->path, + TRANSFER_INTERFACE, "Error", + DBUS_TYPE_STRING, + &code, + DBUS_TYPE_STRING, + &err->message, + DBUS_TYPE_INVALID); + } -done: if (callback) - callback->func(transfer, transfer->size, err, callback->data); + callback->func(transfer, err, callback->data); } static void get_xfer_progress_first(GObex *obex, GError *err, GObexPacket *rsp, @@ -455,6 +524,7 @@ struct obc_transfer *transfer = user_data; GObexPacket *req; GObexHeader *hdr; + GObexApparam *apparam; const guint8 *buf; gsize len; guint8 rspcode; @@ -476,17 +546,9 @@ hdr = g_obex_packet_get_header(rsp, G_OBEX_HDR_APPARAM); if (hdr) { - g_obex_header_get_bytes(hdr, &buf, &len); - if (len != 0) { - if (transfer->params == NULL) - transfer->params = - g_new0(struct obc_transfer_params, 1); - else - g_free(transfer->params->data); - - transfer->params->data = g_memdup(buf, len); - transfer->params->size = len; - } + apparam = g_obex_header_get_apparam(hdr); + if (apparam != NULL) + obc_transfer_set_apparam(transfer, apparam); } hdr = g_obex_packet_get_body(rsp); @@ -513,17 +575,12 @@ static gssize put_xfer_progress(void *buf, gsize len, gpointer user_data) { struct obc_transfer *transfer = user_data; - struct transfer_callback *callback = transfer->callback; gssize size; size = read(transfer->fd, buf, len); if (size <= 0) return size; - if (callback) - callback->func(transfer, transfer->transferred, NULL, - callback->data); - transfer->transferred += size; return size; @@ -547,9 +604,33 @@ return TRUE; } +static gboolean report_progress(gpointer data) +{ + struct obc_transfer *transfer = data; + + if (transfer->transferred == transfer->progress) + return TRUE; + + transfer->progress = transfer->transferred; + + if (transfer->transferred == transfer->size) { + transfer->progress_id = 0; + return FALSE; + } + + obex_dbus_signal_property_changed(transfer->conn, + transfer->path, + TRANSFER_INTERFACE, "Progress", + DBUS_TYPE_INT64, + &transfer->progress); + + return TRUE; +} + static gboolean transfer_start_get(struct obc_transfer *transfer, GError **err) { GObexPacket *req; + GObexHeader *hdr; if (transfer->xfer > 0) { g_set_error(err, OBC_TRANSFER_ERROR, -EALREADY, @@ -567,23 +648,31 @@ g_obex_packet_add_bytes(req, G_OBEX_HDR_TYPE, transfer->type, strlen(transfer->type) + 1); - if (transfer->params != NULL) - g_obex_packet_add_bytes(req, G_OBEX_HDR_APPARAM, - transfer->params->data, - transfer->params->size); + if (transfer->apparam != NULL) { + hdr = g_obex_header_new_apparam(transfer->apparam); + g_obex_packet_add_header(req, hdr); + } - transfer->xfer = g_obex_send_req(transfer->obex, req, -1, + transfer->xfer = g_obex_send_req(transfer->obex, req, + FIRST_PACKET_TIMEOUT, get_xfer_progress_first, transfer, err); if (transfer->xfer == 0) return FALSE; + if (transfer->path == NULL) + return TRUE; + + transfer->progress_id = g_timeout_add_seconds(1, report_progress, + transfer); + return TRUE; } static gboolean transfer_start_put(struct obc_transfer *transfer, GError **err) { GObexPacket *req; + GObexHeader *hdr; if (transfer->xfer > 0) { g_set_error(err, OBC_TRANSFER_ERROR, -EALREADY, @@ -604,10 +693,10 @@ if (transfer->size < UINT32_MAX) g_obex_packet_add_uint32(req, G_OBEX_HDR_LENGTH, transfer->size); - if (transfer->params != NULL) - g_obex_packet_add_bytes(req, G_OBEX_HDR_APPARAM, - transfer->params->data, - transfer->params->size); + if (transfer->apparam != NULL) { + hdr = g_obex_header_new_apparam(transfer->apparam); + g_obex_packet_add_header(req, hdr); + } transfer->xfer = g_obex_put_req_pkt(transfer->obex, req, put_xfer_progress, xfer_complete, @@ -615,6 +704,12 @@ if (transfer->xfer == 0) return FALSE; + if (transfer->path == NULL) + return TRUE; + + transfer->progress_id = g_timeout_add_seconds(1, report_progress, + transfer); + return TRUE; } @@ -639,31 +734,20 @@ return transfer->op; } -void obc_transfer_set_params(struct obc_transfer *transfer, - const void *data, size_t size) +void obc_transfer_set_apparam(struct obc_transfer *transfer, void *data) { - if (transfer->params != NULL) { - g_free(transfer->params->data); - g_free(transfer->params); - } + if (transfer->apparam != NULL) + g_obex_apparam_free(transfer->apparam); if (data == NULL) return; - transfer->params = g_new0(struct obc_transfer_params, 1); - transfer->params->data = g_memdup(data, size); - transfer->params->size = size; + transfer->apparam = data; } -const void *obc_transfer_get_params(struct obc_transfer *transfer, size_t *size) +void *obc_transfer_get_apparam(struct obc_transfer *transfer) { - if (transfer->params == NULL) - return NULL; - - if (size != NULL) - *size = transfer->params->size; - - return transfer->params->data; + return transfer->apparam; } int obc_transfer_get_contents(struct obc_transfer *transfer, char **contents, @@ -701,29 +785,6 @@ return 0; } - -void obc_transfer_set_name(struct obc_transfer *transfer, const char *name) -{ - g_free(transfer->name); - transfer->name = g_strdup(name); -} - -int obc_transfer_set_filename(struct obc_transfer *transfer, - const char *filename) -{ - int err; - - err = rename(transfer->filename, filename); - if (err < 0) { - error("rename(): %s (%d)", strerror(errno), errno); - return -errno; - } - - g_free(transfer->filename); - transfer->filename = g_strdup(filename); - - return 0; -} const char *obc_transfer_get_path(struct obc_transfer *transfer) { diff -Nru obexd-0.46/client/transfer.h obexd-0.48/client/transfer.h --- obexd-0.46/client/transfer.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/client/transfer.h 2012-11-30 08:59:13.000000000 +0100 @@ -3,6 +3,7 @@ * OBEX Client * * Copyright (C) 2007-2010 Marcel Holtmann + * Copyright (C) 2011-2012 BMW Car IT GmbH. All rights reserved. * * * This program is free software; you can redistribute it and/or modify @@ -24,8 +25,7 @@ struct obc_transfer; typedef void (*transfer_callback_t) (struct obc_transfer *transfer, - gint64 transferred, GError *err, - void *user_data); + GError *err, void *user_data); struct obc_transfer *obc_transfer_get(const char *type, const char *name, const char *filename, GError **err); @@ -36,7 +36,8 @@ gboolean obc_transfer_register(struct obc_transfer *transfer, DBusConnection *conn, - const char *agent, + const char *path, + const char *owner, GError **err); void obc_transfer_unregister(struct obc_transfer *transfer); @@ -49,15 +50,13 @@ GError **err); guint8 obc_transfer_get_operation(struct obc_transfer *transfer); -void obc_transfer_set_params(struct obc_transfer *transfer, - const void *data, size_t size); -const void *obc_transfer_get_params(struct obc_transfer *transfer, - size_t *size); +void obc_transfer_set_apparam(struct obc_transfer *transfer, void *data); +void *obc_transfer_get_apparam(struct obc_transfer *transfer); int obc_transfer_get_contents(struct obc_transfer *transfer, char **contents, size_t *size); -void obc_transfer_set_name(struct obc_transfer *transfer, const char *name); -int obc_transfer_set_filename(struct obc_transfer *transfer, - const char *filename); const char *obc_transfer_get_path(struct obc_transfer *transfer); gint64 obc_transfer_get_size(struct obc_transfer *transfer); + +DBusMessage *obc_transfer_create_dbus_reply(struct obc_transfer *transfer, + DBusMessage *message); diff -Nru obexd-0.46/compile obexd-0.48/compile --- obexd-0.46/compile 2012-05-17 17:12:36.000000000 +0200 +++ obexd-0.48/compile 2012-11-30 08:59:31.000000000 +0100 @@ -1,7 +1,7 @@ #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. -scriptversion=2012-01-04.17; # UTC +scriptversion=2012-03-05.13; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free # Software Foundation, Inc. @@ -79,6 +79,48 @@ esac } +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () @@ -109,43 +151,34 @@ ;; esac ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; -l*) - lib=${1#-l} - found=no - save_IFS=$IFS - IFS=';' - for dir in $lib_path $LIB - do - IFS=$save_IFS - if $shared && test -f "$dir/$lib.dll.lib"; then - found=yes - set x "$@" "$dir/$lib.dll.lib" - break - fi - if test -f "$dir/$lib.lib"; then - found=yes - set x "$@" "$dir/$lib.lib" - break - fi - done - IFS=$save_IFS - - test "$found" != yes && set x "$@" "$lib.lib" + func_cl_dashl "${1#-l}" + set x "$@" "$lib" shift ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; -L*) - func_file_conv "${1#-L}" - if test -z "$lib_path"; then - lib_path=$file - else - lib_path="$lib_path;$file" - fi - linker_opts="$linker_opts -LIBPATH:$file" + func_cl_dashL "${1#-L}" ;; -static) shared=false diff -Nru obexd-0.46/config.sub obexd-0.48/config.sub --- obexd-0.46/config.sub 2012-05-17 17:12:36.000000000 +0200 +++ obexd-0.48/config.sub 2012-11-30 08:59:31.000000000 +0100 @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. -timestamp='2012-02-10' +timestamp='2012-04-18' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -225,6 +225,12 @@ -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 + ;; -lynx*) os=-lynxos ;; @@ -1537,6 +1543,9 @@ c4x-* | tic4x-*) os=-coff ;; + hexagon-*) + os=-elf + ;; tic54x-*) os=-coff ;; diff -Nru obexd-0.46/configure obexd-0.48/configure --- obexd-0.46/configure 2012-05-17 17:12:38.000000000 +0200 +++ obexd-0.48/configure 2012-11-30 08:59:33.000000000 +0100 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for obexd 0.46. +# Generated by GNU Autoconf 2.69 for obexd 0.48. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ # Identity of this package. PACKAGE_NAME='obexd' PACKAGE_TARNAME='obexd' -PACKAGE_VERSION='0.46' -PACKAGE_STRING='obexd 0.46' +PACKAGE_VERSION='0.48' +PACKAGE_STRING='obexd 0.48' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1372,7 +1372,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures obexd 0.46 to adapt to many kinds of systems. +\`configure' configures obexd 0.48 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1442,7 +1442,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of obexd 0.46:";; + short | recursive ) echo "Configuration of obexd 0.48:";; esac cat <<\_ACEOF @@ -1586,7 +1586,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -obexd configure 0.46 +obexd configure 0.48 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1951,7 +1951,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by obexd $as_me 0.46, which was +It was created by obexd $as_me 0.48, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2767,7 +2767,7 @@ # Define the identity of the package. PACKAGE='obexd' - VERSION='0.46' + VERSION='0.48' cat >>confdefs.h <<_ACEOF @@ -5748,10 +5748,6 @@ fi ;; -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - haiku*) lt_cv_deplibs_check_method=pass_all ;; @@ -5790,7 +5786,7 @@ ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; @@ -8415,7 +8411,7 @@ lt_prog_compiler_static='-non_shared' ;; - linux* | k*bsd*-gnu | kopensolaris*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) @@ -10585,17 +10581,6 @@ esac ;; -gnu*) - version_type=linux # correct to gnu/linux during the next big refactor - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no @@ -10712,7 +10697,7 @@ ;; # This must be glibc/ELF. -linux* | k*bsd*-gnu | kopensolaris*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no @@ -12152,12 +12137,12 @@ pkg_cv_BLUEZ_CFLAGS="$BLUEZ_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bluez >= 4.99\""; } >&5 - ($PKG_CONFIG --exists --print-errors "bluez >= 4.99") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bluez >= 4.100\""; } >&5 + ($PKG_CONFIG --exists --print-errors "bluez >= 4.100") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_BLUEZ_CFLAGS=`$PKG_CONFIG --cflags "bluez >= 4.99" 2>/dev/null` + pkg_cv_BLUEZ_CFLAGS=`$PKG_CONFIG --cflags "bluez >= 4.100" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -12169,12 +12154,12 @@ pkg_cv_BLUEZ_LIBS="$BLUEZ_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bluez >= 4.99\""; } >&5 - ($PKG_CONFIG --exists --print-errors "bluez >= 4.99") 2>&5 + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"bluez >= 4.100\""; } >&5 + ($PKG_CONFIG --exists --print-errors "bluez >= 4.100") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - pkg_cv_BLUEZ_LIBS=`$PKG_CONFIG --libs "bluez >= 4.99" 2>/dev/null` + pkg_cv_BLUEZ_LIBS=`$PKG_CONFIG --libs "bluez >= 4.100" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes @@ -12195,18 +12180,18 @@ _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - BLUEZ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "bluez >= 4.99" 2>&1` + BLUEZ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "bluez >= 4.100" 2>&1` else - BLUEZ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "bluez >= 4.99" 2>&1` + BLUEZ_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "bluez >= 4.100" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$BLUEZ_PKG_ERRORS" >&5 - as_fn_error $? "BlueZ >= 4.99 is required" "$LINENO" 5 + as_fn_error $? "BlueZ >= 4.100 is required" "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - as_fn_error $? "BlueZ >= 4.99 is required" "$LINENO" 5 + as_fn_error $? "BlueZ >= 4.100 is required" "$LINENO" 5 else BLUEZ_CFLAGS=$pkg_cv_BLUEZ_CFLAGS BLUEZ_LIBS=$pkg_cv_BLUEZ_LIBS @@ -13349,7 +13334,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by obexd $as_me 0.46, which was +This file was extended by obexd $as_me 0.48, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -13415,7 +13400,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -obexd config.status 0.46 +obexd config.status 0.48 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru obexd-0.46/configure.ac obexd-0.48/configure.ac --- obexd-0.46/configure.ac 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/configure.ac 2012-11-30 08:59:13.000000000 +0100 @@ -1,5 +1,5 @@ AC_PREREQ(2.60) -AC_INIT(obexd, 0.46) +AC_INIT(obexd, 0.48) AM_INIT_AUTOMAKE([foreign subdir-objects color-tests]) AM_CONFIG_HEADER(config.h) @@ -79,8 +79,8 @@ AC_SUBST(DBUS_CFLAGS) AC_SUBST(DBUS_LIBS) -PKG_CHECK_MODULES(BLUEZ, bluez >= 4.99, dummy=yes, - AC_MSG_ERROR(BlueZ >= 4.99 is required)) +PKG_CHECK_MODULES(BLUEZ, bluez >= 4.100, dummy=yes, + AC_MSG_ERROR(BlueZ >= 4.100 is required)) AC_SUBST(BLUEZ_CFLAGS) AC_SUBST(BLUEZ_LIBS) diff -Nru obexd-0.46/debian/changelog obexd-0.48/debian/changelog --- obexd-0.46/debian/changelog 2014-01-06 13:49:35.000000000 +0100 +++ obexd-0.48/debian/changelog 2014-02-02 18:14:42.000000000 +0100 @@ -1,3 +1,70 @@ +obexd (0.48-2ubuntu1) trusty; urgency=low + + * Merge from Debian unstable. (LP: #1263260) Remaining changes: + - debian/patches/tests-may-block.patch: + + Don't pass SOCK_NONBLOCK as an option for the socket type + to socketpair(), this doesn't work on buildds. + - debian/patches/test-avoid-double-source-removals.patch: + + Avoid double source removals during tests. + - debian/control: + + Drop libopenobex1 from Build-Depends, it's no longer needed + and replaced by gobex (in source). + + Replace obsolete Builds-Depends on libebook1.2-dev with + the "dummy" libical-dev (>= 1.0) phonebook driver. + * Dropped following changes, applied in Debian: + - debian/patches/includes.diff: + + Replaced with debian/patches/fix_build_libc-2.17 + - debian/rules: + + Removed --with-phonebook=ebook as well + * Fixing new upstream release. (LP: #1030463) + + -- Artur Rona Sun, 02 Feb 2014 17:46:49 +0100 + +obexd (0.48-2) unstable; urgency=low + + * Update debian/rules. + - Fix FTBFS with evolution-data-server 3.8. (Closes: #722023) + Remove "--with-phonebook=ebook" from configure. + + -- Nobuhiro Iwamatsu Fri, 20 Sep 2013 08:26:38 +0900 + +obexd (0.48-1) unstable; urgency=low + + * New upstream release. + * Fix FTBFS with eglibc-2.17. (Closes: #701434) + * Update debian/control. + - Dump version of libbluetooth-dev to 4.101. + - Dump Standard-Version to 3.9.4. + - Update Vcs-Svn and Vcs-Browser field. + - Remove Section field from obexd-client and obexd-server. + - Remove dpkg-dev from Build-Depends. + - Add autotools-dev to Build-Depends. + * Update debian/rules. + - Use autotools_dev addon. Fix lintian warning of + outdated-autotools-helper-file. + + -- Nobuhiro Iwamatsu Tue, 23 Jul 2013 08:56:32 +0900 + +obexd (0.47-2) experimental; urgency=low + + * Update debian/control. + - Remove obex-data-server from Conflicts field. (Closes: #695013, #565318) + Version 0.47 changed the D-Bus namespace to use org.bluez.obex + instead of org.openobex. + * Update debian/rules. + - Add --disable-silent-rules to configure. + + -- Nobuhiro Iwamatsu Thu, 10 Jan 2013 19:17:00 +0900 + +obexd (0.47-1) experimental; urgency=low + + * New upstream release. + * Update debian/obexd-client.examples. + * Remove patches/Remove_left_over_glib-helper.h_support.patch. + Applied to current release. + + -- Nobuhiro Iwamatsu Sat, 28 Jul 2012 05:56:26 +0900 + obexd (0.46-1ubuntu6) trusty; urgency=medium * Avoid double source removals during tests (LP: #1263259). @@ -45,6 +112,7 @@ * New upstream release. * Change source format from 1.0 to 3.0 (quilt). + * Dump compat of debhelper. * Update debian/rules. Add support hardending option. * Fix build by glib-helper.h. diff -Nru obexd-0.46/debian/control obexd-0.48/debian/control --- obexd-0.46/debian/control 2013-06-13 14:38:52.000000000 +0200 +++ obexd-0.48/debian/control 2013-12-14 02:11:49.000000000 +0100 @@ -4,18 +4,18 @@ Maintainer: Ubuntu Developers XSBC-Original-Maintainer: Debian Bluetooth Maintainers Uploaders: Nobuhiro Iwamatsu -Build-Depends: debhelper (>= 8), dpkg-dev (>= 1.16.1~), +Build-Depends: debhelper (>= 8), + autotools-dev, libglib2.0-dev, libdbus-1-dev, - libbluetooth-dev (>= 4.99), + libbluetooth-dev (>= 4.101), libical-dev (>= 1.0) -Vcs-Svn: svn://svn.debian.org/svn/pkg-bluetooth/packages/obexd -Vcs-Browser: http://svn.debian.org/wsvn/pkg-bluetooth/packages/obexd/ +Vcs-Svn: svn://anonscm.debian.org/svn/pkg-bluetooth/packages/obexd/trunk +Vcs-Browser: http://anonscm.debian.org/viewvc/pkg-bluetooth/packages/obexd/trunk/ Homepage: http://www.bluez.org -Standards-Version: 3.9.3 +Standards-Version: 3.9.4 Package: obexd-client -Section: admin Depends: ${shlibs:Depends}, ${misc:Depends} Architecture: any Description: D-Bus OBEX client @@ -28,9 +28,7 @@ In this package the client is included. Package: obexd-server -Section: admin Depends: ${shlibs:Depends}, ${misc:Depends} -Conflicts: obex-data-server Architecture: any Description: D-Bus OBEX server Implementation of OBEX(OBject EXchange) client and server as a D-Bus service diff -Nru obexd-0.46/debian/obexd-client.examples obexd-0.48/debian/obexd-client.examples --- obexd-0.46/debian/obexd-client.examples 2012-09-11 21:38:04.000000000 +0200 +++ obexd-0.48/debian/obexd-client.examples 2013-07-25 05:44:36.000000000 +0200 @@ -2,6 +2,7 @@ test/ftp-client test/list-folders test/pbap-client -test/pull-business-card -test/send-files +test/opp-client +test/simple-agent +test/map-client debian/README.examples diff -Nru obexd-0.46/debian/patches/fix_build_libc-2.17 obexd-0.48/debian/patches/fix_build_libc-2.17 --- obexd-0.46/debian/patches/fix_build_libc-2.17 1970-01-01 01:00:00.000000000 +0100 +++ obexd-0.48/debian/patches/fix_build_libc-2.17 2013-07-25 05:44:36.000000000 +0200 @@ -0,0 +1,37 @@ +Description: Fix FTBFS with libc 2.17 +Origin: upstream +Bug-Debian: http://bugs.debian.org/701434 +Forwarded: no. Because obexd will merge to bluez. +Last-Update: 2013-06-04 + +--- obexd-0.48.orig/src/mimetype.h ++++ obexd-0.48/src/mimetype.h +@@ -20,6 +20,7 @@ + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ ++#include + + typedef gboolean (*obex_object_io_func) (void *object, int flags, int err, + void *user_data); +--- obexd-0.48.orig/src/obex.h ++++ obexd-0.48/src/obex.h +@@ -21,6 +21,7 @@ + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ ++#include + + #define OBJECT_SIZE_UNKNOWN -1 + #define OBJECT_SIZE_DELETE -2 +--- obexd-0.48.orig/plugins/filesystem.h ++++ obexd-0.48/plugins/filesystem.h +@@ -21,6 +21,8 @@ + * + */ + ++#include ++ + ssize_t string_read(void *object, void *buf, size_t count); + gboolean is_filename(const char *name); + int verify_path(const char *path); diff -Nru obexd-0.46/debian/patches/includes.diff obexd-0.48/debian/patches/includes.diff --- obexd-0.46/debian/patches/includes.diff 2013-04-02 19:08:31.000000000 +0200 +++ obexd-0.48/debian/patches/includes.diff 1970-01-01 01:00:00.000000000 +0100 @@ -1,39 +0,0 @@ -Index: b/plugins/filesystem.h -=================================================================== ---- a/plugins/filesystem.h 2012-05-17 15:12:17.000000000 +0000 -+++ b/plugins/filesystem.h 2013-04-02 16:59:27.433752030 +0000 -@@ -21,6 +21,8 @@ - * - */ - -+#include -+ - ssize_t string_read(void *object, void *buf, size_t count); - gboolean is_filename(const char *name); - int verify_path(const char *path); -Index: b/src/mimetype.h -=================================================================== ---- a/src/mimetype.h 2012-05-17 15:12:17.000000000 +0000 -+++ b/src/mimetype.h 2013-04-02 16:59:20.197702060 +0000 -@@ -21,6 +21,8 @@ - * - */ - -+#include -+ - typedef gboolean (*obex_object_io_func) (void *object, int flags, int err, - void *user_data); - -Index: b/src/obex.h -=================================================================== ---- a/src/obex.h 2012-05-17 15:12:17.000000000 +0000 -+++ b/src/obex.h 2013-04-02 16:59:07.709616787 +0000 -@@ -22,6 +22,8 @@ - * - */ - -+#include -+ - #define OBJECT_SIZE_UNKNOWN -1 - #define OBJECT_SIZE_DELETE -2 - diff -Nru obexd-0.46/debian/patches/Remove_left_over_glib-helper.h_support.patch obexd-0.48/debian/patches/Remove_left_over_glib-helper.h_support.patch --- obexd-0.46/debian/patches/Remove_left_over_glib-helper.h_support.patch 2012-09-11 21:38:04.000000000 +0200 +++ obexd-0.48/debian/patches/Remove_left_over_glib-helper.h_support.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,44 +0,0 @@ -Origin: http://git.kernel.org/?p=bluetooth/obexd.git;a=commit;h=1ae7e0cceccf301fef421f615e784e08efb581ee -Bug: None -Bug-Debian: None -Bug-Ubuntu: None -Forwarded: no -Reviewed-By: No, this patch already applied in upstream. -Last-Update: 2012/06/01 - -From 1ae7e0cceccf301fef421f615e784e08efb581ee Mon Sep 17 00:00:00 2001 -From: Paul Seidler -Date: Mon, 21 May 2012 16:59:27 +0200 -Subject: [PATCH] Remove left over glib-helper.h support - ---- - plugins/phonebook-ebook.c | 1 - - plugins/phonebook-tracker.c | 1 - - 2 files changed, 0 insertions(+), 2 deletions(-) - -diff --git a/plugins/phonebook-ebook.c b/plugins/phonebook-ebook.c -index c2e8649..a1f06b5 100644 ---- a/plugins/phonebook-ebook.c -+++ b/plugins/phonebook-ebook.c -@@ -37,7 +37,6 @@ - #include "obex.h" - #include "service.h" - #include "phonebook.h" --#include "glib-helper.h" - - #define QUERY_FN "(contains \"family_name\" \"%s\")" - #define QUERY_NAME "(contains \"given_name\" \"%s\")" -diff --git a/plugins/phonebook-tracker.c b/plugins/phonebook-tracker.c -index da82ff5..96635c4 100644 ---- a/plugins/phonebook-tracker.c -+++ b/plugins/phonebook-tracker.c -@@ -35,7 +35,6 @@ - #include "mimetype.h" - #include "phonebook.h" - #include "vcard.h" --#include "glib-helper.h" - - #define TRACKER_SERVICE "org.freedesktop.Tracker1" - #define TRACKER_RESOURCES_PATH "/org/freedesktop/Tracker1/Resources" --- -1.7.6.5 diff -Nru obexd-0.46/debian/patches/series obexd-0.48/debian/patches/series --- obexd-0.46/debian/patches/series 2014-01-06 13:07:57.000000000 +0100 +++ obexd-0.48/debian/patches/series 2014-02-02 18:13:10.000000000 +0100 @@ -1,4 +1,3 @@ -Remove_left_over_glib-helper.h_support.patch +fix_build_libc-2.17 test-may-block.patch -includes.diff test-avoid-double-source-removals.patch diff -Nru obexd-0.46/debian/patches/test-may-block.patch obexd-0.48/debian/patches/test-may-block.patch --- obexd-0.46/debian/patches/test-may-block.patch 2012-09-11 21:38:04.000000000 +0200 +++ obexd-0.48/debian/patches/test-may-block.patch 2014-02-02 17:47:09.000000000 +0100 @@ -8,10 +8,10 @@ safely by just not passing this option. This will allow keeping the tests running ;) -Index: obexd-0.43/unit/util.c +Index: obexd-0.48/unit/util.c =================================================================== ---- obexd-0.43.orig/unit/util.c 2011-12-21 18:24:49.000000000 -0500 -+++ obexd-0.43/unit/util.c 2012-01-06 14:00:12.360087805 -0500 +--- obexd-0.48.orig/unit/util.c 2012-05-17 17:12:17.000000000 +0200 ++++ obexd-0.48/unit/util.c 2014-02-02 17:47:00.000000000 +0100 @@ -87,7 +87,7 @@ GObexTransportType transport_type; int sv[2]; diff -Nru obexd-0.46/debian/rules obexd-0.48/debian/rules --- obexd-0.46/debian/rules 2012-09-11 21:45:56.000000000 +0200 +++ obexd-0.48/debian/rules 2013-09-20 01:25:17.000000000 +0200 @@ -4,8 +4,11 @@ include /usr/share/dpkg/buildflags.mk %: - dh $@ + dh $@ --with autotools_dev override_dh_auto_configure: + dh_autotools-dev_updateconfig + dh_auto_configure -- --enable-usb \ - --enable-pcsuite + --enable-pcsuite \ + --disable-silent-rules diff -Nru obexd-0.46/depcomp obexd-0.48/depcomp --- obexd-0.46/depcomp 2012-05-17 17:12:37.000000000 +0200 +++ obexd-0.48/depcomp 2012-11-30 08:59:32.000000000 +0100 @@ -1,10 +1,10 @@ #! /bin/sh # depcomp - compile a program generating dependencies as side-effects -scriptversion=2011-12-04.11; # UTC +scriptversion=2012-03-27.16; # UTC # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010, -# 2011 Free Software Foundation, Inc. +# 2011, 2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -28,7 +28,7 @@ case $1 in '') - echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) @@ -40,8 +40,8 @@ Environment variables: depmode Dependency tracking mode. - source Source file read by `PROGRAMS ARGS'. - object Object file output by `PROGRAMS ARGS'. + source Source file read by 'PROGRAMS ARGS'. + object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. @@ -57,6 +57,12 @@ ;; esac +# A tabulation character. +tab=' ' +# A newline character. +nl=' +' + if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 @@ -102,6 +108,12 @@ depmode=msvc7 fi +if test "$depmode" = xlc; then + # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations. + gccflag=-qmakedep=gcc,-MF + depmode=gcc +fi + case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what @@ -156,15 +168,14 @@ ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the `deleted header file' problem. +## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. - tr ' ' ' -' < "$tmpdepfile" | -## Some versions of gcc put a space before the `:'. On the theory + tr ' ' "$nl" < "$tmpdepfile" | +## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. @@ -203,18 +214,15 @@ # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like `#:fec' to the end of the + # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. - tr ' ' ' -' < "$tmpdepfile" \ + tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr ' -' ' ' >> "$depfile" + tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. - tr ' ' ' -' < "$tmpdepfile" \ + tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else @@ -226,10 +234,17 @@ rm -f "$tmpdepfile" ;; +xlc) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts `$object:' at the + # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` @@ -259,12 +274,11 @@ test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then - # Each line is of the form `foo.o: dependent.h'. + # Each line is of the form 'foo.o: dependent.h'. # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. + # '$object: dependent.h' and one to simply 'dependent.h:'. sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a tab and a space in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile @@ -275,23 +289,26 @@ ;; icc) - # Intel's C compiler understands `-MD -MF file'. However on - # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'. + # However on + # $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h - # which is wrong. We want: + # which is wrong. We want # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using \ : + # and will wrap long lines using '\': # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... - + # tcc 0.9.26 (FIXME still under development at the moment of writing) + # will emit a similar output, but also prepend the continuation lines + # with horizontal tabulation characters. "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : @@ -300,15 +317,21 @@ exit $stat fi rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h', - # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Each line is of the form 'foo.o: dependent.h', + # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'. # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | - sed -e 's/$/ :/' >> "$depfile" + # '$object: dependent.h' and one to simply 'dependent.h:'. + sed -e "s/^[ $tab][ $tab]*/ /" -e "s,^[^:]*:,$object :," \ + < "$tmpdepfile" > "$depfile" + sed ' + s/[ '"$tab"'][ '"$tab"']*/ /g + s/^ *// + s/ *\\*$// + s/^[^:]*: *// + /^$/d + /:$/d + s/$/ :/ + ' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; @@ -344,7 +367,7 @@ done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" - # Add `dependent.h:' lines. + # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// @@ -359,9 +382,9 @@ tru64) # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in `foo.d' instead, so we check for that too. + # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= @@ -407,8 +430,7 @@ done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a tab and a space in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi @@ -443,11 +465,11 @@ p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g -s/\(.*\)/ \1 \\/p +s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { - s/.*/ / + s/.*/'"$tab"'/ G p }' >> "$depfile" @@ -478,7 +500,7 @@ shift fi - # Remove `-o $object'. + # Remove '-o $object'. IFS=" " for arg do @@ -498,15 +520,14 @@ done test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for `:' + # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: - # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | - sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" - tr ' ' ' -' < "$tmpdepfile" | \ + tr ' ' "$nl" < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" @@ -562,8 +583,7 @@ # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' ' -' | \ + sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" @@ -583,7 +603,7 @@ shift fi - # Remove `-o $object'. + # Remove '-o $object'. IFS=" " for arg do @@ -652,8 +672,8 @@ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" - sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" - echo " " >> "$depfile" + sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" + echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; diff -Nru obexd-0.46/doc/agent-api.txt obexd-0.48/doc/agent-api.txt --- obexd-0.46/doc/agent-api.txt 2010-04-23 17:52:33.000000000 +0200 +++ obexd-0.48/doc/agent-api.txt 2012-07-26 19:09:25.000000000 +0200 @@ -9,7 +9,7 @@ =============== Service unique name -Interface org.openobex.Agent +Interface org.bluez.obex.Agent Object path freely definable Methods @@ -21,8 +21,8 @@ Returns the full path (including the filename) where the object shall be stored. - Possible errors: org.openobex.Error.Rejected - org.openobex.Error.Canceled + Possible errors: org.bluez.obex.Error.Rejected + org.bluez.obex.Error.Canceled void Cancel() diff -Nru obexd-0.46/doc/client-api.txt obexd-0.48/doc/client-api.txt --- obexd-0.46/doc/client-api.txt 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/doc/client-api.txt 2012-11-30 08:59:13.000000000 +0100 @@ -2,85 +2,116 @@ *************************** Copyright (C) 2007-2010 Marcel Holtmann +Copyright (C) 2011-2012 BMW Car IT GmbH. All rights reserved. Client hierarchy ================ -Service org.openobex.client -Interface org.openobex.Client +Service org.bluez.obex.client +Interface org.bluez.obex.Client Object path / -Methods void SendFiles(dict device, array{string} files, object agent) +Methods object CreateSession(string destination, dict args) - Send one or multiple local files to the specified - device. The device is configured via properties. At - least the Destination property should be specified. + Create a new OBEX session for the given remote address. - void PullBusinessCard(dict device, string file) + The last parameter is a dictionary to hold optional or + type-specific parameters. Typical parameters that can + be set in this dictionary include the following: - Request the business card from a remote device and - store it in the local file. - - void ExchangeBusinessCards(dict device, string clientfile, - string file) - - Push the client's business card to the remote device - and then retrieve the remote business card and store - it in a local file. + string "Target" : type of session to be created + string "Source" : local address to be used + byte "Channel" - object CreateSession(dict device) + The currently supported targets are the following: - Create a new OBEX session. The device is configured - via properties like in SendFiles. + "FTP" + "MAP" + "OPP" + "PBAP" + "SYNC" void RemoveSession(object session) Unregister session and abort pending transfers. - string GetCapabilities(dict device) +Session hierarchy +================= - Get remote device capabilities. +Service org.bluez.obex.client +Interface org.bluez.obex.Session +Object path [variable prefix]/{session0,session1,...} -Properties string Target +Methods dict GetProperties() - string Source + Returns all properties for the session. - string Destination + string GetCapabilities() - byte Channel + Get remote device capabilities. -Session hierarchy -================= +Properties string Source [readonly] + + string Destination [readonly] -Service org.openobex.client -Interface org.openobex.Session + byte Channel [readonly] + +Object Push hierarchy +===================== + +Service org.bluez.obex.client +Interface org.bluez.obex.ObjectPush Object path [variable prefix]/{session0,session1,...} -Methods dict GetProperties() +Methods object, dict SendFile(string sourcefile) - Returns all properties for the session. + Send one local file to the remote device. - void AssignAgent(object agent) + The returned path represents the newly created transfer, + which should be used to find out if the content has been + successfully transferred or if the operation fails. - Assign an OBEX agent to this session. This allows - detailed progress reports about the transactions. + The properties of this transfer are also returned along + with the object path, to avoid a call to GetProperties. - void ReleaseAgent(object agent) + object, dict PullBusinessCard(string targetfile) - Release a previously assigned OBEX agent. + Request the business card from a remote device and + store it in the local file. -Properties string Source [readonly] + If an empty target file is given, a name will be + automatically calculated for the temporary file. - string Destination [readonly] + The returned path represents the newly created transfer, + which should be used to find out if the content has been + successfully transferred or if the operation fails. - byte Channel [readonly] + The properties of this transfer are also returned along + with the object path, to avoid a call to GetProperties. + + object, dict ExchangeBusinessCards(string clientfile, + string targetfile) + + Push the client's business card to the remote device + and then retrieve the remote business card and store + it in a local file. + + If an empty target file is given, a name will be + automatically calculated for the temporary file. + + The returned path represents the newly created transfer, + which should be used to find out if the content has been + successfully transferred or if the operation fails. + + The properties of this transfer are also returned along + with the object path, to avoid a call to GetProperties. File Transfer hierarchy ======================= -Service org.openobex.client -Interface org.openobex.FileTransfer +Service org.bluez.obex.client +Interface org.bluez.obex.FileTransfer Object path [variable prefix]/{session0,session1,...} Methods void ChangeFolder(string folder) @@ -108,21 +139,32 @@ uint64 Accessed : Last access uint64 Created : Creation date - void GetFile(string targetfile, string sourcefile) + object, dict GetFile(string targetfile, string sourcefile) Copy the source file (from remote device) to the target file (on local filesystem). - A new Transfer object is created to represent this - transaction. + If an empty target file is given, a name will be + automatically calculated for the temporary file. - void PutFile(string sourcefile, string targetfile) + The returned path represents the newly created transfer, + which should be used to find out if the content has been + successfully transferred or if the operation fails. + + The properties of this transfer are also returned along + with the object path, to avoid a call to GetProperties. + + object, dict PutFile(string sourcefile, string targetfile) Copy the source file (from local filesystem) to the target file (on remote device). - A new Transfer object is created to represent this - transaction. + The returned path represents the newly created transfer, + which should be used to find out if the content has been + successfully transferred or if the operation fails. + + The properties of this transfer are also returned along + with the object path, to avoid a call to GetProperties. void CopyFile(string sourcefile, string targetfile) @@ -141,8 +183,8 @@ Phonebook Access hierarchy ======================= -Service org.openobex.client -Interface org.openobex.PhonebookAccess +Service org.bluez.obex.client +Interface org.bluez.obex.PhonebookAccess Object path [variable prefix]/{session0,session1,...} Methods void Select(string location, string phonebook) @@ -164,78 +206,115 @@ "mch": missing call history "cch": combination of ich och mch - string PullAll() + object, dict PullAll(string targetfile, dict filters) Return the entire phonebook object from the PSE server - in plain string with vcard format. + in plain string with vcard format, and store it in + a local file. + + If an empty target file is given, a name will be + automatically calculated for the temporary file. + + The returned path represents the newly created transfer, + which should be used to find out if the content has been + successfully transferred or if the operation fails. + + The properties of this transfer are also returned along + with the object path, to avoid a call to GetProperties. + + Possible filters: Format, Order, Offset, MaxCount and + Fields + + array{string vcard, string name} List(dict filters) + + Return an array of vcard-listing data where every entry + consists of a pair of strings containing the vcard + handle and the contact name. For example: + "1.vcf" : "John" + + Possible filters: Order, Offset and MaxCount + + + object, dict + Pull(string vcard, string targetfile, dict filters) - array{string vcard, string name} List() + Given a vcard handle, retrieve the vcard in the current + phonebook object and store it in a local file. - Return an array of vcard-listing data which contains the - vcard : name paired string, for example "1.vcf" : - "John". + If an empty target file is given, a name will be + automatically calculated for the temporary file. - string Pull(string vcard) + The returned path represents the newly created transfer, + which should be used to find out if the content has been + successfully transferred or if the operation fails. + + The properties of this transfer are also returned along + with the object path, to avoid a call to GetProperties. + + Possbile filters: Format and Fields - Retrieve the vcard in the current phonebook object - for example : Pull("0.vcf") array{string vcard, string name} - Search(string field, string value) + Search(string field, string value, dict filters) + + Search for entries matching the given condition and + return an array of vcard-listing data where every entry + consists of a pair of strings containing the vcard + handle and the contact name. - Return an array of vcard-listing data which contains the vcard : name paired string match the search condition. field : the field in the vcard to search with { "name" (default) | "number" | "sound" } value : the string value to search for + + Possible filters: Order, Offset and MaxCount + uint16 GetSize() - Return the number of the non-null entries in the - selected phonebook object. + Return the number of entries in the selected phonebook + object that are actually used (i.e. indexes that + correspond to non-NULL entries). + + array{string} ListFilterFields() - void SetFormat(string format) + Return All Available fields that can be used in Fields + filter. - Indicate the format of the vcard that should be return - by related methods. +Filter: string Format: - format : { "vcard21" (default) | "vcard30" } + Items vcard format - void SetOrder(string order) + Possible values: "vcard21" (default) or "vcard30" - Indicate the sorting method of the vcard-listing data - returned by List and Search methods. + string Order: - order : { "indexed" (default) | "alphanumeric" | - "phonetic" } + Items order - void SetFilter(array{string}) + Possible values: "indexed" (default), "alphanumeric" or + "phonetic" - Indicate fields that should be contained in vcards - return by related methods. + uint16 Offset: - Give an empty array will clear the filter and return - all fields available in vcards. And this is the default - behavior. + Offset of the first item, default is 0 - Possible filter fields : "VERSION", "FN", ..., "ALL", - "bit[0-63]" + uint16 MaxCount: - array{string} ListFilterFields() + Maximum number of items, default is unlimited (65535) + + array{string} Fields: - Return All Available fields that can be used in - SefFilter method. + Item vcard fields, default is all values. - array{string} GetFilter() + Possible values can be query with ListFilterFields. - Return the current filter setting Synchronization hierarchy ======================= -Service org.openobex.client -Interface org.openobex.Synchronization +Service org.bluez.obex.client +Interface org.bluez.obex.Synchronization Object path [variable prefix]/{session0,session1,...} Methods void SetLocation(string location) @@ -251,20 +330,37 @@ "SIM2" ...... - string GetPhonebook() + object, dict GetPhonebook(string targetfile) Retrieve an entire Phonebook Object store from remote - device + device, and stores it in a local file. + + If an empty target file is given, a name will be + automatically calculated for the temporary file. + + The returned path represents the newly created transfer, + which should be used to find out if the content has been + successfully transferred or if the operation fails. + + The properties of this transfer are also returned along + with the object path, to avoid a call to GetProperties. - void PutPhonebook(string obj) + object, dict PutPhonebook(string sourcefile) - Send an entire Phonebook Object store to remote device + Send an entire Phonebook Object store to remote device. + + The returned path represents the newly created transfer, + which should be used to find out if the content has been + successfully transferred or if the operation fails. + + The properties of this transfer are also returned along + with the object path, to avoid a call to GetProperties. Message Access hierarchy ========================= -Service org.openobex.client -Interface org.openobex.MessageAccess +Service org.bluez.obex.client +Interface org.bluez.obex.MessageAccess Object path [variable prefix]/{session0,session1,...} Methods void SetFolder(string name) @@ -272,12 +368,262 @@ Set working directory for current session, *name* may be the directory name or '..[/dir]'. + array{dict} ListFolders(dict filter) + + Returns a dictionary containing information about + the current folder content. + + The following keys are defined: + + string Name : Folder name + + Possible filters: Offset and MaxCount + + array{string} ListFilterFields() + + Return all available fields that can be used in Fields + filter. + + array{object, dict} ListMessages(string folder, dict filter) + + Returns an array containing the messages found in the + given folder. + + Possible Filters: Offset, MaxCount, Fields, Type, + PeriodStart, PeriodEnd, Status, Recipient, Sender, + Priority + + Each message is represented by an object path followed + by a dictionary of the properties. + + Properties: + + string Subject: + + Message subject + + string Timestamp: + + Message timestamp + + string Sender: + + Message sender name + + string SenderAddress: + + Message sender address + + string ReplyTo: + + Message Reply-To address + + string Recipient: + + Message recipient name + + string RecipientAddress: + + Message recipient address + + string Type: + + Message type + + Possible values: "EMAIL", "SMS_GSM", + "SMS_CDMA" and "MMS" + + uint64 Size: + + Message size in bytes + + string Status: + + Message reception status + + Possible values: "complete", + "fractioned" and "notification" + + boolean Priority: + + Message priority flag + + boolean Read: + + Message read flag + + boolean Sent: + + Message sent flag + + boolean Protected: + + Message protected flag + + void UpdateInbox(void) + + Request remote to update its inbox. + + +Filter: uint16 Offset: + + Offset of the first item, default is 0 + + uint16 MaxCount: + + Maximum number of items, default is 1024 + + array{string} Fields: + + Message fields, default is all values. + + Possible values can be query with ListFilterFields. + + array{string} Types: + + Filter messages by type. + + Possible values: "sms", "email", "mms". + + string PeriodBegin: + + Filter messages by starting period. + + Possible values: Date in "YYYYMMDDTHHMMSS" format. + + string PeriodEnd: + + Filter messages by ending period. + + Possible values: Date in "YYYYMMDDTHHMMSS" format. + + boolean Read: + + Filter messages by read flag. + + Possible values: True for read or False for unread + + string Recipient: + + Filter messages by recipient address. + + string Sender: + + Filter messages by sender address. + + gboolean Priority: + + Filter messages by priority flag. + + Possible values: True for high priority or False for + non-high priority + +Message hierarchy +================= + +Service org.bluez.obex.client +Interface org.bluez.obex.Message +Object path [variable prefix]/{session0,session1,...}/{message0,...} + +Methods object, dict Get(string targetfile, boolean attachment) + + Download message and store it in the target file. + + If an empty target file is given, a temporary file + will be automatically generated. + + The returned path represents the newly created transfer, + which should be used to find out if the content has been + successfully transferred or if the operation fails. + + The properties of this transfer are also returned along + with the object path, to avoid a call to GetProperties. + + dict GetProperties() + + Returns all properties for the message. See the + properties section for available properties. + + void SetProperty (string name, variant value) + + Sets value to the mentioned property. + + Possible properties: Read and Deleted. + + +Properties string Subject [readonly] + + Message subject + + string Timestamp [readonly] + + Message timestamp + + string Sender [readonly] + + Message sender name + + string SenderAddress [readonly] + + Message sender address + + string ReplyTo [readonly] + + Message Reply-To address + + string Recipient [readonly] + + Message recipient name + + string RecipientAddress [readonly] + + Message recipient address + + string Type [readonly] + + Message type + + Possible values: "EMAIL", "SMS_GSM", + "SMS_CDMA" and "MMS" + + uint64 Size [readonly] + + Message size in bytes + + string Status [readonly] + + Message reception status + + Possible values: "complete", + "fractioned" and "notification" + + boolean Priority [readonly] + + Message priority flag + + boolean Read [read/write] + + Message read flag + + boolean Deleted [writeonly] + + Message read flag + + boolean Sent [readonly] + + Message sent flag + + boolean Protected [readonly] + + Message protected flag + + Transfer hierarchy ================== -Service org.openobex.client -Interface org.openobex.Transfer -Object path [variable prefix]/{transfer0,transfer1,...} +Service org.bluez.obex.client +Interface org.bluez.obex.Transfer +Object path [variable prefix]/{session0,session1,...}/{transfer0,...} Methods dict GetProperties() @@ -297,49 +643,25 @@ Size of the transferred object. If the size is unknown, then this property will not be present. - string Filename [readonly] + string Filename [readonly, optional] Complete name of the file being received or sent. -Agent hierarchy -=============== - -Service unique name -Interface org.openobex.Agent -Object path freely definable - -Methods void Release() - - This method gets called when the service daemon - unregisters the agent. An agent can use it to do - cleanup tasks. There is no need to unregister the - agent, because when this method gets called it has - already been unregistered. - - string Request(object transfer) - - Accept or reject a new transfer (client and server) - and provide the filename for it. - - In case of incoming transfers it is the filename - where to store the file and for outgoing transfers - it is the filename to show the remote device. If left - empty it will be calculated automatically. + uint64 Progress [readonly, optional] - Possible errors: org.openobex.Error.Rejected - org.openobex.Error.Canceled + Number of bytes transferred. For queued transfers, this + value will not be present. - void Progress(object transfer, uint64 transferred) +Signals PropertyChanged(string name, variant value) - Progress within the transfer has been made. The - number of transferred bytes is given as second - argument for convenience. + This signal indicates a changed value of the given + property. - void Complete(object transfer) + void Complete() Informs that the transfer has completed successfully. - void Error(object transfer, string message) + void Error(string code, string message) Informs that the transfer has been terminated because of some error. diff -Nru obexd-0.46/doc/obexd-api.txt obexd-0.48/doc/obexd-api.txt --- obexd-0.46/doc/obexd-api.txt 2010-04-23 17:52:33.000000000 +0200 +++ obexd-0.48/doc/obexd-api.txt 2012-07-26 19:09:25.000000000 +0200 @@ -8,8 +8,8 @@ Manager hierarchy =============== -Service org.openobex -Interface org.openobex.Manager +Service org.bluez.obex +Interface org.bluez.obex.Manager Object path / Methods @@ -19,7 +19,7 @@ the user to accept/reject objects. Object push service needs to authorize each received object. - Possible errors: org.openobex.Error.AlreadyExists + Possible errors: org.bluez.obex.Error.AlreadyExists void UnregisterAgent(object agent) @@ -27,7 +27,7 @@ registered. The object path parameter must match the same value that has been used on registration. - Possible errors: org.openobex.Error.DoesNotExist + Possible errors: org.bluez.obex.Error.DoesNotExist Signals SessionCreated(object session) @@ -54,8 +54,8 @@ Transfer hierarchy =============== -Service org.openobex -Interface org.openobex.Transfer +Service org.bluez.obex +Interface org.bluez.obex.Transfer Object path /transfer{0, 1, 2, ...} Methods @@ -70,8 +70,8 @@ Session hierarchy =============== -Service org.openobex -Interface org.openobex.Session +Service org.bluez.obex +Interface org.bluez.obex.Session Object path /session{0, 1, 2, ...} Methods diff -Nru obexd-0.46/gdbus/gdbus.h obexd-0.48/gdbus/gdbus.h --- obexd-0.46/gdbus/gdbus.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/gdbus/gdbus.h 2012-11-30 08:59:13.000000000 +0100 @@ -31,6 +31,17 @@ #include #include +typedef enum GDBusMethodFlags GDBusMethodFlags; +typedef enum GDBusSignalFlags GDBusSignalFlags; +typedef enum GDBusPropertyFlags GDBusPropertyFlags; +typedef enum GDBusSecurityFlags GDBusSecurityFlags; + +typedef struct GDBusArgInfo GDBusArgInfo; +typedef struct GDBusMethodTable GDBusMethodTable; +typedef struct GDBusSignalTable GDBusSignalTable; +typedef struct GDBusPropertyTable GDBusPropertyTable; +typedef struct GDBusSecurityTable GDBusSecurityTable; + typedef void (* GDBusWatchFunction) (DBusConnection *connection, void *user_data); @@ -55,6 +66,18 @@ typedef DBusMessage * (* GDBusMethodFunction) (DBusConnection *connection, DBusMessage *message, void *user_data); +typedef gboolean (*GDBusPropertyGetter)(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data); + +typedef guint32 GDBusPendingPropertySet; + +typedef void (*GDBusPropertySetter)(const GDBusPropertyTable *property, + DBusMessageIter *value, GDBusPendingPropertySet id, + void *data); + +typedef gboolean (*GDBusPropertyExists)(const GDBusPropertyTable *property, + void *data); + typedef guint32 GDBusPendingReply; typedef void (* GDBusSecurityFunction) (DBusConnection *connection, @@ -62,53 +85,106 @@ gboolean interaction, GDBusPendingReply pending); -typedef enum { +enum GDBusMethodFlags { G_DBUS_METHOD_FLAG_DEPRECATED = (1 << 0), G_DBUS_METHOD_FLAG_NOREPLY = (1 << 1), G_DBUS_METHOD_FLAG_ASYNC = (1 << 2), -} GDBusMethodFlags; +}; -typedef enum { +enum GDBusSignalFlags { G_DBUS_SIGNAL_FLAG_DEPRECATED = (1 << 0), -} GDBusSignalFlags; +}; -typedef enum { +enum GDBusPropertyFlags { G_DBUS_PROPERTY_FLAG_DEPRECATED = (1 << 0), -} GDBusPropertyFlags; +}; -typedef enum { +enum GDBusSecurityFlags { G_DBUS_SECURITY_FLAG_DEPRECATED = (1 << 0), G_DBUS_SECURITY_FLAG_BUILTIN = (1 << 1), G_DBUS_SECURITY_FLAG_ALLOW_INTERACTION = (1 << 2), -} GDBusSecurityFlags; +}; -typedef struct { +struct GDBusArgInfo { const char *name; const char *signature; - const char *reply; +}; + +struct GDBusMethodTable { + const char *name; GDBusMethodFunction function; GDBusMethodFlags flags; unsigned int privilege; -} GDBusMethodTable; + const GDBusArgInfo *in_args; + const GDBusArgInfo *out_args; +}; -typedef struct { +struct GDBusSignalTable { const char *name; - const char *signature; GDBusSignalFlags flags; -} GDBusSignalTable; + const GDBusArgInfo *args; +}; -typedef struct { +struct GDBusPropertyTable { const char *name; const char *type; + GDBusPropertyGetter get; + GDBusPropertySetter set; + GDBusPropertyExists exists; GDBusPropertyFlags flags; -} GDBusPropertyTable; +}; -typedef struct { +struct GDBusSecurityTable { unsigned int privilege; const char *action; GDBusSecurityFlags flags; GDBusSecurityFunction function; -} GDBusSecurityTable; +}; + +#define GDBUS_ARGS(args...) (const GDBusArgInfo[]) { args, { } } + +#define GDBUS_METHOD(_name, _in_args, _out_args, _function) \ + .name = _name, \ + .in_args = _in_args, \ + .out_args = _out_args, \ + .function = _function + +#define GDBUS_ASYNC_METHOD(_name, _in_args, _out_args, _function) \ + .name = _name, \ + .in_args = _in_args, \ + .out_args = _out_args, \ + .function = _function, \ + .flags = G_DBUS_METHOD_FLAG_ASYNC + +#define GDBUS_DEPRECATED_METHOD(_name, _in_args, _out_args, _function) \ + .name = _name, \ + .in_args = _in_args, \ + .out_args = _out_args, \ + .function = _function, \ + .flags = G_DBUS_METHOD_FLAG_DEPRECATED + +#define GDBUS_DEPRECATED_ASYNC_METHOD(_name, _in_args, _out_args, _function) \ + .name = _name, \ + .in_args = _in_args, \ + .out_args = _out_args, \ + .function = _function, \ + .flags = G_DBUS_METHOD_FLAG_ASYNC | G_DBUS_METHOD_FLAG_DEPRECATED + +#define GDBUS_NOREPLY_METHOD(_name, _in_args, _out_args, _function) \ + .name = _name, \ + .in_args = _in_args, \ + .out_args = _out_args, \ + .function = _function, \ + .flags = G_DBUS_METHOD_FLAG_NOREPLY + +#define GDBUS_SIGNAL(_name, _args) \ + .name = _name, \ + .args = _args + +#define GDBUS_DEPRECATED_SIGNAL(_name, _args) \ + .name = _name, \ + .args = _args, \ + .flags = G_DBUS_SIGNAL_FLAG_DEPRECATED gboolean g_dbus_register_interface(DBusConnection *connection, const char *path, const char *name, @@ -167,9 +243,28 @@ const char *interface, const char *member, GDBusSignalFunction function, void *user_data, GDBusDestroyFunction destroy); +guint g_dbus_add_properties_watch(DBusConnection *connection, + const char *sender, const char *path, + const char *interface, + GDBusSignalFunction function, void *user_data, + GDBusDestroyFunction destroy); gboolean g_dbus_remove_watch(DBusConnection *connection, guint tag); void g_dbus_remove_all_watches(DBusConnection *connection); +void g_dbus_pending_property_success(GDBusPendingPropertySet id); +void g_dbus_pending_property_error_valist(GDBusPendingReply id, + const char *name, const char *format, va_list args); +void g_dbus_pending_property_error(GDBusPendingReply id, const char *name, + const char *format, ...); +void g_dbus_emit_property_changed(DBusConnection *connection, + const char *path, const char *interface, + const char *name); +gboolean g_dbus_get_properties(DBusConnection *connection, const char *path, + const char *interface, DBusMessageIter *iter); + +gboolean g_dbus_attach_object_manager(DBusConnection *connection); +gboolean g_dbus_detach_object_manager(DBusConnection *connection); + #ifdef __cplusplus } #endif diff -Nru obexd-0.46/gdbus/mainloop.c obexd-0.48/gdbus/mainloop.c --- obexd-0.46/gdbus/mainloop.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/gdbus/mainloop.c 2012-11-30 08:59:13.000000000 +0100 @@ -92,8 +92,9 @@ struct watch_info *info = data; unsigned int flags = 0; DBusDispatchStatus status; + DBusConnection *conn; - dbus_connection_ref(info->conn); + conn = dbus_connection_ref(info->conn); if (cond & G_IO_IN) flags |= DBUS_WATCH_READABLE; if (cond & G_IO_OUT) flags |= DBUS_WATCH_WRITABLE; @@ -102,10 +103,10 @@ dbus_watch_handle(info->watch, flags); - status = dbus_connection_get_dispatch_status(info->conn); - queue_dispatch(info->conn, status); + status = dbus_connection_get_dispatch_status(conn); + queue_dispatch(conn, status); - dbus_connection_unref(info->conn); + dbus_connection_unref(conn); return TRUE; } diff -Nru obexd-0.46/gdbus/object.c obexd-0.48/gdbus/object.c --- obexd-0.46/gdbus/object.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/gdbus/object.c 2012-11-30 08:59:13.000000000 +0100 @@ -37,10 +37,28 @@ #define error(fmt...) #define debug(fmt...) +#define DBUS_INTERFACE_OBJECT_MANAGER "org.freedesktop.DBus.ObjectManager" + +#ifndef DBUS_ERROR_UNKNOWN_PROPERTY +#define DBUS_ERROR_UNKNOWN_PROPERTY "org.freedesktop.DBus.Error.UnknownProperty" +#endif + +#ifndef DBUS_ERROR_PROPERTY_READ_ONLY +#define DBUS_ERROR_PROPERTY_READ_ONLY "org.freedesktop.DBus.Error.PropertyReadOnly" +#endif + struct generic_data { unsigned int refcount; + DBusConnection *conn; + char *path; GSList *interfaces; + GSList *objects; + GSList *added; + GSList *removed; + guint process_id; + gboolean pending_prop; char *introspect; + struct generic_data *parent; }; struct interface_data { @@ -48,6 +66,7 @@ const GDBusMethodTable *methods; const GDBusSignalTable *signals; const GDBusPropertyTable *properties; + GSList *pending_prop; void *user_data; GDBusDestroyFunction destroy; }; @@ -59,95 +78,121 @@ void *iface_user_data; }; -static void print_arguments(GString *gstr, const char *sig, - const char *direction) -{ - int i; - - for (i = 0; sig[i]; i++) { - char type[32]; - int struct_level, dict_level; - unsigned int len; - gboolean complete; - - complete = FALSE; - struct_level = dict_level = 0; - memset(type, 0, sizeof(type)); - - /* Gather enough data to have a single complete type */ - for (len = 0; len < (sizeof(type) - 1) && sig[i]; len++, i++) { - switch (sig[i]) { - case '(': - struct_level++; - break; - case ')': - struct_level--; - if (struct_level <= 0 && dict_level <= 0) - complete = TRUE; - break; - case '{': - dict_level++; - break; - case '}': - dict_level--; - if (struct_level <= 0 && dict_level <= 0) - complete = TRUE; - break; - case 'a': - break; - default: - if (struct_level <= 0 && dict_level <= 0) - complete = TRUE; - break; - } +struct property_data { + DBusConnection *conn; + GDBusPendingPropertySet id; + DBusMessage *message; +}; - type[len] = sig[i]; +static struct generic_data *root; - if (complete) - break; - } +static gboolean process_changes(gpointer user_data); +static void process_properties_from_interface(struct generic_data *data, + struct interface_data *iface); +static void process_property_changes(struct generic_data *data); +static void print_arguments(GString *gstr, const GDBusArgInfo *args, + const char *direction) +{ + for (; args && args->name; args++) { + g_string_append_printf(gstr, + "\t\t\tname, args->signature); if (direction) g_string_append_printf(gstr, - "\t\t\t\n", - type, direction); + " direction=\"%s\"/>\n", direction); else - g_string_append_printf(gstr, - "\t\t\t\n", - type); + g_string_append_printf(gstr, "/>\n"); + } } +#define G_DBUS_ANNOTATE(prefix_, name_, value_) \ + prefix_ "\n" + +#define G_DBUS_ANNOTATE_DEPRECATED(prefix_) \ + G_DBUS_ANNOTATE(prefix_, "Deprecated", "true") + +#define G_DBUS_ANNOTATE_NOREPLY(prefix_) \ + G_DBUS_ANNOTATE(prefix_, "Method.NoReply", "true") + static void generate_interface_xml(GString *gstr, struct interface_data *iface) { const GDBusMethodTable *method; const GDBusSignalTable *signal; + const GDBusPropertyTable *property; for (method = iface->methods; method && method->name; method++) { - if (!strlen(method->signature) && !strlen(method->reply)) - g_string_append_printf(gstr, "\t\t\n", - method->name); + gboolean deprecated = method->flags & + G_DBUS_METHOD_FLAG_DEPRECATED; + gboolean noreply = method->flags & + G_DBUS_METHOD_FLAG_NOREPLY; + + if (!deprecated && !noreply && + !(method->in_args && method->in_args->name) && + !(method->out_args && method->out_args->name)) + g_string_append_printf(gstr, + "\t\t\n", + method->name); else { - g_string_append_printf(gstr, "\t\t\n", - method->name); - print_arguments(gstr, method->signature, "in"); - print_arguments(gstr, method->reply, "out"); + g_string_append_printf(gstr, + "\t\t\n", + method->name); + print_arguments(gstr, method->in_args, "in"); + print_arguments(gstr, method->out_args, "out"); + + if (deprecated) + g_string_append_printf(gstr, + G_DBUS_ANNOTATE_DEPRECATED("\t\t\t")); + if (noreply) + g_string_append_printf(gstr, + G_DBUS_ANNOTATE_NOREPLY("\t\t\t")); + g_string_append_printf(gstr, "\t\t\n"); } } for (signal = iface->signals; signal && signal->name; signal++) { - if (!strlen(signal->signature)) - g_string_append_printf(gstr, "\t\t\n", - signal->name); + gboolean deprecated = signal->flags & + G_DBUS_SIGNAL_FLAG_DEPRECATED; + + if (!deprecated && !(signal->args && signal->args->name)) + g_string_append_printf(gstr, + "\t\t\n", + signal->name); else { - g_string_append_printf(gstr, "\t\t\n", - signal->name); - print_arguments(gstr, signal->signature, NULL); + g_string_append_printf(gstr, + "\t\t\n", + signal->name); + print_arguments(gstr, signal->args, NULL); + + if (deprecated) + g_string_append_printf(gstr, + G_DBUS_ANNOTATE_DEPRECATED("\t\t\t")); + g_string_append_printf(gstr, "\t\t\n"); } } + + for (property = iface->properties; property && property->name; + property++) { + gboolean deprecated = property->flags & + G_DBUS_PROPERTY_FLAG_DEPRECATED; + + g_string_append_printf(gstr, "\t\tname, property->type, + property->get ? "read" : "", + property->set ? "write" : ""); + + if (!deprecated) + g_string_append_printf(gstr, "/>\n"); + else + g_string_append_printf(gstr, + G_DBUS_ANNOTATE_DEPRECATED(">\n\t\t\t")); + } } static void generate_introspection_xml(DBusConnection *conn, @@ -196,11 +241,6 @@ struct generic_data *data = user_data; DBusMessage *reply; - if (!dbus_message_has_signature(message, DBUS_TYPE_INVALID_AS_STRING)) { - error("Unexpected signature to introspect call"); - return NULL; - } - if (data->introspect == NULL) generate_introspection_xml(connection, data, dbus_message_get_path(message)); @@ -253,7 +293,7 @@ { GSList *list; - for (list = pending_security; list; list = list->next) { + for (list = pending_security; list; list = list->next) { struct security_data *secdata = list->data; if (secdata->pending != pending) @@ -267,7 +307,7 @@ dbus_message_unref(secdata->message); g_free(secdata); return; - } + } } void g_dbus_pending_error_valist(DBusConnection *connection, @@ -276,7 +316,7 @@ { GSList *list; - for (list = pending_security; list; list = list->next) { + for (list = pending_security; list; list = list->next) { struct security_data *secdata = list->data; DBusMessage *reply; @@ -295,7 +335,7 @@ dbus_message_unref(secdata->message); g_free(secdata); return; - } + } } void g_dbus_pending_error(DBusConnection *connection, @@ -391,12 +431,177 @@ return FALSE; } -static void generic_unregister(DBusConnection *connection, void *user_data) +static GDBusPendingPropertySet next_pending_property = 1; +static GSList *pending_property_set; + +static struct property_data *remove_pending_property_data( + GDBusPendingPropertySet id) { - struct generic_data *data = user_data; + struct property_data *propdata; + GSList *l; - g_free(data->introspect); - g_free(data); + for (l = pending_property_set; l != NULL; l = l->next) { + propdata = l->data; + if (propdata->id != id) + continue; + + break; + } + + if (l == NULL) + return NULL; + + pending_property_set = g_slist_delete_link(pending_property_set, l); + + return propdata; +} + +void g_dbus_pending_property_success(GDBusPendingPropertySet id) +{ + struct property_data *propdata; + + propdata = remove_pending_property_data(id); + if (propdata == NULL) + return; + + g_dbus_send_reply(propdata->conn, propdata->message, + DBUS_TYPE_INVALID); + dbus_message_unref(propdata->message); + g_free(propdata); +} + +void g_dbus_pending_property_error_valist(GDBusPendingReply id, + const char *name, const char *format, + va_list args) +{ + struct property_data *propdata; + DBusMessage *reply; + + propdata = remove_pending_property_data(id); + if (propdata == NULL) + return; + + reply = g_dbus_create_error_valist(propdata->message, name, format, + args); + if (reply != NULL) { + dbus_connection_send(propdata->conn, reply, NULL); + dbus_message_unref(reply); + } + + dbus_message_unref(propdata->message); + g_free(propdata); +} + +void g_dbus_pending_property_error(GDBusPendingReply id, const char *name, + const char *format, ...) +{ + va_list args; + + va_start(args, format); + + g_dbus_pending_property_error_valist(id, name, format, args); + + va_end(args); +} + +static void reset_parent(gpointer data, gpointer user_data) +{ + struct generic_data *child = data; + struct generic_data *parent = user_data; + + child->parent = parent; +} + +static void append_property(struct interface_data *iface, + const GDBusPropertyTable *p, DBusMessageIter *dict) +{ + DBusMessageIter entry, value; + + dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL, + &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &p->name); + dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, p->type, + &value); + + p->get(p, &value, iface->user_data); + + dbus_message_iter_close_container(&entry, &value); + dbus_message_iter_close_container(dict, &entry); +} + +static void append_properties(struct interface_data *data, + DBusMessageIter *iter) +{ + DBusMessageIter dict; + const GDBusPropertyTable *p; + + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + + for (p = data->properties; p && p->name; p++) { + if (p->get == NULL) + continue; + + if (p->exists != NULL && !p->exists(p, data->user_data)) + continue; + + append_property(data, p, &dict); + } + + dbus_message_iter_close_container(iter, &dict); +} + +static void append_interface(gpointer data, gpointer user_data) +{ + struct interface_data *iface = data; + DBusMessageIter *array = user_data; + DBusMessageIter entry; + + dbus_message_iter_open_container(array, DBUS_TYPE_DICT_ENTRY, NULL, + &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &iface->name); + append_properties(data, &entry); + dbus_message_iter_close_container(array, &entry); +} + +static void emit_interfaces_added(struct generic_data *data) +{ + DBusMessage *signal; + DBusMessageIter iter, array; + + if (root == NULL || data == root) + return; + + signal = dbus_message_new_signal(root->path, + DBUS_INTERFACE_OBJECT_MANAGER, + "InterfacesAdded"); + if (signal == NULL) + return; + + dbus_message_iter_init_append(signal, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, + &data->path); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array); + + g_slist_foreach(data->added, append_interface, &array); + g_slist_free(data->added); + data->added = NULL; + + dbus_message_iter_close_container(&iter, &array); + + g_dbus_send_message(data->conn, signal); } static struct interface_data *find_interface(GSList *interfaces, @@ -416,6 +621,391 @@ return NULL; } +static gboolean g_dbus_args_have_signature(const GDBusArgInfo *args, + DBusMessage *message) +{ + const char *sig = dbus_message_get_signature(message); + const char *p = NULL; + + for (; args && args->signature && *sig; args++) { + p = args->signature; + + for (; *sig && *p; sig++, p++) { + if (*p != *sig) + return FALSE; + } + } + + if (*sig || (p && *p) || (args && args->signature)) + return FALSE; + + return TRUE; +} + +static gboolean remove_interface(struct generic_data *data, const char *name) +{ + struct interface_data *iface; + + iface = find_interface(data->interfaces, name); + if (iface == NULL) + return FALSE; + + process_properties_from_interface(data, iface); + + data->interfaces = g_slist_remove(data->interfaces, iface); + + if (iface->destroy) { + iface->destroy(iface->user_data); + iface->user_data = NULL; + } + + /* + * Interface being removed was just added, on the same mainloop + * iteration? Don't send any signal + */ + if (g_slist_find(data->added, iface)) { + data->added = g_slist_remove(data->added, iface); + g_free(iface->name); + g_free(iface); + return TRUE; + } + + if (data->parent == NULL) { + g_free(iface->name); + g_free(iface); + return TRUE; + } + + data->removed = g_slist_prepend(data->removed, iface->name); + g_free(iface); + + if (data->process_id > 0) + return TRUE; + + data->process_id = g_idle_add(process_changes, data); + + return TRUE; +} + +static struct generic_data *invalidate_parent_data(DBusConnection *conn, + const char *child_path) +{ + struct generic_data *data = NULL, *child = NULL, *parent = NULL; + char *parent_path, *slash; + + parent_path = g_strdup(child_path); + slash = strrchr(parent_path, '/'); + if (slash == NULL) + goto done; + + if (slash == parent_path && parent_path[1] != '\0') + parent_path[1] = '\0'; + else + *slash = '\0'; + + if (!strlen(parent_path)) + goto done; + + if (dbus_connection_get_object_path_data(conn, parent_path, + (void *) &data) == FALSE) { + goto done; + } + + parent = invalidate_parent_data(conn, parent_path); + + if (data == NULL) { + data = parent; + if (data == NULL) + goto done; + } + + g_free(data->introspect); + data->introspect = NULL; + + if (!dbus_connection_get_object_path_data(conn, child_path, + (void *) &child)) + goto done; + + if (child == NULL || g_slist_find(data->objects, child) != NULL) + goto done; + + data->objects = g_slist_prepend(data->objects, child); + child->parent = data; + +done: + g_free(parent_path); + return data; +} + +static inline const GDBusPropertyTable *find_property(const GDBusPropertyTable *properties, + const char *name) +{ + const GDBusPropertyTable *p; + + for (p = properties; p && p->name; p++) { + if (strcmp(name, p->name) == 0) + return p; + } + + return NULL; +} + +static DBusMessage *properties_get(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct generic_data *data = user_data; + struct interface_data *iface; + const GDBusPropertyTable *property; + const char *interface, *name; + DBusMessageIter iter, value; + DBusMessage *reply; + + if (!dbus_message_get_args(message, NULL, + DBUS_TYPE_STRING, &interface, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) + return NULL; + + iface = find_interface(data->interfaces, interface); + if (iface == NULL) + return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, + "No such interface '%s'", interface); + + property = find_property(iface->properties, name); + if (property == NULL) + return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, + "No such property '%s'", name); + + if (property->exists != NULL && + !property->exists(property, iface->user_data)) + return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, + "No such property '%s'", name); + + if (property->get == NULL) + return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, + "Property '%s' is not readable", name); + + reply = dbus_message_new_method_return(message); + if (reply == NULL) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, + property->type, &value); + + if (!property->get(property, &value, iface->user_data)) { + dbus_message_unref(reply); + return NULL; + } + + dbus_message_iter_close_container(&iter, &value); + + return reply; +} + +static DBusMessage *properties_get_all(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct generic_data *data = user_data; + struct interface_data *iface; + const char *interface; + DBusMessageIter iter; + DBusMessage *reply; + + if (!dbus_message_get_args(message, NULL, + DBUS_TYPE_STRING, &interface, + DBUS_TYPE_INVALID)) + return NULL; + + iface = find_interface(data->interfaces, interface); + if (iface == NULL) + return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, + "No such interface '%s'", interface); + + reply = dbus_message_new_method_return(message); + if (reply == NULL) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + + append_properties(iface, &iter); + + return reply; +} + +static DBusMessage *properties_set(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct generic_data *data = user_data; + DBusMessageIter iter, sub; + struct interface_data *iface; + const GDBusPropertyTable *property; + const char *name, *interface; + struct property_data *propdata; + + if (!dbus_message_iter_init(message, &iter)) + return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, + "No arguments given"); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, + "Invalid argument type: '%c'", + dbus_message_iter_get_arg_type(&iter)); + + dbus_message_iter_get_basic(&iter, &interface); + dbus_message_iter_next(&iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, + "Invalid argument type: '%c'", + dbus_message_iter_get_arg_type(&iter)); + + dbus_message_iter_get_basic(&iter, &name); + dbus_message_iter_next(&iter); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) + return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, + "Invalid argument type: '%c'", + dbus_message_iter_get_arg_type(&iter)); + + dbus_message_iter_recurse(&iter, &sub); + + iface = find_interface(data->interfaces, interface); + if (iface == NULL) + return g_dbus_create_error(message, DBUS_ERROR_INVALID_ARGS, + "No such interface '%s'", interface); + + property = find_property(iface->properties, name); + if (property == NULL) + return g_dbus_create_error(message, + DBUS_ERROR_UNKNOWN_PROPERTY, + "No such property '%s'", name); + + if (property->set == NULL) + return g_dbus_create_error(message, + DBUS_ERROR_PROPERTY_READ_ONLY, + "Property '%s' is not writable", name); + + if (property->exists != NULL && + !property->exists(property, iface->user_data)) + return g_dbus_create_error(message, + DBUS_ERROR_UNKNOWN_PROPERTY, + "No such property '%s'", name); + + propdata = g_new(struct property_data, 1); + propdata->id = next_pending_property++; + propdata->message = dbus_message_ref(message); + propdata->conn = connection; + pending_property_set = g_slist_prepend(pending_property_set, propdata); + + property->set(property, &sub, propdata->id, iface->user_data); + + return NULL; +} + +static const GDBusMethodTable properties_methods[] = { + { GDBUS_METHOD("Get", + GDBUS_ARGS({ "interface", "s" }, { "name", "s" }), + GDBUS_ARGS({ "value", "v" }), + properties_get) }, + { GDBUS_ASYNC_METHOD("Set", + GDBUS_ARGS({ "interface", "s" }, { "name", "s" }, + { "value", "v" }), + NULL, + properties_set) }, + { GDBUS_METHOD("GetAll", + GDBUS_ARGS({ "interface", "s" }), + GDBUS_ARGS({ "properties", "a{sv}" }), + properties_get_all) }, + { } +}; + +static const GDBusSignalTable properties_signals[] = { + { GDBUS_SIGNAL("PropertiesChanged", + GDBUS_ARGS({ "interface", "s" }, + { "changed_properties", "a{sv}" }, + { "invalidated_properties", "as"})) }, + { } +}; + +static void append_name(gpointer data, gpointer user_data) +{ + char *name = data; + DBusMessageIter *iter = user_data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &name); +} + +static void emit_interfaces_removed(struct generic_data *data) +{ + DBusMessage *signal; + DBusMessageIter iter, array; + + if (root == NULL || data == root) + return; + + signal = dbus_message_new_signal(root->path, + DBUS_INTERFACE_OBJECT_MANAGER, + "InterfacesRemoved"); + if (signal == NULL) + return; + + dbus_message_iter_init_append(signal, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, + &data->path); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &array); + + g_slist_foreach(data->removed, append_name, &array); + g_slist_free_full(data->removed, g_free); + data->removed = NULL; + + dbus_message_iter_close_container(&iter, &array); + + g_dbus_send_message(data->conn, signal); +} + +static gboolean process_changes(gpointer user_data) +{ + struct generic_data *data = user_data; + + data->process_id = 0; + + if (data->added != NULL) + emit_interfaces_added(data); + + /* Flush pending properties */ + if (data->pending_prop == TRUE) + process_property_changes(data); + + if (data->removed != NULL) + emit_interfaces_removed(data); + + return FALSE; +} + +static void generic_unregister(DBusConnection *connection, void *user_data) +{ + struct generic_data *data = user_data; + struct generic_data *parent = data->parent; + + if (parent != NULL) + parent->objects = g_slist_remove(parent->objects, data); + + if (data->process_id > 0) { + g_source_remove(data->process_id); + process_changes(data); + } + + g_slist_foreach(data->objects, reset_parent, data->parent); + g_slist_free(data->objects); + + dbus_connection_unref(data->conn); + g_free(data->introspect); + g_free(data->path); + g_free(data); +} + static DBusHandlerResult generic_message(DBusConnection *connection, DBusMessage *message, void *user_data) { @@ -436,8 +1026,8 @@ method->name) == FALSE) continue; - if (dbus_message_has_signature(message, - method->signature) == FALSE) + if (g_dbus_args_have_signature(method->in_args, + message) == FALSE) continue; if (check_privilege(connection, message, method, @@ -456,47 +1046,100 @@ .message_function = generic_message, }; -static void invalidate_parent_data(DBusConnection *conn, const char *child_path) +static const GDBusMethodTable introspect_methods[] = { + { GDBUS_METHOD("Introspect", NULL, + GDBUS_ARGS({ "xml", "s" }), introspect) }, + { } +}; + +static void append_interfaces(struct generic_data *data, DBusMessageIter *iter) { - struct generic_data *data = NULL; - char *parent_path, *slash; + DBusMessageIter array; - parent_path = g_strdup(child_path); - slash = strrchr(parent_path, '/'); - if (slash == NULL) - goto done; + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &array); - if (slash == parent_path && parent_path[1] != '\0') - parent_path[1] = '\0'; - else - *slash = '\0'; + g_slist_foreach(data->interfaces, append_interface, &array); - if (!strlen(parent_path)) - goto done; + dbus_message_iter_close_container(iter, &array); +} - if (dbus_connection_get_object_path_data(conn, parent_path, - (void *) &data) == FALSE) { - goto done; - } +static void append_object(gpointer data, gpointer user_data) +{ + struct generic_data *child = data; + DBusMessageIter *array = user_data; + DBusMessageIter entry; - invalidate_parent_data(conn, parent_path); + dbus_message_iter_open_container(array, DBUS_TYPE_DICT_ENTRY, NULL, + &entry); + dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH, + &child->path); + append_interfaces(child, &entry); + dbus_message_iter_close_container(array, &entry); - if (data == NULL) - goto done; + g_slist_foreach(child->objects, append_object, user_data); +} - g_free(data->introspect); - data->introspect = NULL; +static DBusMessage *get_objects(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct generic_data *data = user_data; + DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter array; -done: - g_free(parent_path); + reply = dbus_message_new_method_return(message); + if (reply == NULL) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_OBJECT_PATH_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &array); + + g_slist_foreach(data->objects, append_object, &array); + + dbus_message_iter_close_container(&iter, &array); + + return reply; } -static GDBusMethodTable introspect_methods[] = { - { "Introspect", "", "s", introspect }, +static const GDBusMethodTable manager_methods[] = { + { GDBUS_METHOD("GetManagedObjects", NULL, + GDBUS_ARGS({ "objects", "a{oa{sa{sv}}}" }), get_objects) }, + { } +}; + +static const GDBusSignalTable manager_signals[] = { + { GDBUS_SIGNAL("InterfacesAdded", + GDBUS_ARGS({ "object", "o" }, + { "interfaces", "a{sa{sv}}" })) }, + { GDBUS_SIGNAL("InterfacesRemoved", + GDBUS_ARGS({ "object", "o" }, { "interfaces", "as" })) }, { } }; -static void add_interface(struct generic_data *data, const char *name, +static void add_interface(struct generic_data *data, + const char *name, const GDBusMethodTable *methods, const GDBusSignalTable *signals, const GDBusPropertyTable *properties, @@ -514,6 +1157,14 @@ iface->destroy = destroy; data->interfaces = g_slist_append(data->interfaces, iface); + if (data->parent == NULL) + return; + + data->added = g_slist_append(data->added, iface); + if (data->process_id > 0) + return; + + data->process_id = g_idle_add(process_changes, data); } static struct generic_data *object_path_ref(DBusConnection *connection, @@ -530,6 +1181,8 @@ } data = g_new0(struct generic_data, 1); + data->conn = dbus_connection_ref(connection); + data->path = g_strdup(path); data->refcount = 1; data->introspect = g_strdup(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE ""); @@ -543,31 +1196,12 @@ invalidate_parent_data(connection, path); - add_interface(data, DBUS_INTERFACE_INTROSPECTABLE, - introspect_methods, NULL, NULL, data, NULL); + add_interface(data, DBUS_INTERFACE_INTROSPECTABLE, introspect_methods, + NULL, NULL, data, NULL); return data; } -static gboolean remove_interface(struct generic_data *data, const char *name) -{ - struct interface_data *iface; - - iface = find_interface(data->interfaces, name); - if (iface == NULL) - return FALSE; - - data->interfaces = g_slist_remove(data->interfaces, iface); - - if (iface->destroy) - iface->destroy(iface->user_data); - - g_free(iface->name); - g_free(iface); - - return TRUE; -} - static void object_path_unref(DBusConnection *connection, const char *path) { struct generic_data *data = NULL; @@ -585,15 +1219,16 @@ return; remove_interface(data, DBUS_INTERFACE_INTROSPECTABLE); + remove_interface(data, DBUS_INTERFACE_PROPERTIES); - invalidate_parent_data(connection, path); + invalidate_parent_data(data->conn, data->path); - dbus_connection_unregister_object_path(connection, path); + dbus_connection_unregister_object_path(data->conn, data->path); } static gboolean check_signal(DBusConnection *conn, const char *path, const char *interface, const char *name, - const char **args) + const GDBusArgInfo **args) { struct generic_data *data = NULL; struct interface_data *iface; @@ -616,17 +1251,13 @@ for (signal = iface->signals; signal && signal->name; signal++) { if (!strcmp(signal->name, name)) { - *args = signal->signature; - break; + *args = signal->args; + return TRUE; } } - if (*args == NULL) { - error("No signal named %s on interface %s", name, interface); - return FALSE; - } - - return TRUE; + error("No signal named %s on interface %s", name, interface); + return FALSE; } static dbus_bool_t emit_signal_valist(DBusConnection *conn, @@ -638,7 +1269,7 @@ { DBusMessage *signal; dbus_bool_t ret; - const char *signature, *args; + const GDBusArgInfo *args; if (!check_signal(conn, path, interface, name, &args)) return FALSE; @@ -653,10 +1284,9 @@ if (!ret) goto fail; - signature = dbus_message_get_signature(signal); - if (strcmp(args, signature) != 0) { - error("%s.%s: expected signature'%s' but got '%s'", - interface, name, args, signature); + if (g_dbus_args_have_signature(args, signal) == FALSE) { + error("%s.%s: got unexpected signature '%s'", interface, name, + dbus_message_get_signature(signal)); ret = FALSE; goto fail; } @@ -688,8 +1318,14 @@ return FALSE; } - add_interface(data, name, methods, signals, - properties, user_data, destroy); + if (properties != NULL && !find_interface(data->interfaces, + DBUS_INTERFACE_PROPERTIES)) + add_interface(data, DBUS_INTERFACE_PROPERTIES, + properties_methods, properties_signals, NULL, + data, NULL); + + add_interface(data, name, methods, signals, properties, user_data, + destroy); g_free(data->introspect); data->introspect = NULL; @@ -718,7 +1354,7 @@ g_free(data->introspect); data->introspect = NULL; - object_path_unref(connection, path); + object_path_unref(connection, data->path); return TRUE; } @@ -866,3 +1502,158 @@ return emit_signal_valist(connection, path, interface, name, type, args); } + +static void process_properties_from_interface(struct generic_data *data, + struct interface_data *iface) +{ + GSList *l; + DBusMessage *signal; + DBusMessageIter iter, dict, array; + GSList *invalidated; + + if (iface->pending_prop == NULL) + return; + + signal = dbus_message_new_signal(data->path, + DBUS_INTERFACE_PROPERTIES, "PropertiesChanged"); + if (signal == NULL) { + error("Unable to allocate new " DBUS_INTERFACE_PROPERTIES + ".PropertiesChanged signal"); + return; + } + + iface->pending_prop = g_slist_reverse(iface->pending_prop); + + dbus_message_iter_init_append(signal, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &iface->name); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + + invalidated = NULL; + + for (l = iface->pending_prop; l != NULL; l = l->next) { + GDBusPropertyTable *p = l->data; + + if (p->get == NULL) + continue; + + if (p->exists != NULL && !p->exists(p, iface->user_data)) { + invalidated = g_slist_prepend(invalidated, p); + continue; + } + + append_property(iface, p, &dict); + } + + dbus_message_iter_close_container(&iter, &dict); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &array); + for (l = invalidated; l != NULL; l = g_slist_next(l)) { + GDBusPropertyTable *p = l->data; + + dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, + &p->name); + } + g_slist_free(invalidated); + dbus_message_iter_close_container(&iter, &array); + + g_dbus_send_message(data->conn, signal); + + g_slist_free(iface->pending_prop); + iface->pending_prop = NULL; +} + +static void process_property_changes(struct generic_data *data) +{ + GSList *l; + + for (l = data->interfaces; l != NULL; l = l->next) { + struct interface_data *iface = l->data; + + process_properties_from_interface(data, iface); + } + + data->pending_prop = FALSE; +} + +void g_dbus_emit_property_changed(DBusConnection *connection, + const char *path, const char *interface, + const char *name) +{ + const GDBusPropertyTable *property; + struct generic_data *data; + struct interface_data *iface; + + if (!dbus_connection_get_object_path_data(connection, path, + (void **) &data) || data == NULL) + return; + + iface = find_interface(data->interfaces, interface); + if (iface == NULL) + return; + + property = find_property(iface->properties, name); + if (property == NULL) { + error("Could not find property %s in %p", name, + iface->properties); + return; + } + + data->pending_prop = TRUE; + iface->pending_prop = g_slist_prepend(iface->pending_prop, + (void *) property); + + if (!data->process_id) { + data->process_id = g_idle_add(process_changes, data); + return; + } +} + +gboolean g_dbus_get_properties(DBusConnection *connection, const char *path, + const char *interface, DBusMessageIter *iter) +{ + struct generic_data *data; + struct interface_data *iface; + + if (!dbus_connection_get_object_path_data(connection, path, + (void **) &data) || data == NULL) + return FALSE; + + iface = find_interface(data->interfaces, interface); + if (iface == NULL) + return FALSE; + + append_properties(iface, iter); + + return TRUE; +} + +gboolean g_dbus_attach_object_manager(DBusConnection *connection) +{ + struct generic_data *data; + + data = object_path_ref(connection, "/"); + if (data == NULL) + return FALSE; + + add_interface(data, DBUS_INTERFACE_OBJECT_MANAGER, + manager_methods, manager_signals, + NULL, data, NULL); + root = data; + + return TRUE; +} + +gboolean g_dbus_detach_object_manager(DBusConnection *connection) +{ + if (!g_dbus_unregister_interface(connection, "/", + DBUS_INTERFACE_OBJECT_MANAGER)) + return FALSE; + + root = NULL; + + return TRUE; +} diff -Nru obexd-0.46/gdbus/watch.c obexd-0.48/gdbus/watch.c --- obexd-0.46/gdbus/watch.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/gdbus/watch.c 2012-11-30 08:59:13.000000000 +0100 @@ -78,7 +78,7 @@ gboolean registered; }; -static struct filter_data *filter_data_find(DBusConnection *connection, +static struct filter_data *filter_data_find_match(DBusConnection *connection, const char *name, const char *owner, const char *path, @@ -95,28 +95,39 @@ if (connection != data->connection) continue; - if (name && data->name && - g_str_equal(name, data->name) == FALSE) + if (g_strcmp0(name, data->name) != 0) continue; - if (owner && data->owner && - g_str_equal(owner, data->owner) == FALSE) + if (g_strcmp0(owner, data->owner) != 0) continue; - if (path && data->path && - g_str_equal(path, data->path) == FALSE) + if (g_strcmp0(path, data->path) != 0) continue; - if (interface && data->interface && - g_str_equal(interface, data->interface) == FALSE) + if (g_strcmp0(interface, data->interface) != 0) continue; - if (member && data->member && - g_str_equal(member, data->member) == FALSE) + if (g_strcmp0(member, data->member) != 0) continue; - if (argument && data->argument && - g_str_equal(argument, data->argument) == FALSE) + if (g_strcmp0(argument, data->argument) != 0) + continue; + + return data; + } + + return NULL; +} + +static struct filter_data *filter_data_find(DBusConnection *connection) +{ + GSList *current; + + for (current = listeners; + current != NULL; current = current->next) { + struct filter_data *data = current->data; + + if (connection != data->connection) continue; return data; @@ -204,7 +215,7 @@ struct filter_data *data; const char *name = NULL, *owner = NULL; - if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL, NULL) == NULL) { + if (filter_data_find(connection) == NULL) { if (!dbus_connection_add_filter(connection, message_filter, NULL, NULL)) { error("dbus_connection_add_filter() failed"); @@ -221,16 +232,16 @@ name = sender; proceed: - data = filter_data_find(connection, name, owner, path, interface, - member, argument); + data = filter_data_find_match(connection, name, owner, path, + interface, member, argument); if (data) return data; data = g_new0(struct filter_data, 1); data->connection = dbus_connection_ref(connection); - data->name = name ? g_strdup(name) : NULL; - data->owner = owner ? g_strdup(owner) : NULL; + data->name = g_strdup(name); + data->owner = g_strdup(owner); data->path = g_strdup(path); data->interface = g_strdup(interface); data->member = g_strdup(member); @@ -376,15 +387,13 @@ connection = dbus_connection_ref(data->connection); listeners = g_slist_remove(listeners, data); - filter_data_free(data); /* Remove filter if there are no listeners left for the connection */ - data = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL, - NULL); - if (data == NULL) + if (filter_data_find(connection) == NULL) dbus_connection_remove_filter(connection, message_filter, NULL); + filter_data_free(data); dbus_connection_unref(connection); return TRUE; @@ -502,6 +511,7 @@ { struct filter_data *data; const char *sender, *path, *iface, *member, *arg = NULL; + GSList *current, *delete_listener = NULL; /* Only filter signals */ if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) @@ -513,36 +523,66 @@ member = dbus_message_get_member(message); dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &arg, DBUS_TYPE_INVALID); - /* Sender is always bus name */ - data = filter_data_find(connection, NULL, sender, path, iface, member, - arg); - if (data == NULL) { - error("Got %s.%s signal which has no listeners", iface, member); - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - } + /* Sender is always the owner */ + + for (current = listeners; current != NULL; current = current->next) { + data = current->data; + + if (connection != data->connection) + continue; + + if (data->owner && g_str_equal(sender, data->owner) == FALSE) + continue; + + if (data->path && g_str_equal(path, data->path) == FALSE) + continue; + + if (data->interface && g_str_equal(iface, + data->interface) == FALSE) + continue; + + if (data->member && g_str_equal(member, data->member) == FALSE) + continue; + + if (data->argument && g_str_equal(arg, + data->argument) == FALSE) + continue; - if (data->handle_func) { - data->lock = TRUE; + if (data->handle_func) { + data->lock = TRUE; - data->handle_func(connection, message, data); + data->handle_func(connection, message, data); - data->callbacks = data->processed; - data->processed = NULL; - data->lock = FALSE; + data->callbacks = data->processed; + data->processed = NULL; + data->lock = FALSE; + } + + if (!data->callbacks) + delete_listener = g_slist_prepend(delete_listener, + current); } - if (data->callbacks) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + for (current = delete_listener; current != NULL; + current = delete_listener->next) { + GSList *l = current->data; - remove_match(data); + data = l->data; - listeners = g_slist_remove(listeners, data); - filter_data_free(data); + /* Has any other callback added callbacks back to this data? */ + if (data->callbacks != NULL) + continue; - /* Remove filter if there no listener left for the connection */ - data = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL, - NULL); - if (data == NULL) + remove_match(data); + listeners = g_slist_delete_link(listeners, l); + + filter_data_free(data); + } + + g_slist_free(delete_listener); + + /* Remove filter if there are no listeners left for the connection */ + if (filter_data_find(connection) == NULL) dbus_connection_remove_filter(connection, message_filter, NULL); @@ -712,6 +752,34 @@ return cb->id; } +guint g_dbus_add_properties_watch(DBusConnection *connection, + const char *sender, const char *path, + const char *interface, + GDBusSignalFunction function, void *user_data, + GDBusDestroyFunction destroy) +{ + struct filter_data *data; + struct filter_callback *cb; + + data = filter_data_get(connection, signal_filter, sender, path, + DBUS_INTERFACE_PROPERTIES, "PropertiesChanged", + interface); + if (data == NULL) + return 0; + + cb = filter_data_add_callback(data, NULL, NULL, function, destroy, + user_data); + if (cb == NULL) + return 0; + + if (data->name != NULL && data->name_watch == 0) + data->name_watch = g_dbus_add_service_watch(connection, + data->name, NULL, + NULL, NULL, NULL); + + return cb->id; +} + gboolean g_dbus_remove_watch(DBusConnection *connection, guint id) { struct filter_data *data; @@ -738,8 +806,7 @@ { struct filter_data *data; - while ((data = filter_data_find(connection, NULL, NULL, NULL, NULL, - NULL, NULL))) { + while ((data = filter_data_find(connection))) { listeners = g_slist_remove(listeners, data); filter_data_call_and_free(data); } diff -Nru obexd-0.46/gobex/gobex-apparam.c obexd-0.48/gobex/gobex-apparam.c --- obexd-0.46/gobex/gobex-apparam.c 1970-01-01 01:00:00.000000000 +0100 +++ obexd-0.48/gobex/gobex-apparam.c 2012-11-30 08:59:13.000000000 +0100 @@ -0,0 +1,364 @@ +/* + * + * OBEX library with GLib integration + * + * Copyright (C) 2012 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include "gobex-apparam.h" +#include "gobex-debug.h" + +struct _GObexApparam { + GHashTable *tags; +}; + +struct apparam_tag { + guint8 id; + guint8 len; + union { + /* Data is stored in network order */ + char string[0]; + guint8 data[0]; + guint8 u8; + guint16 u16; + guint32 u32; + guint64 u64; + } value; +} __attribute__ ((packed)); + +static struct apparam_tag *tag_new(guint8 id, guint8 len, const void *data) +{ + struct apparam_tag *tag; + + tag = g_malloc0(2 + len); + tag->id = id; + tag->len = len; + memcpy(tag->value.data, data, len); + + return tag; +} + +static GObexApparam *g_obex_apparam_new(void) +{ + GObexApparam *apparam; + + apparam = g_new0(GObexApparam, 1); + apparam->tags = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, g_free); + + return apparam; +} + +static struct apparam_tag *apparam_tag_decode(const void *data, gsize size, + gsize *parsed) +{ + struct apparam_tag *tag; + const guint8 *ptr = data; + guint8 id; + guint8 len; + + if (size < 2) + return NULL; + + id = ptr[0]; + len = ptr[1]; + + if (len > size - 2) + return NULL; + + tag = tag_new(id, len, ptr + 2); + if (tag == NULL) + return NULL; + + *parsed = 2 + tag->len; + + return tag; +} + +GObexApparam *g_obex_apparam_decode(const void *data, gsize size) +{ + GObexApparam *apparam; + GHashTable *tags; + gsize count = 0; + + if (size < 2) + return NULL; + + apparam = g_obex_apparam_new(); + + tags = apparam->tags; + while (count < size) { + struct apparam_tag *tag; + gsize parsed; + guint id; + + tag = apparam_tag_decode(data + count, size - count, &parsed); + if (tag == NULL) + break; + + id = tag->id; + g_hash_table_insert(tags, GUINT_TO_POINTER(id), tag); + + count += parsed; + } + + if (count != size) { + g_obex_apparam_free(apparam); + return NULL; + } + + return apparam; +} + +static gssize tag_encode(struct apparam_tag *tag, void *buf, gsize len) +{ + gsize count = 2 + tag->len; + + if (len < count) + return -ENOBUFS; + + memcpy(buf, tag, count); + + return count; +} + +gssize g_obex_apparam_encode(GObexApparam *apparam, void *buf, gsize len) +{ + gsize count = 0; + gssize ret; + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init(&iter, apparam->tags); + while (g_hash_table_iter_next(&iter, &key, &value)) { + struct apparam_tag *tag = value; + + ret = tag_encode(tag, buf + count, len - count); + if (ret < 0) + return ret; + + count += ret; + } + + return count; +} + +GObexApparam *g_obex_apparam_set_bytes(GObexApparam *apparam, guint8 id, + const void *value, gsize len) +{ + struct apparam_tag *tag; + guint uid = id; + + if (apparam == NULL) + apparam = g_obex_apparam_new(); + + tag = tag_new(id, len, value); + g_hash_table_replace(apparam->tags, GUINT_TO_POINTER(uid), tag); + + return apparam; +} + +GObexApparam *g_obex_apparam_set_uint8(GObexApparam *apparam, guint8 id, + guint8 value) +{ + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x value %u", id, value); + + return g_obex_apparam_set_bytes(apparam, id, &value, 1); +} + +GObexApparam *g_obex_apparam_set_uint16(GObexApparam *apparam, guint8 id, + guint16 value) +{ + guint16 num = g_htons(value); + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x value %u", id, value); + + return g_obex_apparam_set_bytes(apparam, id, &num, 2); +} + +GObexApparam *g_obex_apparam_set_uint32(GObexApparam *apparam, guint8 id, + guint32 value) +{ + guint32 num = g_htonl(value); + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x value %u", id, value); + + return g_obex_apparam_set_bytes(apparam, id, &num, 4); +} + +GObexApparam *g_obex_apparam_set_uint64(GObexApparam *apparam, guint8 id, + guint64 value) +{ + guint64 num = GUINT64_TO_BE(value); + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x value %" + G_GUINT64_FORMAT, id, value); + + return g_obex_apparam_set_bytes(apparam, id, &num, 8); +} + +GObexApparam *g_obex_apparam_set_string(GObexApparam *apparam, guint8 id, + const char *value) +{ + gsize len; + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x value %s", id, value); + + len = strlen(value) + 1; + if (len > G_MAXUINT8) { + ((char *) value)[G_MAXUINT8 - 1] = '\0'; + len = G_MAXUINT8; + } + + return g_obex_apparam_set_bytes(apparam, id, value, len); +} + +static struct apparam_tag *g_obex_apparam_find_tag(GObexApparam *apparam, + guint id) +{ + return g_hash_table_lookup(apparam->tags, GUINT_TO_POINTER(id)); +} + +gboolean g_obex_apparam_get_uint8(GObexApparam *apparam, guint8 id, + guint8 *dest) +{ + struct apparam_tag *tag; + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x", id); + + tag = g_obex_apparam_find_tag(apparam, id); + if (tag == NULL) + return FALSE; + + *dest = tag->value.u8; + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "%u", *dest); + + return TRUE; +} + +gboolean g_obex_apparam_get_uint16(GObexApparam *apparam, guint8 id, + guint16 *dest) +{ + struct apparam_tag *tag; + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x", id); + + tag = g_obex_apparam_find_tag(apparam, id); + if (tag == NULL) + return FALSE; + + if (tag->len < sizeof(*dest)) + return FALSE; + + *dest = g_ntohs(tag->value.u16); + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "%u", *dest); + + return TRUE; +} + +gboolean g_obex_apparam_get_uint32(GObexApparam *apparam, guint8 id, + guint32 *dest) +{ + struct apparam_tag *tag; + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x", id); + + tag = g_obex_apparam_find_tag(apparam, id); + if (tag == NULL) + return FALSE; + + if (tag->len < sizeof(*dest)) + return FALSE; + + *dest = g_ntohl(tag->value.u32); + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "%u", *dest); + + return TRUE; +} + +gboolean g_obex_apparam_get_uint64(GObexApparam *apparam, guint8 id, + guint64 *dest) +{ + struct apparam_tag *tag; + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x", id); + + tag = g_obex_apparam_find_tag(apparam, id); + if (tag == NULL) + return FALSE; + + if (tag->len < sizeof(*dest)) + return FALSE; + + *dest = GUINT64_FROM_BE(tag->value.u64); + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "%" G_GUINT64_FORMAT, *dest); + + return TRUE; +} + +char *g_obex_apparam_get_string(GObexApparam *apparam, guint8 id) +{ + struct apparam_tag *tag; + char *string; + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x", id); + + tag = g_obex_apparam_find_tag(apparam, id); + if (tag == NULL) + return NULL; + + string = g_strndup(tag->value.string, tag->len); + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "%s", string); + + return string; +} + +gboolean g_obex_apparam_get_bytes(GObexApparam *apparam, guint8 id, + const guint8 **val, gsize *len) +{ + struct apparam_tag *tag; + + g_obex_debug(G_OBEX_DEBUG_APPARAM, "tag 0x%02x", id); + + tag = g_obex_apparam_find_tag(apparam, id); + if (tag == NULL) + return FALSE; + + *len = tag->len; + *val = tag->value.data; + + return TRUE; +} + +void g_obex_apparam_free(GObexApparam *apparam) +{ + g_hash_table_unref(apparam->tags); + g_free(apparam); +} diff -Nru obexd-0.46/gobex/gobex-apparam.h obexd-0.48/gobex/gobex-apparam.h --- obexd-0.46/gobex/gobex-apparam.h 1970-01-01 01:00:00.000000000 +0100 +++ obexd-0.48/gobex/gobex-apparam.h 2012-11-30 08:59:13.000000000 +0100 @@ -0,0 +1,59 @@ +/* + * + * OBEX library with GLib integration + * + * Copyright (C) 2012 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __GOBEX_APPARAM_H +#define __GOBEX_APPARAM_H + +#include + +typedef struct _GObexApparam GObexApparam; + +GObexApparam *g_obex_apparam_decode(const void *data, gsize size); +gssize g_obex_apparam_encode(GObexApparam *apparam, void *buf, gsize size); + +GObexApparam *g_obex_apparam_set_bytes(GObexApparam *apparam, guint8 id, + const void *value, gsize size); +GObexApparam *g_obex_apparam_set_uint8(GObexApparam *apparam, guint8 id, + guint8 value); +GObexApparam *g_obex_apparam_set_uint16(GObexApparam *apparam, guint8 id, + guint16 value); +GObexApparam *g_obex_apparam_set_uint32(GObexApparam *apparam, guint8 id, + guint32 value); +GObexApparam *g_obex_apparam_set_uint64(GObexApparam *apparam, guint8 id, + guint64 value); +GObexApparam *g_obex_apparam_set_string(GObexApparam *apparam, guint8 id, + const char *value); + +gboolean g_obex_apparam_get_bytes(GObexApparam *apparam, guint8 id, + const guint8 **val, gsize *len); +gboolean g_obex_apparam_get_uint8(GObexApparam *apparam, guint8 id, + guint8 *value); +gboolean g_obex_apparam_get_uint16(GObexApparam *apparam, guint8 id, + guint16 *value); +gboolean g_obex_apparam_get_uint32(GObexApparam *apparam, guint8 id, + guint32 *value); +gboolean g_obex_apparam_get_uint64(GObexApparam *apparam, guint8 id, + guint64 *value); +char *g_obex_apparam_get_string(GObexApparam *apparam, guint8 id); + +void g_obex_apparam_free(GObexApparam *apparam); + +#endif /* __GOBEX_APPARAM_H */ diff -Nru obexd-0.46/gobex/gobex.c obexd-0.48/gobex/gobex.c --- obexd-0.46/gobex/gobex.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/gobex/gobex.c 2012-11-30 08:59:13.000000000 +0100 @@ -267,7 +267,7 @@ if (status != G_IO_STATUS_NORMAL) return FALSE; - g_obex_dump("<", buf, bytes_written); + g_obex_dump(G_OBEX_DEBUG_DATA, "<", buf, bytes_written); obex->tx_sent += bytes_written; obex->tx_data -= bytes_written; @@ -290,7 +290,7 @@ if (bytes_written != obex->tx_data) return FALSE; - g_obex_dump("<", buf, bytes_written); + g_obex_dump(G_OBEX_DEBUG_DATA, "<", buf, bytes_written); obex->tx_sent += bytes_written; obex->tx_data -= bytes_written; @@ -1078,7 +1078,7 @@ } while (rbytes > 0 && obex->rx_data < obex->rx_pkt_len); done: - g_obex_dump(">", obex->rx_buf, obex->rx_data); + g_obex_dump(G_OBEX_DEBUG_DATA, ">", obex->rx_buf, obex->rx_data); return TRUE; } @@ -1124,7 +1124,7 @@ return FALSE; } - g_obex_dump(">", obex->rx_buf, obex->rx_data); + g_obex_dump(G_OBEX_DEBUG_DATA, ">", obex->rx_buf, obex->rx_data); return TRUE; fail: @@ -1236,6 +1236,7 @@ { "header", G_OBEX_DEBUG_HEADER }, { "packet", G_OBEX_DEBUG_PACKET }, { "data", G_OBEX_DEBUG_DATA }, + { "apparam", G_OBEX_DEBUG_APPARAM }, }; GObex *g_obex_new(GIOChannel *io, GObexTransportType transport_type, @@ -1246,9 +1247,11 @@ if (gobex_debug == 0) { const char *env = g_getenv("GOBEX_DEBUG"); - if (env) - gobex_debug = g_parse_debug_string(env, keys, 6); - else + + if (env) { + gobex_debug = g_parse_debug_string(env, keys, 7); + g_setenv("G_MESSAGES_DEBUG", "gobex", FALSE); + } else gobex_debug = G_OBEX_DEBUG_NONE; } diff -Nru obexd-0.46/gobex/gobex-debug.h obexd-0.48/gobex/gobex-debug.h --- obexd-0.46/gobex/gobex-debug.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/gobex/gobex-debug.h 2012-11-30 08:59:13.000000000 +0100 @@ -32,21 +32,22 @@ #define G_OBEX_DEBUG_HEADER (1 << 4) #define G_OBEX_DEBUG_PACKET (1 << 5) #define G_OBEX_DEBUG_DATA (1 << 6) +#define G_OBEX_DEBUG_APPARAM (1 << 7) extern guint gobex_debug; #define g_obex_debug(level, format, ...) \ if (gobex_debug & level) \ - g_debug("%s:%s() " format, __FILE__, __FUNCTION__, \ - ## __VA_ARGS__) + g_log("gobex", G_LOG_LEVEL_DEBUG, "%s:%s() " format, __FILE__, \ + __FUNCTION__, ## __VA_ARGS__) -static inline void g_obex_dump(const char *prefix, const void *buf, - gsize len) +static inline void g_obex_dump(guint level, const char *prefix, + const void *buf, gsize len) { const guint8 *data = buf; int n = 0; - if (!(gobex_debug & G_OBEX_DEBUG_DATA)) + if (!(gobex_debug & level)) return; while (len > 0) { diff -Nru obexd-0.46/gobex/gobex-header.c obexd-0.48/gobex/gobex-header.c --- obexd-0.46/gobex/gobex-header.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/gobex/gobex-header.c 2012-11-30 08:59:13.000000000 +0100 @@ -109,23 +109,23 @@ g_assert_cmpuint(utf16_len + 3, ==, header->hlen); u16 = g_htons(utf16_len + 3); ptr = put_bytes(ptr, &u16, sizeof(u16)); - ptr = put_bytes(ptr, utf16, utf16_len); + put_bytes(ptr, utf16, utf16_len); g_free(utf16); break; case G_OBEX_HDR_ENC_BYTES: u16 = g_htons(header->hlen); ptr = put_bytes(ptr, &u16, sizeof(u16)); if (header->extdata) - ptr = put_bytes(ptr, header->v.extdata, header->vlen); + put_bytes(ptr, header->v.extdata, header->vlen); else - ptr = put_bytes(ptr, header->v.data, header->vlen); + put_bytes(ptr, header->v.data, header->vlen); break; case G_OBEX_HDR_ENC_UINT8: *ptr = header->v.u8; break; case G_OBEX_HDR_ENC_UINT32: u32 = g_htonl(header->v.u32); - ptr = put_bytes(ptr, &u32, sizeof(u32)); + put_bytes(ptr, &u32, sizeof(u32)); break; default: g_assert_not_reached(); @@ -187,7 +187,7 @@ } header->v.string = g_convert((const char *) ptr, hdr_len - 5, - "UTF8", "UTF16BE", + "UTF-8", "UTF-16BE", NULL, &str_len, &conv_err); if (header->v.string == NULL) { g_set_error(err, G_OBEX_ERROR, @@ -263,7 +263,7 @@ } header->vlen = 4; header->hlen = 5; - ptr = get_bytes(&header->v.u32, ptr, sizeof(header->v.u32)); + get_bytes(&header->v.u32, ptr, sizeof(header->v.u32)); header->v.u32 = g_ntohl(header->v.u32); *parsed = 5; break; @@ -337,6 +337,19 @@ return TRUE; } +GObexApparam *g_obex_header_get_apparam(GObexHeader *header) +{ + gboolean ret; + const guint8 *val; + gsize len; + + ret = g_obex_header_get_bytes(header, &val, &len); + if (!ret) + return NULL; + + return g_obex_apparam_decode(val, len); +} + gboolean g_obex_header_get_uint8(GObexHeader *header, guint8 *val) { g_obex_debug(G_OBEX_DEBUG_HEADER, "header 0x%02x", @@ -411,6 +424,18 @@ return header; } +GObexHeader *g_obex_header_new_apparam(GObexApparam *apparam) +{ + guint8 buf[1024]; + gssize len; + + len = g_obex_apparam_encode(apparam, buf, sizeof(buf)); + if (len < 0) + return NULL; + + return g_obex_header_new_bytes(G_OBEX_HDR_APPARAM, buf, len); +} + GObexHeader *g_obex_header_new_uint8(guint8 id, guint8 val) { GObexHeader *header; diff -Nru obexd-0.46/gobex/gobex-header.h obexd-0.48/gobex/gobex-header.h --- obexd-0.46/gobex/gobex-header.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/gobex/gobex-header.h 2012-11-30 08:59:13.000000000 +0100 @@ -25,6 +25,7 @@ #include #include +#include /* Header ID's */ #define G_OBEX_HDR_INVALID 0x00 @@ -77,11 +78,13 @@ gsize *len); gboolean g_obex_header_get_uint8(GObexHeader *header, guint8 *val); gboolean g_obex_header_get_uint32(GObexHeader *header, guint32 *val); +GObexApparam *g_obex_header_get_apparam(GObexHeader *header); GObexHeader *g_obex_header_new_unicode(guint8 id, const char *str); GObexHeader *g_obex_header_new_bytes(guint8 id, const void *data, gsize len); GObexHeader *g_obex_header_new_uint8(guint8 id, guint8 val); GObexHeader *g_obex_header_new_uint32(guint8 id, guint32 val); +GObexHeader *g_obex_header_new_apparam(GObexApparam *apparam); GSList *g_obex_header_create_list(guint8 first_hdr_id, va_list args, gsize *total_len); diff -Nru obexd-0.46/ltmain.sh obexd-0.48/ltmain.sh --- obexd-0.46/ltmain.sh 2012-05-17 17:12:34.000000000 +0200 +++ obexd-0.48/ltmain.sh 2012-11-30 08:59:30.000000000 +0100 @@ -70,7 +70,7 @@ # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1 +# $progname: (GNU libtool) 2.4.2 Debian-2.4.2-1.1 # automake: $automake_version # autoconf: $autoconf_version # @@ -80,7 +80,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION="2.4.2 Debian-2.4.2-1" +VERSION="2.4.2 Debian-2.4.2-1.1" TIMESTAMP="" package_revision=1.3337 diff -Nru obexd-0.46/Makefile.am obexd-0.48/Makefile.am --- obexd-0.46/Makefile.am 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/Makefile.am 2012-11-30 08:59:13.000000000 +0100 @@ -7,10 +7,9 @@ doc_files = doc/obexd-api.txt doc/agent-api.txt doc/client-api.txt -test_files = test/simple-agent test/send-files \ - test/pull-business-card test/exchange-business-cards \ +test_files = test/simple-agent test/exchange-business-cards \ test/list-folders test/pbap-client test/ftp-client \ - test/map-client + test/map-client test/opp-client gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/watch.c \ gdbus/object.c gdbus/polkit.c @@ -21,7 +20,8 @@ gobex/gobex-defs.h gobex/gobex-defs.c \ gobex/gobex-packet.c gobex/gobex-packet.h \ gobex/gobex-header.c gobex/gobex-header.h \ - gobex/gobex-transfer.c gobex/gobex-debug.h + gobex/gobex-transfer.c gobex/gobex-debug.h \ + gobex/gobex-apparam.h gobex/gobex-apparam.c noinst_PROGRAMS = libexec_PROGRAMS = @@ -63,7 +63,7 @@ builtin_modules += mas builtin_sources += plugins/mas.c plugins/messages.h \ - src/map_ap.c src/map_ap.h + src/map_ap.h builtin_modules += irmc builtin_sources += plugins/irmc.c @@ -124,10 +124,10 @@ client/opp.h client/opp.c \ client/map.h client/map.c \ client/transfer.h client/transfer.c \ - client/agent.h client/agent.c \ client/transport.h client/transport.c \ + client/dbus.h client/dbus.c \ client/driver.h client/driver.c \ - src/map_ap.h src/map_ap.c + src/map_ap.h client_obex_client_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ endif @@ -166,11 +166,12 @@ plugins/messages.c: plugins/@MESSAGES_DRIVER@ $(AM_V_GEN)$(LN_S) @abs_top_srcdir@/$< $@ -TESTS = unit/test-gobex-header unit/test-gobex-packet unit/test-gobex \ - unit/test-gobex-transfer +TESTS = unit/test-gobex-apparam unit/test-gobex-header unit/test-gobex-packet \ + unit/test-gobex unit/test-gobex-transfer noinst_PROGRAMS += unit/test-gobex-header unit/test-gobex-packet \ - unit/test-gobex unit/test-gobex-transfer + unit/test-gobex unit/test-gobex-transfer \ + unit/test-gobex-apparam unit_test_gobex_SOURCES = $(gobex_sources) unit/test-gobex.c \ unit/util.c unit/util.h @@ -188,6 +189,10 @@ unit/test-gobex-transfer.c unit_test_gobex_transfer_LDADD = @GLIB_LIBS@ +unit_test_gobex_apparam_SOURCES = $(gobex_sources) unit/util.c unit/util.h \ + unit/test-gobex-apparam.c +unit_test_gobex_apparam_LDADD = @GLIB_LIBS@ + if READLINE noinst_PROGRAMS += tools/test-client tools_test_client_SOURCES = $(gobex_sources) $(btio_sources) \ diff -Nru obexd-0.46/Makefile.in obexd-0.48/Makefile.in --- obexd-0.46/Makefile.in 2012-05-17 17:12:37.000000000 +0200 +++ obexd-0.48/Makefile.in 2012-11-30 08:59:32.000000000 +0100 @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11.3 from Makefile.am. +# Makefile.in generated by automake 1.11.6 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -18,6 +18,23 @@ VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -38,7 +55,8 @@ host_triplet = @host@ noinst_PROGRAMS = unit/test-gobex-header$(EXEEXT) \ unit/test-gobex-packet$(EXEEXT) unit/test-gobex$(EXEEXT) \ - unit/test-gobex-transfer$(EXEEXT) $(am__EXEEXT_3) \ + unit/test-gobex-transfer$(EXEEXT) \ + unit/test-gobex-apparam$(EXEEXT) $(am__EXEEXT_3) \ tools/test-server$(EXEEXT) libexec_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) @SERVER_TRUE@am__append_1 = src/obexd.service.in @@ -49,7 +67,8 @@ @SERVER_TRUE@am__append_6 = src/obexd @CLIENT_TRUE@am__append_7 = client/obex-client.service.in @CLIENT_TRUE@am__append_8 = client/obex-client -TESTS = unit/test-gobex-header$(EXEEXT) \ +TESTS = unit/test-gobex-apparam$(EXEEXT) \ + unit/test-gobex-header$(EXEEXT) \ unit/test-gobex-packet$(EXEEXT) unit/test-gobex$(EXEEXT) \ unit/test-gobex-transfer$(EXEEXT) @READLINE_TRUE@am__append_9 = tools/test-client @@ -109,21 +128,22 @@ gobex/gobex.c gobex/gobex-defs.h gobex/gobex-defs.c \ gobex/gobex-packet.c gobex/gobex-packet.h gobex/gobex-header.c \ gobex/gobex-header.h gobex/gobex-transfer.c \ - gobex/gobex-debug.h btio/btio.h btio/btio.c client/main.c \ + gobex/gobex-debug.h gobex/gobex-apparam.h \ + gobex/gobex-apparam.c btio/btio.h btio/btio.c client/main.c \ src/log.h src/log.c client/manager.h client/manager.c \ client/session.h client/session.c client/bluetooth.h \ client/bluetooth.c client/sync.h client/sync.c client/pbap.h \ client/pbap.c client/ftp.h client/ftp.c client/opp.h \ client/opp.c client/map.h client/map.c client/transfer.h \ - client/transfer.c client/agent.h client/agent.c \ - client/transport.h client/transport.c client/driver.h \ - client/driver.c src/map_ap.h src/map_ap.c + client/transfer.c client/transport.h client/transport.c \ + client/dbus.h client/dbus.c client/driver.h client/driver.c \ + src/map_ap.h am__dirstamp = $(am__leading_dot)dirstamp am__objects_1 = gdbus/mainloop.$(OBJEXT) gdbus/watch.$(OBJEXT) \ gdbus/object.$(OBJEXT) gdbus/polkit.$(OBJEXT) am__objects_2 = gobex/gobex.$(OBJEXT) gobex/gobex-defs.$(OBJEXT) \ gobex/gobex-packet.$(OBJEXT) gobex/gobex-header.$(OBJEXT) \ - gobex/gobex-transfer.$(OBJEXT) + gobex/gobex-transfer.$(OBJEXT) gobex/gobex-apparam.$(OBJEXT) am__objects_3 = btio/btio.$(OBJEXT) @CLIENT_TRUE@am_client_obex_client_OBJECTS = $(am__objects_1) \ @CLIENT_TRUE@ $(am__objects_2) $(am__objects_3) \ @@ -132,9 +152,9 @@ @CLIENT_TRUE@ client/bluetooth.$(OBJEXT) client/sync.$(OBJEXT) \ @CLIENT_TRUE@ client/pbap.$(OBJEXT) client/ftp.$(OBJEXT) \ @CLIENT_TRUE@ client/opp.$(OBJEXT) client/map.$(OBJEXT) \ -@CLIENT_TRUE@ client/transfer.$(OBJEXT) client/agent.$(OBJEXT) \ -@CLIENT_TRUE@ client/transport.$(OBJEXT) \ -@CLIENT_TRUE@ client/driver.$(OBJEXT) src/map_ap.$(OBJEXT) +@CLIENT_TRUE@ client/transfer.$(OBJEXT) \ +@CLIENT_TRUE@ client/transport.$(OBJEXT) client/dbus.$(OBJEXT) \ +@CLIENT_TRUE@ client/driver.$(OBJEXT) client_obex_client_OBJECTS = $(am_client_obex_client_OBJECTS) client_obex_client_DEPENDENCIES = AM_V_lt = $(am__v_lt_@AM_V@) @@ -146,12 +166,13 @@ plugins/filesystem.h plugins/pcsuite.c plugins/opp.c \ plugins/ftp.c plugins/ftp.h plugins/pbap.c plugins/phonebook.h \ plugins/vcard.h plugins/vcard.c plugins/mas.c \ - plugins/messages.h src/map_ap.c src/map_ap.h plugins/irmc.c \ + plugins/messages.h src/map_ap.h plugins/irmc.c \ plugins/syncevolution.c btio/btio.h btio/btio.c gobex/gobex.h \ gobex/gobex.c gobex/gobex-defs.h gobex/gobex-defs.c \ gobex/gobex-packet.c gobex/gobex-packet.h gobex/gobex-header.c \ gobex/gobex-header.h gobex/gobex-transfer.c \ - gobex/gobex-debug.h src/main.c src/obexd.h src/plugin.h \ + gobex/gobex-debug.h gobex/gobex-apparam.h \ + gobex/gobex-apparam.c src/main.c src/obexd.h src/plugin.h \ src/plugin.c src/log.h src/log.c src/manager.h src/manager.c \ src/obex.h src/obex.c src/obex-priv.h src/mimetype.h \ src/mimetype.c src/service.h src/service.c src/transport.h \ @@ -164,7 +185,7 @@ @SERVER_TRUE@ $(am__objects_5) plugins/opp.$(OBJEXT) \ @SERVER_TRUE@ plugins/ftp.$(OBJEXT) plugins/pbap.$(OBJEXT) \ @SERVER_TRUE@ plugins/vcard.$(OBJEXT) plugins/mas.$(OBJEXT) \ -@SERVER_TRUE@ src/map_ap.$(OBJEXT) plugins/irmc.$(OBJEXT) \ +@SERVER_TRUE@ plugins/irmc.$(OBJEXT) \ @SERVER_TRUE@ plugins/syncevolution.$(OBJEXT) @SERVER_TRUE@am_src_obexd_OBJECTS = $(am__objects_1) $(am__objects_6) \ @SERVER_TRUE@ $(am__objects_3) $(am__objects_2) \ @@ -186,7 +207,8 @@ am__tools_test_client_SOURCES_DIST = gobex/gobex.h gobex/gobex.c \ gobex/gobex-defs.h gobex/gobex-defs.c gobex/gobex-packet.c \ gobex/gobex-packet.h gobex/gobex-header.c gobex/gobex-header.h \ - gobex/gobex-transfer.c gobex/gobex-debug.h btio/btio.h \ + gobex/gobex-transfer.c gobex/gobex-debug.h \ + gobex/gobex-apparam.h gobex/gobex-apparam.c btio/btio.h \ btio/btio.c tools/test-client.c @READLINE_TRUE@am_tools_test_client_OBJECTS = $(am__objects_2) \ @READLINE_TRUE@ $(am__objects_3) tools/test-client.$(OBJEXT) @@ -200,6 +222,11 @@ unit/test-gobex.$(OBJEXT) unit/util.$(OBJEXT) unit_test_gobex_OBJECTS = $(am_unit_test_gobex_OBJECTS) unit_test_gobex_DEPENDENCIES = +am_unit_test_gobex_apparam_OBJECTS = $(am__objects_2) \ + unit/util.$(OBJEXT) unit/test-gobex-apparam.$(OBJEXT) +unit_test_gobex_apparam_OBJECTS = \ + $(am_unit_test_gobex_apparam_OBJECTS) +unit_test_gobex_apparam_DEPENDENCIES = am_unit_test_gobex_header_OBJECTS = $(am__objects_2) \ unit/test-gobex-header.$(OBJEXT) unit/util.$(OBJEXT) unit_test_gobex_header_OBJECTS = $(am_unit_test_gobex_header_OBJECTS) @@ -242,6 +269,7 @@ SOURCES = $(client_obex_client_SOURCES) $(src_obexd_SOURCES) \ $(nodist_src_obexd_SOURCES) $(tools_test_client_SOURCES) \ $(tools_test_server_SOURCES) $(unit_test_gobex_SOURCES) \ + $(unit_test_gobex_apparam_SOURCES) \ $(unit_test_gobex_header_SOURCES) \ $(unit_test_gobex_packet_SOURCES) \ $(unit_test_gobex_transfer_SOURCES) @@ -249,9 +277,15 @@ $(am__src_obexd_SOURCES_DIST) \ $(am__tools_test_client_SOURCES_DIST) \ $(tools_test_server_SOURCES) $(unit_test_gobex_SOURCES) \ + $(unit_test_gobex_apparam_SOURCES) \ $(unit_test_gobex_header_SOURCES) \ $(unit_test_gobex_packet_SOURCES) \ $(unit_test_gobex_transfer_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac DATA = $(service_DATA) ETAGS = etags CTAGS = ctags @@ -428,10 +462,9 @@ servicedir = $(datarootdir)/dbus-1/services service_in_files = $(am__append_1) $(am__append_7) doc_files = doc/obexd-api.txt doc/agent-api.txt doc/client-api.txt -test_files = test/simple-agent test/send-files \ - test/pull-business-card test/exchange-business-cards \ +test_files = test/simple-agent test/exchange-business-cards \ test/list-folders test/pbap-client test/ftp-client \ - test/map-client + test/map-client test/opp-client gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/watch.c \ gdbus/object.c gdbus/polkit.c @@ -441,7 +474,8 @@ gobex/gobex-defs.h gobex/gobex-defs.c \ gobex/gobex-packet.c gobex/gobex-packet.h \ gobex/gobex-header.c gobex/gobex-header.h \ - gobex/gobex-transfer.c gobex/gobex-debug.h + gobex/gobex-transfer.c gobex/gobex-debug.h \ + gobex/gobex-apparam.h gobex/gobex-apparam.c @SERVER_TRUE@confdir = $(sysconfdir)/obex @SERVER_TRUE@builtin_modules = bluetooth $(am__append_2) filesystem \ @@ -452,8 +486,8 @@ @SERVER_TRUE@ $(am__append_5) plugins/opp.c plugins/ftp.c \ @SERVER_TRUE@ plugins/ftp.h plugins/pbap.c plugins/phonebook.h \ @SERVER_TRUE@ plugins/vcard.h plugins/vcard.c plugins/mas.c \ -@SERVER_TRUE@ plugins/messages.h src/map_ap.c src/map_ap.h \ -@SERVER_TRUE@ plugins/irmc.c plugins/syncevolution.c +@SERVER_TRUE@ plugins/messages.h src/map_ap.h plugins/irmc.c \ +@SERVER_TRUE@ plugins/syncevolution.c @SERVER_TRUE@builtin_nodist = plugins/phonebook.c plugins/messages.c @SERVER_TRUE@src_obexd_SOURCES = $(gdbus_sources) $(builtin_sources) $(btio_sources) \ @SERVER_TRUE@ $(gobex_sources) src/main.c src/obexd.h \ @@ -486,10 +520,10 @@ @CLIENT_TRUE@ client/opp.h client/opp.c \ @CLIENT_TRUE@ client/map.h client/map.c \ @CLIENT_TRUE@ client/transfer.h client/transfer.c \ -@CLIENT_TRUE@ client/agent.h client/agent.c \ @CLIENT_TRUE@ client/transport.h client/transport.c \ +@CLIENT_TRUE@ client/dbus.h client/dbus.c \ @CLIENT_TRUE@ client/driver.h client/driver.c \ -@CLIENT_TRUE@ src/map_ap.h src/map_ap.c +@CLIENT_TRUE@ src/map_ap.h @CLIENT_TRUE@client_obex_client_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@ service_DATA = $(service_in_files:.service.in=.service) @@ -530,6 +564,10 @@ unit/test-gobex-transfer.c unit_test_gobex_transfer_LDADD = @GLIB_LIBS@ +unit_test_gobex_apparam_SOURCES = $(gobex_sources) unit/util.c unit/util.h \ + unit/test-gobex-apparam.c + +unit_test_gobex_apparam_LDADD = @GLIB_LIBS@ @READLINE_TRUE@tools_test_client_SOURCES = $(gobex_sources) $(btio_sources) \ @READLINE_TRUE@ tools/test-client.c @@ -594,7 +632,6 @@ -rm -f config.h stamp-h1 install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)" @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -602,6 +639,8 @@ else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } @@ -625,8 +664,11 @@ done install-libexecPROGRAMS: $(libexec_PROGRAMS) @$(NORMAL_INSTALL) - test -z "$(libexecdir)" || $(MKDIR_P) "$(DESTDIR)$(libexecdir)" @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p || test -f $$p1; \ @@ -705,6 +747,8 @@ gobex/$(DEPDIR)/$(am__dirstamp) gobex/gobex-transfer.$(OBJEXT): gobex/$(am__dirstamp) \ gobex/$(DEPDIR)/$(am__dirstamp) +gobex/gobex-apparam.$(OBJEXT): gobex/$(am__dirstamp) \ + gobex/$(DEPDIR)/$(am__dirstamp) btio/$(am__dirstamp): @$(MKDIR_P) btio @: > btio/$(am__dirstamp) @@ -746,14 +790,12 @@ client/$(DEPDIR)/$(am__dirstamp) client/transfer.$(OBJEXT): client/$(am__dirstamp) \ client/$(DEPDIR)/$(am__dirstamp) -client/agent.$(OBJEXT): client/$(am__dirstamp) \ - client/$(DEPDIR)/$(am__dirstamp) client/transport.$(OBJEXT): client/$(am__dirstamp) \ client/$(DEPDIR)/$(am__dirstamp) +client/dbus.$(OBJEXT): client/$(am__dirstamp) \ + client/$(DEPDIR)/$(am__dirstamp) client/driver.$(OBJEXT): client/$(am__dirstamp) \ client/$(DEPDIR)/$(am__dirstamp) -src/map_ap.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) client/obex-client$(EXEEXT): $(client_obex_client_OBJECTS) $(client_obex_client_DEPENDENCIES) $(EXTRA_client_obex_client_DEPENDENCIES) client/$(am__dirstamp) @rm -f client/obex-client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(client_obex_client_OBJECTS) $(client_obex_client_LDADD) $(LIBS) @@ -835,6 +877,11 @@ unit/test-gobex$(EXEEXT): $(unit_test_gobex_OBJECTS) $(unit_test_gobex_DEPENDENCIES) $(EXTRA_unit_test_gobex_DEPENDENCIES) unit/$(am__dirstamp) @rm -f unit/test-gobex$(EXEEXT) $(AM_V_CCLD)$(LINK) $(unit_test_gobex_OBJECTS) $(unit_test_gobex_LDADD) $(LIBS) +unit/test-gobex-apparam.$(OBJEXT): unit/$(am__dirstamp) \ + unit/$(DEPDIR)/$(am__dirstamp) +unit/test-gobex-apparam$(EXEEXT): $(unit_test_gobex_apparam_OBJECTS) $(unit_test_gobex_apparam_DEPENDENCIES) $(EXTRA_unit_test_gobex_apparam_DEPENDENCIES) unit/$(am__dirstamp) + @rm -f unit/test-gobex-apparam$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(unit_test_gobex_apparam_OBJECTS) $(unit_test_gobex_apparam_LDADD) $(LIBS) unit/test-gobex-header.$(OBJEXT): unit/$(am__dirstamp) \ unit/$(DEPDIR)/$(am__dirstamp) unit/test-gobex-header$(EXEEXT): $(unit_test_gobex_header_OBJECTS) $(unit_test_gobex_header_DEPENDENCIES) $(EXTRA_unit_test_gobex_header_DEPENDENCIES) unit/$(am__dirstamp) @@ -854,8 +901,8 @@ mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f btio/btio.$(OBJEXT) - -rm -f client/agent.$(OBJEXT) -rm -f client/bluetooth.$(OBJEXT) + -rm -f client/dbus.$(OBJEXT) -rm -f client/driver.$(OBJEXT) -rm -f client/ftp.$(OBJEXT) -rm -f client/main.$(OBJEXT) @@ -871,6 +918,7 @@ -rm -f gdbus/object.$(OBJEXT) -rm -f gdbus/polkit.$(OBJEXT) -rm -f gdbus/watch.$(OBJEXT) + -rm -f gobex/gobex-apparam.$(OBJEXT) -rm -f gobex/gobex-defs.$(OBJEXT) -rm -f gobex/gobex-header.$(OBJEXT) -rm -f gobex/gobex-packet.$(OBJEXT) @@ -892,7 +940,6 @@ -rm -f src/log.$(OBJEXT) -rm -f src/main.$(OBJEXT) -rm -f src/manager.$(OBJEXT) - -rm -f src/map_ap.$(OBJEXT) -rm -f src/mimetype.$(OBJEXT) -rm -f src/obex.$(OBJEXT) -rm -f src/plugin.$(OBJEXT) @@ -901,6 +948,7 @@ -rm -f src/transport.$(OBJEXT) -rm -f tools/test-client.$(OBJEXT) -rm -f tools/test-server.$(OBJEXT) + -rm -f unit/test-gobex-apparam.$(OBJEXT) -rm -f unit/test-gobex-header.$(OBJEXT) -rm -f unit/test-gobex-packet.$(OBJEXT) -rm -f unit/test-gobex-transfer.$(OBJEXT) @@ -911,8 +959,8 @@ -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@btio/$(DEPDIR)/btio.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/agent.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/bluetooth.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/dbus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/driver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/ftp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/main.Po@am__quote@ @@ -928,6 +976,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@gdbus/$(DEPDIR)/object.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gdbus/$(DEPDIR)/polkit.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gdbus/$(DEPDIR)/watch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/gobex-apparam.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/gobex-defs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/gobex-header.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@gobex/$(DEPDIR)/gobex-packet.Po@am__quote@ @@ -949,7 +998,6 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/log.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/manager.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/map_ap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/mimetype.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/obex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/plugin.Po@am__quote@ @@ -958,6 +1006,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/transport.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/test-client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tools/$(DEPDIR)/test-server.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gobex-apparam.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gobex-header.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gobex-packet.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@unit/$(DEPDIR)/test-gobex-transfer.Po@am__quote@ @@ -1002,8 +1051,11 @@ -rm -f libtool config.lt install-serviceDATA: $(service_DATA) @$(NORMAL_INSTALL) - test -z "$(servicedir)" || $(MKDIR_P) "$(DESTDIR)$(servicedir)" @list='$(service_DATA)'; test -n "$(servicedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(servicedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(servicedir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -1262,7 +1314,7 @@ *.zip*) \ unzip $(distdir).zip ;;\ esac - chmod -R a-w $(distdir); chmod a+w $(distdir) + chmod -R a-w $(distdir); chmod u+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) diff -Nru obexd-0.46/plugins/bluetooth.c obexd-0.48/plugins/bluetooth.c --- obexd-0.46/plugins/bluetooth.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/bluetooth.c 2012-11-30 08:59:13.000000000 +0100 @@ -325,9 +325,8 @@ stream = FALSE; /* Read MTU if io is an L2CAP socket */ - bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_OMTU, &omtu, - BT_IO_OPT_IMTU, &imtu, - BT_IO_OPT_INVALID); + bt_io_get(io, NULL, BT_IO_OPT_OMTU, &omtu, BT_IO_OPT_IMTU, &imtu, + BT_IO_OPT_INVALID); done: if (obex_server_new_connection(server, io, omtu, imtu, stream) < 0) @@ -520,7 +519,7 @@ char address[18]; uint8_t channel; - bt_io_get(io, BT_IO_RFCOMM, &err, + bt_io_get(io, &err, BT_IO_OPT_SOURCE, source, BT_IO_OPT_DEST, address, BT_IO_OPT_CHANNEL, &channel, @@ -545,7 +544,7 @@ char address[18]; uint16_t psm; - bt_io_get(io, BT_IO_L2CAP, &err, + bt_io_get(io, &err, BT_IO_OPT_SOURCE, source, BT_IO_OPT_DEST, address, BT_IO_OPT_PSM, &psm, @@ -576,7 +575,7 @@ else sec_level = BT_IO_SEC_LOW; - io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_rfcomm, + io = bt_io_listen(NULL, confirm_rfcomm, service, NULL, &err, BT_IO_OPT_CHANNEL, service->channel, BT_IO_OPT_SEC_LEVEL, sec_level, @@ -595,7 +594,7 @@ psm = service->port == OBEX_PORT_RANDOM ? 0 : service->port; - io = bt_io_listen(BT_IO_L2CAP, NULL, confirm_l2cap, + io = bt_io_listen(NULL, confirm_l2cap, service, NULL, &err, BT_IO_OPT_PSM, psm, BT_IO_OPT_MODE, BT_IO_MODE_ERTM, @@ -610,7 +609,7 @@ service->port = 0; } else { l = g_slist_prepend(l, io); - bt_io_get(io, BT_IO_L2CAP, &err, BT_IO_OPT_PSM, &service->port, + bt_io_get(io, &err, BT_IO_OPT_PSM, &service->port, BT_IO_OPT_INVALID); DBG("listening on psm %d", service->port); } @@ -656,23 +655,10 @@ static int bluetooth_getpeername(GIOChannel *io, char **name) { - int sk = g_io_channel_unix_get_fd(io); GError *gerr = NULL; char address[18]; - int type; - socklen_t len = sizeof(int); - - if (getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0) - return -errno; - if (type == SOCK_STREAM) - bt_io_get(io, BT_IO_RFCOMM, &gerr, - BT_IO_OPT_DEST, address, - BT_IO_OPT_INVALID); - else - bt_io_get(io, BT_IO_L2CAP, &gerr, - BT_IO_OPT_DEST, address, - BT_IO_OPT_INVALID); + bt_io_get(io, &gerr, BT_IO_OPT_DEST, address, BT_IO_OPT_INVALID); if (gerr) { error("%s", gerr->message); diff -Nru obexd-0.46/plugins/filesystem.c obexd-0.48/plugins/filesystem.c --- obexd-0.46/plugins/filesystem.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/filesystem.c 2012-11-30 08:59:13.000000000 +0100 @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -604,7 +603,7 @@ len = MIN(string->len, count); memcpy(buf, string->str, len); - string = g_string_erase(string, 0, len); + g_string_erase(string, 0, len); return len; } diff -Nru obexd-0.46/plugins/irmc.c obexd-0.48/plugins/irmc.c --- obexd-0.46/plugins/irmc.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/irmc.c 2012-11-30 08:59:13.000000000 +0100 @@ -172,7 +172,7 @@ /* loop around buffer and add X-IRMC-LUID attribs */ s = buffer; while ((t = strstr(s, "UID:")) != NULL) { - /* add upto UID: into buffer */ + /* add up to UID: into buffer */ irmc->buffer = g_string_append_len(irmc->buffer, s, t-s); /* * add UID: line into buffer @@ -226,7 +226,7 @@ param->maxlistcount = 0; /* to count the number of vcards... */ param->filter = 0x200085; /* UID TEL N VERSION */ irmc->params = param; - irmc->request = phonebook_pull("telecom/pb.vcf", irmc->params, + irmc->request = phonebook_pull(PB_CONTACTS, irmc->params, phonebook_size_result, irmc, err); ret = phonebook_pull_read(irmc->request); if (err) @@ -281,7 +281,7 @@ return -EBADR; } -static void *irmc_open_devinfo(struct irmc_session *irmc, int *err) +static int irmc_open_devinfo(struct irmc_session *irmc) { if (!irmc->buffer) irmc->buffer = g_string_new(""); @@ -301,93 +301,56 @@ "NOTE-TYPE-RX:NONE\r\n", irmc->manu, irmc->model, irmc->sn); - return irmc; + return 0; } -static void *irmc_open_pb(const char *name, struct irmc_session *irmc, - int *err) +static int irmc_open_pb(struct irmc_session *irmc) { - GString *mybuf; int ret; - if (!g_strcmp0(name, ".vcf")) { - /* how can we tell if the vcard count call already finished? */ - irmc->request = phonebook_pull("telecom/pb.vcf", irmc->params, + /* how can we tell if the vcard count call already finished? */ + irmc->request = phonebook_pull(PB_CONTACTS, irmc->params, query_result, irmc, &ret); - if (ret < 0) { - DBG("phonebook_pull failed..."); - goto fail; - } - - ret = phonebook_pull_read(irmc->request); - if (ret < 0) { - DBG("phonebook_pull_read failed..."); - goto fail; - } + if (ret < 0) { + DBG("phonebook_pull failed..."); + return ret; + } - return irmc; + ret = phonebook_pull_read(irmc->request); + if (ret < 0) { + DBG("phonebook_pull_read failed..."); + return ret; } - if (!g_strcmp0(name, "/info.log")) { - mybuf = g_string_new(""); - g_string_printf(mybuf, "Total-Records:%d\r\n" + return 0; +} + +static int irmc_open_info(struct irmc_session *irmc) +{ + if (irmc->buffer == NULL) + irmc->buffer = g_string_new(""); + + g_string_printf(irmc->buffer, "Total-Records:%d\r\n" "Maximum-Records:%d\r\n" "IEL:2\r\n" "DID:%s\r\n", irmc->params->maxlistcount, irmc->params->maxlistcount, irmc->did); - } else if (!strncmp(name, "/luid/", 6)) { - name += 6; - if (!g_strcmp0(name, "cc.log")) { - mybuf = g_string_new(""); - g_string_printf(mybuf, "%d\r\n", - irmc->params->maxlistcount); - } else { - int l = strlen(name); - /* FIXME: - * Reply the same to any *.log so we hopefully force a - * full phonebook dump. - * Is IEL:2 ok? - */ - if (l > 4 && !g_strcmp0(name + l - 4, ".log")) { - DBG("changelog request, force whole book"); - mybuf = g_string_new(""); - g_string_printf(mybuf, "SN:%s\r\n" - "DID:%s\r\n" - "Total-Records:%d\r\n" - "Maximum-Records:%d\r\n" - "*\r\n", - irmc->sn, irmc->did, - irmc->params->maxlistcount, - irmc->params->maxlistcount); - } else { - ret = -EBADR; - goto fail; - } - } - } else { - ret = -EBADR; - goto fail; - } - if (!irmc->buffer) - irmc->buffer = mybuf; - else { - irmc->buffer = g_string_append(irmc->buffer, mybuf->str); - g_string_free(mybuf, TRUE); - } + return 0; +} - return irmc; +static int irmc_open_cc(struct irmc_session *irmc) +{ + if (irmc->buffer == NULL) + irmc->buffer = g_string_new(""); -fail: - if (err) - *err = ret; + g_string_printf(irmc->buffer, "%d\r\n", irmc->params->maxlistcount); - return NULL; + return 0; } -static void *irmc_open_cal(const char *name, struct irmc_session *irmc, - int *err) +static int irmc_open_cal(struct irmc_session *irmc) { /* no suport yet. Just return an empty buffer. cal.vcs */ DBG("unsupported, returning empty buffer"); @@ -395,11 +358,10 @@ if (!irmc->buffer) irmc->buffer = g_string_new(""); - return irmc; + return 0; } -static void *irmc_open_nt(const char *name, struct irmc_session *irmc, - int *err) +static int irmc_open_nt(struct irmc_session *irmc) { /* no suport yet. Just return an empty buffer. nt.vnt */ DBG("unsupported, returning empty buffer"); @@ -407,7 +369,25 @@ if (!irmc->buffer) irmc->buffer = g_string_new(""); - return irmc; + return 0; +} + +static int irmc_open_luid(struct irmc_session *irmc) +{ + if (irmc->buffer == NULL) + irmc->buffer = g_string_new(""); + + DBG("changelog request, force whole book"); + g_string_printf(irmc->buffer, "SN:%s\r\n" + "DID:%s\r\n" + "Total-Records:%d\r\n" + "Maximum-Records:%d\r\n" + "*\r\n", + irmc->sn, irmc->did, + irmc->params->maxlistcount, + irmc->params->maxlistcount); + + return 0; } static void *irmc_open(const char *name, int oflag, mode_t mode, void *context, @@ -415,7 +395,7 @@ { struct irmc_session *irmc = context; int ret = 0; - const char *p; + char *path; DBG("name %s context %p", name, context); @@ -423,20 +403,39 @@ ret = -EPERM; goto fail; } - if (name == NULL || strncmp(name, "telecom/", 8) != 0) { + + if (name == NULL) { ret = -EBADR; goto fail; } - p = name + 8; - if (!g_strcmp0(p, "devinfo.txt")) - return irmc_open_devinfo(irmc, err); - else if (!strncmp(p, "pb", 2)) - return irmc_open_pb(p+2, irmc, err); - else if (!strncmp(p, "cal", 3)) - return irmc_open_cal(p+3, irmc, err); - else if (!strncmp(p, "nt", 2)) - return irmc_open_nt(p+2, irmc, err); + /* Always contains the absolute path */ + if (g_path_is_absolute(name)) + path = g_strdup(name); + else + path = g_build_filename("/", name, NULL); + + if (g_str_equal(path, PB_DEVINFO)) + ret = irmc_open_devinfo(irmc); + else if (g_str_equal(path, PB_CONTACTS)) + ret = irmc_open_pb(irmc); + else if (g_str_equal(path, PB_INFO_LOG)) + ret = irmc_open_info(irmc); + else if (g_str_equal(path, PB_CC_LOG)) + ret = irmc_open_cc(irmc); + else if (g_str_has_prefix(path, PB_CALENDAR_FOLDER)) + ret = irmc_open_cal(irmc); + else if (g_str_has_prefix(path, PB_NOTES_FOLDER)) + ret = irmc_open_nt(irmc); + else if (g_str_has_prefix(path, PB_LUID_FOLDER)) + ret = irmc_open_luid(irmc); + else + ret = -EBADR; + + g_free(path); + + if (ret == 0) + return irmc; fail: if (err) diff -Nru obexd-0.46/plugins/mas.c obexd-0.48/plugins/mas.c --- obexd-0.46/plugins/mas.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/mas.c 2012-11-30 08:59:13.000000000 +0100 @@ -32,6 +32,7 @@ #include #include +#include #include "obexd.h" #include "plugin.h" @@ -45,6 +46,9 @@ #include "messages.h" +#define READ_STATUS_REQ 0 +#define DELETE_STATUS_REQ 1 + /* Channel number according to bluez doc/assigned-numbers.txt */ #define MAS_CHANNEL 16 @@ -112,8 +116,8 @@ gboolean finished; gboolean nth_call; GString *buffer; - map_ap_t *inparams; - map_ap_t *outparams; + GObexApparam *inparams; + GObexApparam *outparams; gboolean ap_sent; }; @@ -130,14 +134,12 @@ if (size < 0) size = 0; - mas->inparams = map_ap_decode(buffer, size); + mas->inparams = g_obex_apparam_decode(buffer, size); if (mas->inparams == NULL) { DBG("Error when parsing parameters!"); return -EBADR; } - mas->outparams = map_ap_new(); - return 0; } @@ -148,13 +150,19 @@ mas->buffer = NULL; } - map_ap_free(mas->inparams); - mas->inparams = NULL; - map_ap_free(mas->outparams); - mas->outparams = NULL; + if (mas->inparams) { + g_obex_apparam_free(mas->inparams); + mas->inparams = NULL; + } + + if (mas->outparams) { + g_obex_apparam_free(mas->outparams); + mas->outparams = NULL; + } mas->nth_call = FALSE; mas->finished = FALSE; + mas->ap_sent = FALSE; } static void mas_clean(struct mas_session *mas) @@ -289,7 +297,7 @@ return; } - map_ap_get_u16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max); + g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max); if (max == 0) { if (!entry) @@ -390,10 +398,12 @@ proceed: if (!entry) { - map_ap_set_u16(mas->outparams, MAP_AP_MESSAGESLISTINGSIZE, - size); - map_ap_set_u8(mas->outparams, MAP_AP_NEWMESSAGE, - newmsg ? 1 : 0); + mas->outparams = g_obex_apparam_set_uint16(mas->outparams, + MAP_AP_MESSAGESLISTINGSIZE, + size); + mas->outparams = g_obex_apparam_set_uint8(mas->outparams, + MAP_AP_NEWMESSAGE, + newmsg ? 1 : 0); } if (err != -EAGAIN) @@ -435,12 +445,14 @@ return; } - map_ap_get_u16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max); + g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max); if (max == 0) { if (err != -EAGAIN) - map_ap_set_u16(mas->outparams, - MAP_AP_FOLDERLISTINGSIZE, size); + mas->outparams = g_obex_apparam_set_uint16( + mas->outparams, + MAP_AP_FOLDERLISTINGSIZE, + size); if (!name) mas->finished = TRUE; @@ -477,7 +489,7 @@ obex_object_set_io_flags(mas, G_IO_IN, err); } -static void update_inbox_cb(void *session, int err, void *user_data) +static void set_status_cb(void *session, int err, void *user_data) { struct mas_session *mas = user_data; @@ -529,8 +541,8 @@ DBG("name = %s", name); - map_ap_get_u16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max); - map_ap_get_u16(mas->inparams, MAP_AP_STARTOFFSET, &offset); + g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max); + g_obex_apparam_get_uint16(mas->inparams, MAP_AP_STARTOFFSET, &offset); *err = messages_get_folder_listing(mas->backend_data, name, max, offset, get_folder_listing_cb, mas); @@ -551,6 +563,9 @@ /* 1024 is the default when there was no MaxListCount sent */ uint16_t max = 1024; uint16_t offset = 0; + /* If MAP client does not specify the subject length, + then subject_len = 0 and subject should be sent unaltered. */ + uint8_t subject_len = 0; DBG(""); @@ -559,28 +574,30 @@ return NULL; } - map_ap_get_u16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max); - map_ap_get_u16(mas->inparams, MAP_AP_STARTOFFSET, &offset); + g_obex_apparam_get_uint16(mas->inparams, MAP_AP_MAXLISTCOUNT, &max); + g_obex_apparam_get_uint16(mas->inparams, MAP_AP_STARTOFFSET, &offset); + g_obex_apparam_get_uint8(mas->inparams, MAP_AP_SUBJECTLENGTH, + &subject_len); - map_ap_get_u32(mas->inparams, MAP_AP_PARAMETERMASK, + g_obex_apparam_get_uint32(mas->inparams, MAP_AP_PARAMETERMASK, &filter.parameter_mask); - map_ap_get_u8(mas->inparams, MAP_AP_FILTERMESSAGETYPE, + g_obex_apparam_get_uint8(mas->inparams, MAP_AP_FILTERMESSAGETYPE, &filter.type); - filter.period_begin = map_ap_get_string(mas->inparams, + filter.period_begin = g_obex_apparam_get_string(mas->inparams, MAP_AP_FILTERPERIODBEGIN); - filter.period_end = map_ap_get_string(mas->inparams, + filter.period_end = g_obex_apparam_get_string(mas->inparams, MAP_AP_FILTERPERIODEND); - map_ap_get_u8(mas->inparams, MAP_AP_FILTERREADSTATUS, + g_obex_apparam_get_uint8(mas->inparams, MAP_AP_FILTERREADSTATUS, &filter.read_status); - filter.recipient = map_ap_get_string(mas->inparams, + filter.recipient = g_obex_apparam_get_string(mas->inparams, MAP_AP_FILTERRECIPIENT); - filter.originator = map_ap_get_string(mas->inparams, + filter.originator = g_obex_apparam_get_string(mas->inparams, MAP_AP_FILTERORIGINATOR); - map_ap_get_u8(mas->inparams, MAP_AP_FILTERPRIORITY, + g_obex_apparam_get_uint8(mas->inparams, MAP_AP_FILTERPRIORITY, &filter.priority); *err = messages_get_messages_listing(mas->backend_data, name, max, - offset, &filter, + offset, subject_len, &filter, get_messages_listing_cb, mas); mas->buffer = g_string_new(""); @@ -624,24 +641,65 @@ DBG(""); - if (oflag != O_WRONLY) { + if (oflag == O_RDONLY) { *err = -EBADR; return NULL; } - *err = messages_update_inbox(mas->backend_data, update_inbox_cb, mas); + *err = messages_update_inbox(mas->backend_data, set_status_cb, mas); if (*err < 0) return NULL; else return mas; } +static void *message_set_status_open(const char *name, int oflag, mode_t mode, + void *driver_data, size_t *size, + int *err) + +{ + struct mas_session *mas = driver_data; + uint8_t indicator; + uint8_t value; + + DBG(""); + + if (oflag == O_RDONLY) { + *err = -EBADR; + return NULL; + } + + if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_STATUSINDICATOR, + &indicator)) { + *err = -EBADR; + return NULL; + } + + if (!g_obex_apparam_get_uint8(mas->inparams, MAP_AP_STATUSVALUE, + &value)) { + *err = -EBADR; + return NULL; + } + + if (indicator == READ_STATUS_REQ) + *err = messages_set_read(mas->backend_data, name, value, + set_status_cb, mas); + else if (indicator == DELETE_STATUS_REQ) + *err = messages_set_delete(mas->backend_data, name, value, + set_status_cb, mas); + else + *err = -EBADR; + + if (*err < 0) + return NULL; + + return mas; +} + static ssize_t any_get_next_header(void *object, void *buf, size_t mtu, uint8_t *hi) { struct mas_session *mas = object; - size_t len; - uint8_t *apbuf; DBG(""); @@ -654,18 +712,7 @@ return 0; mas->ap_sent = TRUE; - apbuf = map_ap_encode(mas->outparams, &len); - - if (len > mtu) { - DBG("MTU is to small to fit application parameters header!"); - g_free(apbuf); - - return -EIO; - } - - memcpy(buf, apbuf, len); - - return len; + return g_obex_apparam_encode(mas->outparams, buf, mtu); } static void *any_open(const char *name, int oflag, mode_t mode, @@ -764,6 +811,7 @@ .target = MAS_TARGET, .target_size = TARGET_SIZE, .mimetype = "x-bt/MAP-msg-listing", + .get_next_header = any_get_next_header, .open = msg_listing_open, .close = any_close, .read = any_read, @@ -784,7 +832,7 @@ .target = MAS_TARGET, .target_size = TARGET_SIZE, .mimetype = "x-bt/messageStatus", - .open = any_open, + .open = message_set_status_open, .close = any_close, .read = any_read, .write = any_write, diff -Nru obexd-0.46/plugins/messages-dummy.c obexd-0.48/plugins/messages-dummy.c --- obexd-0.46/plugins/messages-dummy.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/messages-dummy.c 2012-11-30 08:59:13.000000000 +0100 @@ -331,6 +331,7 @@ 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) @@ -346,11 +347,23 @@ return -ENOSYS; } -int messages_update_inbox(void *session, messages_update_inbox_cb callback, +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 *s) { diff -Nru obexd-0.46/plugins/messages.h obexd-0.48/plugins/messages.h --- obexd-0.46/plugins/messages.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/messages.h 2012-11-30 08:59:13.000000000 +0100 @@ -215,6 +215,8 @@ * session: Backend session. * name: Optional subdirectory name. * max: Maximum number of entries to retrieve. + * offset: Offset of the first entry. + * subject_len: Maximum string length of the "subject" parameter in the entries. * filter: Filter to apply on returned message listing. * size: Total size of listing to be returned. * newmsg: Indicates presence of unread messages. @@ -229,6 +231,7 @@ 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); @@ -265,17 +268,39 @@ messages_get_message_cb callback, void *user_data); +typedef void (*messages_status_cb)(void *session, int err, void *user_data); + /* Informs Message Server to Update Inbox via network. * * session: Backend session. * user_data: User data if any to be sent. - * Callback shall be called for every update inbox request recieved from MCE. + * Callback shall be called for every update inbox request received from MCE. */ -typedef void (*messages_update_inbox_cb)(void *session, int err, +int messages_update_inbox(void *session, messages_status_cb callback, void *user_data); +/* Informs Message Server to modify read status of a given message. + * + * session: Backend session. + * handle: Unique identifier to the message. + * value: Indicates the new value of the read status for a given message. + * Callback shall be called for every read status update request + * recieved from MCE. + * user_data: User data if any to be sent. + */ +int messages_set_read(void *session, const char *handle, uint8_t value, + messages_status_cb callback, void *user_data); -int messages_update_inbox(void *session, messages_update_inbox_cb callback, - void *user_data); +/* Informs Message Server to modify delete status of a given message. + * + * session: Backend session. + * handle: Unique identifier to the message. + * value: Indicates the new value of the delete status for a given message. + * Callback shall be called for every delete status update request + * recieved from MCE. + * user_data: User data if any to be sent. + */ +int messages_set_delete(void *session, const char *handle, uint8_t value, + messages_status_cb callback, void *user_data); /* Aborts currently pending request. * diff -Nru obexd-0.46/plugins/messages-tracker.c obexd-0.48/plugins/messages-tracker.c --- obexd-0.46/plugins/messages-tracker.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/messages-tracker.c 2012-11-30 08:59:13.000000000 +0100 @@ -303,9 +303,9 @@ return 0; } -int messages_get_messages_listing(void *session, - const char *name, +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) @@ -321,11 +321,24 @@ return -ENOSYS; } -int messages_update_inbox(void *session, messages_update_inbox_cb callback, +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) { diff -Nru obexd-0.46/plugins/pbap.c obexd-0.48/plugins/pbap.c --- obexd-0.46/plugins/pbap.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/pbap.c 2012-11-30 08:59:13.000000000 +0100 @@ -39,6 +39,7 @@ #include #include +#include #include "obexd.h" #include "plugin.h" @@ -64,16 +65,6 @@ #define PHONEBOOKSIZE_TAG 0X08 #define NEWMISSEDCALLS_TAG 0X09 -/* The following length is in the unit of byte */ -#define ORDER_LEN 1 -#define SEARCHATTRIB_LEN 1 -#define MAXLISTCOUNT_LEN 2 -#define LISTSTARTOFFSET_LEN 2 -#define FILTER_LEN 8 -#define FORMAT_LEN 1 -#define PHONEBOOKSIZE_LEN 2 -#define NEWMISSEDCALLS_LEN 1 - #define PBAP_CHANNEL 15 #define PBAP_RECORD " \ @@ -117,12 +108,6 @@ \ " -struct aparam_header { - uint8_t tag; - uint8_t len; - uint8_t val[0]; -} __attribute__ ((packed)); - struct cache { gboolean valid; uint32_t index; @@ -147,7 +132,7 @@ struct pbap_object { GString *buffer; - GByteArray *aparams; + GObexApparam *apparam; gboolean firstpacket; gboolean lastpart; struct pbap_session *session; @@ -229,33 +214,6 @@ cache->entries = NULL; } -static GByteArray *append_aparam_header(GByteArray *buf, uint8_t tag, - const void *val) -{ - /* largest aparam is for phonebooksize (4 bytes) */ - uint8_t aparam[sizeof(struct aparam_header) + PHONEBOOKSIZE_LEN]; - struct aparam_header *hdr = (struct aparam_header *) aparam; - - switch (tag) { - case PHONEBOOKSIZE_TAG: - hdr->tag = PHONEBOOKSIZE_TAG; - hdr->len = PHONEBOOKSIZE_LEN; - memcpy(hdr->val, val, PHONEBOOKSIZE_LEN); - - return g_byte_array_append(buf, aparam, - sizeof(struct aparam_header) + PHONEBOOKSIZE_LEN); - case NEWMISSEDCALLS_TAG: - hdr->tag = NEWMISSEDCALLS_TAG; - hdr->len = NEWMISSEDCALLS_LEN; - memcpy(hdr->val, val, NEWMISSEDCALLS_LEN); - - return g_byte_array_append(buf, aparam, - sizeof(struct aparam_header) + NEWMISSEDCALLS_LEN); - default: - return buf; - } -} - static void phonebook_size_result(const char *buffer, size_t bufsize, int vcards, int missed, gboolean lastpart, void *user_data) @@ -275,15 +233,16 @@ phonebooksize = htons(vcards); - pbap->obj->aparams = g_byte_array_new(); - pbap->obj->aparams = append_aparam_header(pbap->obj->aparams, - PHONEBOOKSIZE_TAG, &phonebooksize); + pbap->obj->apparam = g_obex_apparam_set_uint16(NULL, PHONEBOOKSIZE_TAG, + phonebooksize); if (missed > 0) { DBG("missed %d", missed); - pbap->obj->aparams = append_aparam_header(pbap->obj->aparams, - NEWMISSEDCALLS_TAG, &missed); + pbap->obj->apparam = g_obex_apparam_set_uint16( + pbap->obj->apparam, + NEWMISSEDCALLS_TAG, + missed); } obex_object_set_io_flags(pbap->obj, G_IO_IN, 0); @@ -319,9 +278,10 @@ pbap->obj->firstpacket = TRUE; - pbap->obj->aparams = g_byte_array_new(); - pbap->obj->aparams = append_aparam_header(pbap->obj->aparams, - NEWMISSEDCALLS_TAG, &missed); + pbap->obj->apparam = g_obex_apparam_set_uint16( + pbap->obj->apparam, + NEWMISSEDCALLS_TAG, + missed); } obex_object_set_io_flags(pbap->obj, G_IO_IN, 0); @@ -450,9 +410,10 @@ /* Ignore all other parameter and return PhoneBookSize */ uint16_t size = htons(g_slist_length(pbap->cache.entries)); - pbap->obj->aparams = g_byte_array_new(); - pbap->obj->aparams = append_aparam_header(pbap->obj->aparams, - PHONEBOOKSIZE_TAG, &size); + pbap->obj->apparam = g_obex_apparam_set_uint16( + pbap->obj->apparam, + PHONEBOOKSIZE_TAG, + size); return 0; } @@ -527,85 +488,34 @@ static struct apparam_field *parse_aparam(const uint8_t *buffer, uint32_t hlen) { + GObexApparam *apparam; struct apparam_field *param; - struct aparam_header *hdr; - uint64_t val64; - uint32_t len = 0; - uint16_t val16; - - param = g_new0(struct apparam_field, 1); - - while (len < hlen) { - hdr = (void *) buffer + len; - - switch (hdr->tag) { - case ORDER_TAG: - if (hdr->len != ORDER_LEN) - goto failed; - - param->order = hdr->val[0]; - break; - - case SEARCHATTRIB_TAG: - if (hdr->len != SEARCHATTRIB_LEN) - goto failed; - - param->searchattrib = hdr->val[0]; - break; - case SEARCHVALUE_TAG: - if (hdr->len == 0) - goto failed; - - param->searchval = g_try_malloc0(hdr->len + 1); - if (param->searchval) - memcpy(param->searchval, hdr->val, hdr->len); - break; - case FILTER_TAG: - if (hdr->len != FILTER_LEN) - goto failed; - - memcpy(&val64, hdr->val, sizeof(val64)); - param->filter = GUINT64_FROM_BE(val64); - - break; - case FORMAT_TAG: - if (hdr->len != FORMAT_LEN) - goto failed; - param->format = hdr->val[0]; - break; - case MAXLISTCOUNT_TAG: - if (hdr->len != MAXLISTCOUNT_LEN) - goto failed; + apparam = g_obex_apparam_decode(buffer, hlen); + if (apparam == NULL) + return NULL; - memcpy(&val16, hdr->val, sizeof(val16)); - param->maxlistcount = GUINT16_FROM_BE(val16); - break; - case LISTSTARTOFFSET_TAG: - if (hdr->len != LISTSTARTOFFSET_LEN) - goto failed; - - memcpy(&val16, hdr->val, sizeof(val16)); - param->liststartoffset = GUINT16_FROM_BE(val16); - break; - default: - goto failed; - } + param = g_new0(struct apparam_field, 1); - len += hdr->len + sizeof(struct aparam_header); - } + g_obex_apparam_get_uint8(apparam, ORDER_TAG, ¶m->order); + g_obex_apparam_get_uint8(apparam, SEARCHATTRIB_TAG, + ¶m->searchattrib); + g_obex_apparam_get_uint8(apparam, FORMAT_TAG, ¶m->format); + g_obex_apparam_get_uint16(apparam, MAXLISTCOUNT_TAG, + ¶m->maxlistcount); + g_obex_apparam_get_uint16(apparam, LISTSTARTOFFSET_TAG, + ¶m->liststartoffset); + g_obex_apparam_get_uint64(apparam, FILTER_TAG, ¶m->filter); + param->searchval = g_obex_apparam_get_string(apparam, SEARCHVALUE_TAG); DBG("o %x sa %x sv %s fil %" G_GINT64_MODIFIER "x for %x max %x off %x", param->order, param->searchattrib, param->searchval, param->filter, param->format, param->maxlistcount, param->liststartoffset); - return param; - -failed: - g_free(param); + g_obex_apparam_free(apparam); - return NULL; + return param; } static void *pbap_connect(struct obex_session *os, int *err) @@ -839,8 +749,8 @@ if (obj->buffer) g_string_free(obj->buffer, TRUE); - if (obj->aparams) - g_byte_array_free(obj->aparams, TRUE); + if (obj->apparam) + g_obex_apparam_free(obj->apparam); if (obj->request) phonebook_req_finalize(obj->request); @@ -952,27 +862,13 @@ return NULL; } -static ssize_t array_read(GByteArray *array, void *buf, size_t count) -{ - ssize_t len; - - if (array->len == 0) - return 0; - - len = MIN(array->len, count); - memcpy(buf, array->data, len); - array = g_byte_array_remove_range(array, 0, len); - - return len; -} - static ssize_t vobject_pull_get_next_header(void *object, void *buf, size_t mtu, uint8_t *hi) { struct pbap_object *obj = object; struct pbap_session *pbap = obj->session; - if (!obj->buffer && !obj->aparams) + if (!obj->buffer && !obj->apparam) return -EAGAIN; *hi = G_OBEX_HDR_APPARAM; @@ -980,7 +876,7 @@ if (pbap->params->maxlistcount == 0 || obj->firstpacket) { obj->firstpacket = FALSE; - return array_read(obj->aparams, buf, mtu); + return g_obex_apparam_encode(obj->apparam, buf, mtu); } return 0; @@ -1031,7 +927,7 @@ *hi = G_OBEX_HDR_APPARAM; if (pbap->params->maxlistcount == 0) - return array_read(obj->aparams, buf, mtu); + return g_obex_apparam_encode(obj->apparam, buf, mtu); return 0; } diff -Nru obexd-0.46/plugins/phonebook-dummy.c obexd-0.48/plugins/phonebook-dummy.c --- obexd-0.46/plugins/phonebook-dummy.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/phonebook-dummy.c 2012-07-26 19:09:25.000000000 +0200 @@ -218,7 +218,7 @@ struct dummy_data *dummy = user_data; GString *buffer; DIR *dp; - uint16_t count, max, offset; + uint16_t count = 0, max, offset; buffer = g_string_new(""); diff -Nru obexd-0.46/plugins/phonebook-ebook.c obexd-0.48/plugins/phonebook-ebook.c --- obexd-0.46/plugins/phonebook-ebook.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/phonebook-ebook.c 2012-11-30 08:59:13.000000000 +0100 @@ -37,7 +37,6 @@ #include "obex.h" #include "service.h" #include "phonebook.h" -#include "glib-helper.h" #define QUERY_FN "(contains \"family_name\" \"%s\")" #define QUERY_NAME "(contains \"given_name\" \"%s\")" @@ -460,7 +459,7 @@ root = (g_strcmp0("/", current_folder) == 0); child = (new_folder && strlen(new_folder) != 0); - /* Evolution back-end will support telecom/pb folder only */ + /* Evolution back-end will support /telecom/pb folder only */ switch (flags) { case 0x02: @@ -472,8 +471,8 @@ /* Go down 1 level */ fullname = g_build_filename(current_folder, new_folder, NULL); - if (strcmp("/telecom", fullname) != 0 && - strcmp("/telecom/pb", fullname) != 0) { + if (strcmp(PB_TELECOM_FOLDER, fullname) != 0 && + strcmp(PB_CONTACTS_FOLDER, fullname) != 0) { g_free(fullname); fullname = NULL; ret = -ENOENT; @@ -512,8 +511,8 @@ } fullname = g_build_filename(base, new_folder, NULL); - if (strcmp(fullname, "/telecom") != 0 && - strcmp(fullname, "/telecom/pb") != 0) { + if (strcmp(fullname, PB_TELECOM_FOLDER) != 0 && + strcmp(fullname, PB_CONTACTS_FOLDER) != 0) { g_free(fullname); fullname = NULL; ret = -ENOENT; @@ -549,7 +548,7 @@ { struct query_context *data; - if (g_strcmp0("/telecom/pb.vcf", name) != 0) { + if (g_strcmp0(PB_CONTACTS, name) != 0) { if (err) *err = -ENOENT; @@ -639,7 +638,7 @@ EVCardAttribute *attrib; char *uid, *tel, *cname; - if (g_strcmp0("/telecom/pb", name) != 0) { + if (g_strcmp0(PB_CONTACTS_FOLDER, name) != 0) { if (err) *err = -ENOENT; diff -Nru obexd-0.46/plugins/phonebook.h obexd-0.48/plugins/phonebook.h --- obexd-0.46/plugins/phonebook.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/phonebook.h 2012-11-30 08:59:13.000000000 +0100 @@ -29,6 +29,26 @@ #define VCARD_LISTING_ELEMENT "" EOL #define VCARD_LISTING_END "" +#define PB_TELECOM_FOLDER "/telecom" +#define PB_CONTACTS_FOLDER "/telecom/pb" +#define PB_CALENDAR_FOLDER "/telecom/cal" +#define PB_NOTES_FOLDER "/telecom/nt" +#define PB_CALLS_COMBINED_FOLDER "/telecom/cch" +#define PB_CALLS_INCOMING_FOLDER "/telecom/ich" +#define PB_CALLS_MISSED_FOLDER "/telecom/mch" +#define PB_CALLS_OUTGOING_FOLDER "/telecom/och" +#define PB_LUID_FOLDER "/telecom/luid" + +#define PB_CONTACTS "/telecom/pb.vcf" +#define PB_CALLS_COMBINED "/telecom/cch.vcf" +#define PB_CALLS_INCOMING "/telecom/ich.vcf" +#define PB_CALLS_MISSED "/telecom/mch.vcf" +#define PB_CALLS_OUTGOING "/telecom/och.vcf" +#define PB_DEVINFO "/telecom/devinfo.txt" +#define PB_INFO_LOG "/telecom/pb/info.log" +#define PB_CC_LOG "/telecom/pb/luid/cc.log" + + struct apparam_field { /* list and pull attributes */ uint16_t maxlistcount; @@ -41,7 +61,7 @@ /* list attributes only */ uint8_t order; uint8_t searchattrib; - uint8_t *searchval; + char *searchval; }; /* diff -Nru obexd-0.46/plugins/phonebook-tracker.c obexd-0.48/plugins/phonebook-tracker.c --- obexd-0.46/plugins/phonebook-tracker.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/phonebook-tracker.c 2012-11-30 08:59:13.000000000 +0100 @@ -35,7 +35,6 @@ #include "mimetype.h" #include "phonebook.h" #include "vcard.h" -#include "glib-helper.h" #define TRACKER_SERVICE "org.freedesktop.Tracker1" #define TRACKER_RESOURCES_PATH "/org/freedesktop/Tracker1/Resources" @@ -514,15 +513,15 @@ static const char *name2query(const char *name) { - if (g_str_equal(name, "/telecom/pb.vcf")) + if (g_str_equal(name, PB_CONTACTS)) return CONTACTS_QUERY_ALL; - else if (g_str_equal(name, "/telecom/ich.vcf")) + else if (g_str_equal(name, PB_CALLS_INCOMING)) return INCOMING_CALLS_QUERY; - else if (g_str_equal(name, "/telecom/och.vcf")) + else if (g_str_equal(name, PB_CALLS_OUTGOING)) return OUTGOING_CALLS_QUERY; - else if (g_str_equal(name, "/telecom/mch.vcf")) + else if (g_str_equal(name, PB_CALLS_MISSED)) return MISSED_CALLS_QUERY; - else if (g_str_equal(name, "/telecom/cch.vcf")) + else if (g_str_equal(name, PB_CALLS_COMBINED)) return COMBINED_CALLS_QUERY; return NULL; @@ -530,15 +529,15 @@ static const char *name2count_query(const char *name) { - if (g_str_equal(name, "/telecom/pb.vcf")) + if (g_str_equal(name, PB_CONTACTS)) return CONTACTS_COUNT_QUERY; - else if (g_str_equal(name, "/telecom/ich.vcf")) + else if (g_str_equal(name, PB_CALLS_INCOMING)) return INCOMING_CALLS_COUNT_QUERY; - else if (g_str_equal(name, "/telecom/och.vcf")) + else if (g_str_equal(name, PB_CALLS_OUTGOING)) return OUTGOING_CALLS_COUNT_QUERY; - else if (g_str_equal(name, "/telecom/mch.vcf")) + else if (g_str_equal(name, PB_CALLS_MISSED)) return MISSED_CALLS_COUNT_QUERY; - else if (g_str_equal(name, "/telecom/cch.vcf")) + else if (g_str_equal(name, PB_CALLS_COMBINED)) return COMBINED_CALLS_COUNT_QUERY; return NULL; @@ -551,17 +550,17 @@ if (g_str_equal(folder, "/")) return TRUE; - else if (g_str_equal(folder, "/telecom")) + else if (g_str_equal(folder, PB_TELECOM_FOLDER)) return TRUE; - else if (g_str_equal(folder, "/telecom/pb")) + else if (g_str_equal(folder, PB_CONTACTS_FOLDER)) return TRUE; - else if (g_str_equal(folder, "/telecom/ich")) + else if (g_str_equal(folder, PB_CALLS_INCOMING_FOLDER)) return TRUE; - else if (g_str_equal(folder, "/telecom/och")) + else if (g_str_equal(folder, PB_CALLS_OUTGOING_FOLDER)) return TRUE; - else if (g_str_equal(folder, "/telecom/mch")) + else if (g_str_equal(folder, PB_CALLS_MISSED_FOLDER)) return TRUE; - else if (g_str_equal(folder, "/telecom/cch")) + else if (g_str_equal(folder, PB_CALLS_COMBINED_FOLDER)) return TRUE; return FALSE; @@ -569,15 +568,15 @@ static const char *folder2query(const char *folder) { - if (g_str_equal(folder, "/telecom/pb")) + if (g_str_equal(folder, PB_CONTACTS_FOLDER)) return CONTACTS_QUERY_ALL_LIST; - else if (g_str_equal(folder, "/telecom/ich")) + else if (g_str_equal(folder, PB_CALLS_INCOMING_FOLDER)) return INCOMING_CALLS_LIST; - else if (g_str_equal(folder, "/telecom/och")) + else if (g_str_equal(folder, PB_CALLS_OUTGOING_FOLDER)) return OUTGOING_CALLS_LIST; - else if (g_str_equal(folder, "/telecom/mch")) + else if (g_str_equal(folder, PB_CALLS_MISSED_FOLDER)) return MISSED_CALLS_LIST; - else if (g_str_equal(folder, "/telecom/cch")) + else if (g_str_equal(folder, PB_CALLS_COMBINED_FOLDER)) return COMBINED_CALLS_LIST; return NULL; @@ -1542,11 +1541,11 @@ } if (data->params->maxlistcount == 0) { - query = name2count_query("/telecom/mch.vcf"); + query = name2count_query(PB_CALLS_MISSED); col_amount = COUNT_QUERY_COL_AMOUNT; pull_cb = pull_contacts_size; } else { - query = name2query("/telecom/mch.vcf"); + query = name2query(PB_CALLS_MISSED); col_amount = PULL_QUERY_COL_AMOUNT; pull_cb = pull_contacts; } @@ -1614,7 +1613,7 @@ data->newmissedcalls = 0; - if (g_strcmp0(data->req_name, "/telecom/mch.vcf") == 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 diff -Nru obexd-0.46/plugins/syncevolution.c obexd-0.48/plugins/syncevolution.c --- obexd-0.46/plugins/syncevolution.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/plugins/syncevolution.c 2012-07-26 19:09:25.000000000 +0200 @@ -365,8 +365,7 @@ append_dict_entry(&dict, "id", DBUS_TYPE_STRING, context->id); - snprintf(transport, sizeof(transport), "%s.obexd", - OPENOBEX_SERVICE); + snprintf(transport, sizeof(transport), "%s.obexd", OBEXD_SERVICE); append_dict_entry(&dict, "transport", DBUS_TYPE_STRING, transport); snprintf(transport_description, sizeof(transport_description), diff -Nru obexd-0.46/src/manager.c obexd-0.48/src/manager.c --- obexd-0.46/src/manager.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/src/manager.c 2012-07-26 19:09:25.000000000 +0200 @@ -44,11 +44,12 @@ #include "btio.h" #include "service.h" -#define OPENOBEX_MANAGER_PATH "/" -#define OPENOBEX_MANAGER_INTERFACE OPENOBEX_SERVICE ".Manager" -#define ERROR_INTERFACE OPENOBEX_SERVICE ".Error" -#define TRANSFER_INTERFACE OPENOBEX_SERVICE ".Transfer" -#define SESSION_INTERFACE OPENOBEX_SERVICE ".Session" +#define OBEX_MANAGER_PATH "/" +#define OBEX_MANAGER_INTERFACE OBEXD_SERVICE ".Manager" +#define ERROR_INTERFACE OBEXD_SERVICE ".Error" +#define TRANSFER_INTERFACE OBEXD_SERVICE ".Transfer" +#define SESSION_INTERFACE OBEXD_SERVICE ".Session" +#define AGENT_INTERFACE OBEXD_SERVICE ".Agent" #define TIMEOUT 60*1000 /* Timeout for user response (miliseconds) */ @@ -310,32 +311,38 @@ return dbus_message_new_method_return(msg); } -static GDBusMethodTable manager_methods[] = { - { "RegisterAgent", "o", "", register_agent }, - { "UnregisterAgent", "o", "", unregister_agent }, +static const GDBusMethodTable manager_methods[] = { + { GDBUS_METHOD("RegisterAgent", + GDBUS_ARGS({ "agent", "o" }), NULL, register_agent) }, + { GDBUS_METHOD("UnregisterAgent", + GDBUS_ARGS({ "agent", "o" }), NULL, unregister_agent) }, { } }; -static GDBusSignalTable manager_signals[] = { - { "TransferStarted", "o" }, - { "TransferCompleted", "ob" }, - { "SessionCreated", "o" }, - { "SessionRemoved", "o" }, +static const GDBusSignalTable manager_signals[] = { + { GDBUS_SIGNAL("TransferStarted", GDBUS_ARGS({ "transfer", "o"})) }, + { GDBUS_SIGNAL("TransferCompleted", GDBUS_ARGS({ "transfer", "o" }, + { "success", "b" })) }, + { GDBUS_SIGNAL("SessionCreated", GDBUS_ARGS({ "session", "o" })) }, + { GDBUS_SIGNAL("SessionRemoved", GDBUS_ARGS({ "session", "o" })) }, { } }; -static GDBusMethodTable transfer_methods[] = { - { "Cancel", "", "", transfer_cancel }, +static const GDBusMethodTable transfer_methods[] = { + { GDBUS_METHOD("Cancel", NULL, NULL, transfer_cancel) }, { } }; -static GDBusSignalTable transfer_signals[] = { - { "Progress", "ii" }, +static const GDBusSignalTable transfer_signals[] = { + { GDBUS_SIGNAL("Progress", GDBUS_ARGS({ "total", "i" }, + { "transferred", "i" })) }, { } }; -static GDBusMethodTable session_methods[] = { - { "GetProperties", "", "{sv}", get_properties }, +static const GDBusMethodTable session_methods[] = { + { GDBUS_METHOD("GetProperties", + NULL, GDBUS_ARGS({ "properties", "a{sv}" }), + get_properties) }, { } }; @@ -347,8 +354,7 @@ dbus_error_init(&err); - connection = g_dbus_setup_bus(DBUS_BUS_SESSION, OPENOBEX_SERVICE, - &err); + connection = g_dbus_setup_bus(DBUS_BUS_SESSION, OBEXD_SERVICE, &err); if (connection == NULL) { if (dbus_error_is_set(&err) == TRUE) { fprintf(stderr, "%s\n", err.message); @@ -358,8 +364,8 @@ return FALSE; } - return g_dbus_register_interface(connection, OPENOBEX_MANAGER_PATH, - OPENOBEX_MANAGER_INTERFACE, + return g_dbus_register_interface(connection, OBEX_MANAGER_PATH, + OBEX_MANAGER_INTERFACE, manager_methods, manager_signals, NULL, NULL, NULL); } @@ -368,8 +374,8 @@ { DBG(""); - g_dbus_unregister_interface(connection, OPENOBEX_MANAGER_PATH, - OPENOBEX_MANAGER_INTERFACE); + g_dbus_unregister_interface(connection, OBEX_MANAGER_PATH, + OBEX_MANAGER_INTERFACE); /* FIXME: Release agent? */ @@ -383,8 +389,8 @@ { char *path = g_strdup_printf("/transfer%u", os->id); - g_dbus_emit_signal(connection, OPENOBEX_MANAGER_PATH, - OPENOBEX_MANAGER_INTERFACE, "TransferStarted", + g_dbus_emit_signal(connection, OBEX_MANAGER_PATH, + OBEX_MANAGER_INTERFACE, "TransferStarted", DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); @@ -395,8 +401,8 @@ { char *path = g_strdup_printf("/transfer%u", os->id); - g_dbus_emit_signal(connection, OPENOBEX_MANAGER_PATH, - OPENOBEX_MANAGER_INTERFACE, "TransferCompleted", + g_dbus_emit_signal(connection, OBEX_MANAGER_PATH, + OBEX_MANAGER_INTERFACE, "TransferCompleted", DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_BOOLEAN, &success, DBUS_TYPE_INVALID); @@ -405,14 +411,14 @@ } static void emit_transfer_progress(struct obex_session *os, uint32_t total, - uint32_t transfered) + uint32_t transferred) { char *path = g_strdup_printf("/transfer%u", os->id); g_dbus_emit_signal(connection, path, TRANSFER_INTERFACE, "Progress", DBUS_TYPE_INT32, &total, - DBUS_TYPE_INT32, &transfered, + DBUS_TYPE_INT32, &transferred, DBUS_TYPE_INVALID); g_free(path); @@ -456,7 +462,7 @@ return; msg = dbus_message_new_method_call(agent->bus_name, agent->path, - "org.openobex.Agent", "Cancel"); + AGENT_INTERFACE, "Cancel"); g_dbus_send_message(connection, msg); } @@ -542,7 +548,7 @@ path = g_strdup_printf("/transfer%u", os->id); msg = dbus_message_new_method_call(agent->bus_name, agent->path, - "org.openobex.Agent", "Authorize"); + AGENT_INTERFACE, "Authorize"); dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path, @@ -610,8 +616,8 @@ goto done; } - g_dbus_emit_signal(connection, OPENOBEX_MANAGER_PATH, - OPENOBEX_MANAGER_INTERFACE, "SessionCreated", + g_dbus_emit_signal(connection, OBEX_MANAGER_PATH, + OBEX_MANAGER_INTERFACE, "SessionCreated", DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); @@ -623,8 +629,8 @@ { char *path = g_strdup_printf("/session%u", GPOINTER_TO_UINT(os)); - g_dbus_emit_signal(connection, OPENOBEX_MANAGER_PATH, - OPENOBEX_MANAGER_INTERFACE, "SessionRemoved", + g_dbus_emit_signal(connection, OBEX_MANAGER_PATH, + OBEX_MANAGER_INTERFACE, "SessionRemoved", DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID); diff -Nru obexd-0.46/src/manager.h obexd-0.48/src/manager.h --- obexd-0.46/src/manager.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/src/manager.h 2012-07-26 19:09:25.000000000 +0200 @@ -23,7 +23,7 @@ #include -#define OPENOBEX_SERVICE "org.openobex" +#define OBEXD_SERVICE "org.bluez.obex" void manager_register_session(struct obex_session *os); void manager_unregister_session(struct obex_session *os); diff -Nru obexd-0.46/src/map_ap.c obexd-0.48/src/map_ap.c --- obexd-0.46/src/map_ap.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/src/map_ap.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,466 +0,0 @@ -/* - * - * OBEX Server - * - * Copyright (C) 2010-2011 Nokia Corporation - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "log.h" - -#include "map_ap.h" - -enum ap_type { - APT_UINT8, - APT_UINT16, - APT_UINT32, - APT_STR -}; - -/* NOTE: ap_defs array has to be kept in sync with map_ap_tag. */ -static const struct ap_def { - const char *name; - enum ap_type type; -} ap_defs[] = { - { "MAXLISTCOUNT", APT_UINT16 }, - { "STARTOFFSET", APT_UINT16 }, - { "FILTERMESSAGETYPE", APT_UINT8 }, - { "FILTERPERIODBEGIN", APT_STR }, - { "FILTERPERIODEND", APT_STR }, - { "FILTERREADSTATUS", APT_UINT8 }, - { "FILTERRECIPIENT", APT_STR }, - { "FILTERORIGINATOR", APT_STR }, - { "FILTERPRIORITY", APT_UINT8 }, - { "ATTACHMENT", APT_UINT8 }, - { "TRANSPARENT", APT_UINT8 }, - { "RETRY", APT_UINT8 }, - { "NEWMESSAGE", APT_UINT8 }, - { "NOTIFICATIONSTATUS", APT_UINT8 }, - { "MASINSTANCEID", APT_UINT8 }, - { "PARAMETERMASK", APT_UINT32 }, - { "FOLDERLISTINGSIZE", APT_UINT16 }, - { "MESSAGESLISTINGSIZE", APT_UINT16 }, - { "SUBJECTLENGTH", APT_UINT8 }, - { "CHARSET", APT_UINT8 }, - { "FRACTIONREQUEST", APT_UINT8 }, - { "FRACTIONDELIVER", APT_UINT8 }, - { "STATUSINDICATOR", APT_UINT8 }, - { "STATUSVALUE", APT_UINT8 }, - { "MSETIME", APT_STR }, -}; - -struct ap_entry { - enum map_ap_tag tag; - union { - uint32_t u32; - uint16_t u16; - uint8_t u8; - char *str; - } val; -}; - -/* This comes from OBEX specs */ -struct obex_ap_header { - uint8_t tag; - uint8_t len; - uint8_t val[0]; -} __attribute__ ((packed)); - -static int find_ap_def_offset(uint8_t tag) -{ - if (tag == 0 || tag > G_N_ELEMENTS(ap_defs)) - return -1; - - return tag - 1; -} - -static void ap_entry_dump(gpointer tag, gpointer val, gpointer user_data) -{ - struct ap_entry *entry = val; - int offset; - - offset = find_ap_def_offset(GPOINTER_TO_INT(tag)); - - switch (ap_defs[offset].type) { - case APT_UINT8: - DBG("%-30s %08x", ap_defs[offset].name, entry->val.u8); - break; - case APT_UINT16: - DBG("%-30s %08x", ap_defs[offset].name, entry->val.u16); - break; - case APT_UINT32: - DBG("%-30s %08x", ap_defs[offset].name, entry->val.u32); - break; - case APT_STR: - DBG("%-30s %s", ap_defs[offset].name, entry->val.str); - break; - } -} - -static void ap_entry_free(gpointer val) -{ - struct ap_entry *entry = val; - int offset; - - offset = find_ap_def_offset(entry->tag); - - if (offset >= 0 && ap_defs[offset].type == APT_STR) - g_free(entry->val.str); - - g_free(entry); -} - -map_ap_t *map_ap_new(void) -{ - return g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, - ap_entry_free); -} - -void map_ap_free(map_ap_t *ap) -{ - if (!ap) - return; - - g_hash_table_destroy(ap); -} - -static void ap_decode_u8(map_ap_t *ap, const struct obex_ap_header *hdr) -{ - if (hdr->len != 1) { - DBG("Value of tag %u is %u byte(s) long instead of expected " - "1 byte - skipped!", hdr->tag, hdr->len); - return; - } - - map_ap_set_u8(ap, hdr->tag, hdr->val[0]); -} - -static void ap_decode_u16(map_ap_t *ap, const struct obex_ap_header *hdr) -{ - uint16_t val; - - if (hdr->len != 2) { - DBG("Value of tag %u is %u byte(s) long instead of expected " - "2 bytes - skipped!", hdr->tag, hdr->len); - return; - } - - memcpy(&val, hdr->val, sizeof(val)); - map_ap_set_u16(ap, hdr->tag, GUINT16_FROM_BE(val)); -} - -static void ap_decode_u32(map_ap_t *ap, const struct obex_ap_header *hdr) -{ - uint32_t val; - - if (hdr->len != 4) { - DBG("Value of tag %u is %u byte(s) long instead of expected " - "4 bytes - skipped!", hdr->tag, hdr->len); - return; - } - - memcpy(&val, hdr->val, sizeof(val)); - map_ap_set_u32(ap, hdr->tag, GUINT32_FROM_BE(val)); -} - -static void ap_decode_str(map_ap_t *ap, const struct obex_ap_header *hdr) -{ - char *val = g_malloc0(hdr->len + 1); - - memcpy(val, hdr->val, hdr->len); - map_ap_set_string(ap, hdr->tag, val); - - g_free(val); -} - -map_ap_t *map_ap_decode(const uint8_t *buffer, size_t length) -{ - map_ap_t *ap; - struct obex_ap_header *hdr; - uint32_t done; - int offset; - - ap = map_ap_new(); - if (!ap) - return NULL; - - for (done = 0; done < length; done += hdr->len + sizeof(*hdr)) { - hdr = (struct obex_ap_header *)(buffer + done); - - offset = find_ap_def_offset(hdr->tag); - - if (offset < 0) { - DBG("Unknown tag %u (length %u) - skipped.", - hdr->tag, hdr->len); - continue; - } - - switch (ap_defs[offset].type) { - case APT_UINT8: - ap_decode_u8(ap, hdr); - break; - case APT_UINT16: - ap_decode_u16(ap, hdr); - break; - case APT_UINT32: - ap_decode_u32(ap, hdr); - break; - case APT_STR: - ap_decode_str(ap, hdr); - break; - } - } - - g_hash_table_foreach(ap, ap_entry_dump, NULL); - - return ap; -} - -static void ap_encode_u8(GByteArray *buf, struct ap_entry *entry) -{ - struct obex_ap_header *hdr; - - hdr = (struct obex_ap_header *) buf->data + buf->len; - g_byte_array_set_size(buf, buf->len + sizeof(*hdr) + 1); - - hdr->tag = entry->tag; - hdr->len = 1; - hdr->val[0] = entry->val.u8; -} - -static void ap_encode_u16(GByteArray *buf, struct ap_entry *entry) -{ - struct obex_ap_header *hdr; - uint16_t val; - - hdr = (struct obex_ap_header *) buf->data + buf->len; - - g_byte_array_set_size(buf, buf->len + sizeof(*hdr) + 2); - - hdr->tag = entry->tag; - hdr->len = 2; - - val = GUINT16_TO_BE(entry->val.u16); - memcpy(hdr->val, &val, sizeof(val)); -} - -static void ap_encode_u32(GByteArray *buf, struct ap_entry *entry) -{ - uint32_t val; - struct obex_ap_header *hdr; - - hdr = (struct obex_ap_header *) buf->data + buf->len; - g_byte_array_set_size(buf, buf->len + sizeof(*hdr) + 4); - - hdr->tag = entry->tag; - hdr->len = 4; - - val = GUINT32_TO_BE(entry->val.u16); - memcpy(hdr->val, &val, sizeof(val)); -} - -static void ap_encode_str(GByteArray *buf, struct ap_entry *entry) -{ - size_t len; - struct obex_ap_header *hdr; - - hdr = (struct obex_ap_header *) buf->data + buf->len; - len = strlen(entry->val.str); - g_byte_array_set_size(buf, buf->len + sizeof(*hdr) + len); - - hdr->tag = entry->tag; - hdr->len = len; - - memcpy(hdr->val, entry->val.str, len); -} - -uint8_t *map_ap_encode(map_ap_t *ap, size_t *length) -{ - GByteArray *buf; - GHashTableIter iter; - gpointer key, value; - struct ap_entry *entry; - int offset; - - buf = g_byte_array_new(); - g_hash_table_iter_init(&iter, ap); - - while (g_hash_table_iter_next(&iter, &key, &value)) { - entry = (struct ap_entry *) value; - offset = find_ap_def_offset(entry->tag); - - switch (ap_defs[offset].type) { - case APT_UINT8: - ap_encode_u8(buf, entry); - break; - case APT_UINT16: - ap_encode_u16(buf, entry); - break; - case APT_UINT32: - ap_encode_u32(buf, entry); - break; - case APT_STR: - ap_encode_str(buf, entry); - break; - } - } - - *length = buf->len; - - return g_byte_array_free(buf, FALSE); -} - -gboolean map_ap_get_u8(map_ap_t *ap, enum map_ap_tag tag, uint8_t *val) -{ - struct ap_entry *entry; - int offset = find_ap_def_offset(tag); - - if (offset < 0 || ap_defs[offset].type != APT_UINT8) - return FALSE; - - entry = g_hash_table_lookup(ap, GINT_TO_POINTER(tag)); - if (entry == NULL) - return FALSE; - - *val = entry->val.u8; - - return TRUE; -} - -gboolean map_ap_get_u16(map_ap_t *ap, enum map_ap_tag tag, uint16_t *val) -{ - struct ap_entry *entry; - int offset = find_ap_def_offset(tag); - - if (offset < 0 || ap_defs[offset].type != APT_UINT16) - return FALSE; - - entry = g_hash_table_lookup(ap, GINT_TO_POINTER(tag)); - if (entry == NULL) - return FALSE; - - *val = entry->val.u16; - - return TRUE; -} - -gboolean map_ap_get_u32(map_ap_t *ap, enum map_ap_tag tag, uint32_t *val) -{ - struct ap_entry *entry; - int offset = find_ap_def_offset(tag); - - if (offset < 0 || ap_defs[offset].type != APT_UINT32) - return FALSE; - - entry = g_hash_table_lookup(ap, GINT_TO_POINTER(tag)); - if (entry == NULL) - return FALSE; - - *val = entry->val.u32; - - return TRUE; -} - -const char *map_ap_get_string(map_ap_t *ap, enum map_ap_tag tag) -{ - struct ap_entry *entry; - int offset = find_ap_def_offset(tag); - - if (offset < 0 || ap_defs[offset].type != APT_STR) - return NULL; - - entry = g_hash_table_lookup(ap, GINT_TO_POINTER(tag)); - if (entry == NULL) - return NULL; - - return entry->val.str; -} - -gboolean map_ap_set_u8(map_ap_t *ap, enum map_ap_tag tag, uint8_t val) -{ - struct ap_entry *entry; - int offset = find_ap_def_offset(tag); - - if (offset < 0 || ap_defs[offset].type != APT_UINT8) - return FALSE; - - entry = g_new0(struct ap_entry, 1); - entry->tag = tag; - entry->val.u8 = val; - - g_hash_table_insert(ap, GINT_TO_POINTER(tag), entry); - - return TRUE; -} - -gboolean map_ap_set_u16(map_ap_t *ap, enum map_ap_tag tag, uint16_t val) -{ - struct ap_entry *entry; - int offset = find_ap_def_offset(tag); - - if (offset < 0 || ap_defs[offset].type != APT_UINT16) - return FALSE; - - entry = g_new0(struct ap_entry, 1); - entry->tag = tag; - entry->val.u16 = val; - - g_hash_table_insert(ap, GINT_TO_POINTER(tag), entry); - - return TRUE; -} - -gboolean map_ap_set_u32(map_ap_t *ap, enum map_ap_tag tag, uint32_t val) -{ - struct ap_entry *entry; - int offset = find_ap_def_offset(tag); - - if (offset < 0 || ap_defs[offset].type != APT_UINT32) - return FALSE; - - entry = g_new0(struct ap_entry, 1); - entry->tag = tag; - entry->val.u32 = val; - - g_hash_table_insert(ap, GINT_TO_POINTER(tag), entry); - - return TRUE; -} - -gboolean map_ap_set_string(map_ap_t *ap, enum map_ap_tag tag, const char *val) -{ - struct ap_entry *entry; - int offset = find_ap_def_offset(tag); - - if (offset < 0 || ap_defs[offset].type != APT_STR) - return FALSE; - - entry = g_new0(struct ap_entry, 1); - entry->tag = tag; - entry->val.str = g_strdup(val); - - g_hash_table_insert(ap, GINT_TO_POINTER(tag), entry); - - return TRUE; -} diff -Nru obexd-0.46/src/map_ap.h obexd-0.48/src/map_ap.h --- obexd-0.46/src/map_ap.h 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/src/map_ap.h 2012-11-30 08:59:13.000000000 +0100 @@ -21,9 +21,6 @@ * */ -#include -#include - /* List of OBEX application parameters tags as per MAP specification. */ enum map_ap_tag { MAP_AP_MAXLISTCOUNT = 0x01, /* uint16_t */ @@ -52,63 +49,3 @@ MAP_AP_STATUSVALUE = 0x18, /* uint8_t */ MAP_AP_MSETIME = 0x19, /* char * */ }; - -/* Data type representing MAP application parameters. Consider opaque. */ -typedef GHashTable map_ap_t; - -/* Creates a new empty MAP application parameters object. */ -map_ap_t *map_ap_new(void); - -/* Frees all the memory used by MAP application parameters object. */ -void map_ap_free(map_ap_t *ap); - -/* Parses given buffer that is a payload of OBEX application parameter header - * with a given length. Returned value can be used in calls to map_ap_get_*() - * and map_ap_set_*(). It has to be freed using map_ap_free(). It also takes - * care of converting all the data to host byte order, so this is the byte - * order used in map_ap_get_*()/map_ap_set_*(). - * - * Returns NULL in case of failure. - */ -map_ap_t *map_ap_decode(const uint8_t *buffer, size_t length); - -/* Takes all parameters currently set and packs them into a buffer with OBEX - * application parameters header payload format. - * - * Returns newly allocated buffer of size 'length'. Free with g_free(). - */ -uint8_t *map_ap_encode(map_ap_t *ap, size_t *length); - -/* Following family of functions reads value of MAP parameter with given tag. - * Use the one with appropriate type for a given tag, as noted above in - * map_ap_tag declaration comments. - * - * Returns TRUE when value is present. FALSE if it is not or the function is - * used get a parameter of a different type. When FALSE is returned, variable - * pointed by 'val' is left intact. - */ -gboolean map_ap_get_u8(map_ap_t *ap, enum map_ap_tag tag, uint8_t *val); -gboolean map_ap_get_u16(map_ap_t *ap, enum map_ap_tag tag, uint16_t *val); -gboolean map_ap_get_u32(map_ap_t *ap, enum map_ap_tag tag, uint32_t *val); - -/* Reads value of MAP parameter with given tag that is of a string type. - * - * Returns NULL if parameter is not present in ap or given tag is not of a - * string type. - */ -const char *map_ap_get_string(map_ap_t *ap, enum map_ap_tag tag); - -/* Following family of functions sets the value of MAP parameter with given - * tag. Use the one with appropriate type for a given tag, as noted above in - * map_ap_tag declaration comments. - * - * If there is already a parameter with given tag present, it will be - * replaced. map_ap_set_string() makes its own copy of given string. - * - * Returns TRUE on success (the tag is known and the function chosen matches - * the type of tag). - */ -gboolean map_ap_set_u8(map_ap_t *ap, enum map_ap_tag tag, uint8_t val); -gboolean map_ap_set_u16(map_ap_t *ap, enum map_ap_tag tag, uint16_t val); -gboolean map_ap_set_u32(map_ap_t *ap, enum map_ap_tag tag, uint32_t val); -gboolean map_ap_set_string(map_ap_t *ap, enum map_ap_tag tag, const char *val); diff -Nru obexd-0.46/src/obex.c obexd-0.48/src/obex.c --- obexd-0.46/src/obex.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/src/obex.c 2012-07-26 19:09:25.000000000 +0200 @@ -656,7 +656,7 @@ if (os->aborted) return FALSE; - /* workaround: client didn't send the object lenght */ + /* workaround: client didn't send the object length */ if (os->size == OBJECT_SIZE_DELETE) os->size = OBJECT_SIZE_UNKNOWN; diff -Nru obexd-0.46/src/obexd.service.in obexd-0.48/src/obexd.service.in --- obexd-0.46/src/obexd.service.in 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/src/obexd.service.in 2012-07-26 19:09:25.000000000 +0200 @@ -1,3 +1,3 @@ [D-BUS Service] -Name=org.openobex +Name=org.bluez.obex Exec=@libexecdir@/obexd --nodaemon diff -Nru obexd-0.46/src/server.c obexd-0.48/src/server.c --- obexd-0.46/src/server.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/src/server.c 2012-11-30 08:59:13.000000000 +0100 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff -Nru obexd-0.46/test/exchange-business-cards obexd-0.48/test/exchange-business-cards --- obexd-0.46/test/exchange-business-cards 2009-05-02 17:52:30.000000000 +0200 +++ obexd-0.48/test/exchange-business-cards 2012-07-26 19:09:25.000000000 +0200 @@ -4,12 +4,16 @@ import dbus bus = dbus.SessionBus() -client = dbus.Interface(bus.get_object("org.openobex.client", "/"), - "org.openobex.Client") +client = dbus.Interface(bus.get_object("org.bluez.obex.client", "/"), + "org.bluez.obex.Client") if (len(sys.argv) < 4): print "Usage: %s " % (sys.argv[0]) sys.exit(1) -client.ExchangeBusinessCards({ "Destination": sys.argv[1] }, - sys.argv[2], sys.argv[3]) +print "Creating Session" +path = client.CreateSession(sys.argv[1], { "Target": "OPP" }) +opp = dbus.Interface(bus.get_object("org.bluez.obex.client", path), + "org.bluez.obex.ObjectPush") + +opp.ExchangeBusinessCards(sys.argv[2], sys.argv[3]) diff -Nru obexd-0.46/test/ftp-client obexd-0.48/test/ftp-client --- obexd-0.46/test/ftp-client 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/test/ftp-client 2012-07-26 19:09:25.000000000 +0200 @@ -9,162 +9,175 @@ import os.path from optparse import OptionParser -class Agent(dbus.service.Object): - def __init__(self, conn=None, obj_path=None, verbose=False): - dbus.service.Object.__init__(self, conn, obj_path) - self.verbose = verbose - - @dbus.service.method("org.openobex.Agent", - in_signature="o", out_signature="s") - def Request(self, path): - return "" - - @dbus.service.method("org.openobex.Agent", - in_signature="ot", out_signature="") - def Progress(self, path, transferred): - if self.verbose: - print "Transfer progress (%d bytes)" % (transferred) - return - - @dbus.service.method("org.openobex.Agent", - in_signature="o", out_signature="") - def Complete(self, path): - if self.verbose: - print "Transfer finished" - mainloop.quit() - - @dbus.service.method("org.openobex.Agent", - in_signature="os", out_signature="") - def Error(self, path, error): - print "Transfer finished with an error: %s" % (error) - mainloop.quit() - - @dbus.service.method("org.openobex.Agent", - in_signature="", out_signature="") - def Release(self): - mainloop.quit() - - def parse_options(): - parser.add_option("-d", "--device", dest="device", - help="Device to connect", metavar="DEVICE") - parser.add_option("-c", "--chdir", dest="new_dir", - help="Change current directory to DIR", metavar="DIR") - parser.add_option("-l", "--list", action="store_true", dest="list_dir", - help="List the current directory") - parser.add_option("-g", "--get", dest="get_file", - help="Get FILE", metavar="FILE") - parser.add_option("-p", "--put", dest="put_file", - help="Put FILE", metavar="FILE") - parser.add_option("-y", "--copy", dest="copy_file", - help="Copy FILE", metavar="FILE") - parser.add_option("-m", "--move", dest="move_file", - help="Move FILE", metavar="FILE") - parser.add_option("-n", "--destname", dest="dest_file", - help="Destination FILE", metavar="FILE") - parser.add_option("-r", "--remove", dest="remove_file", - help="Remove FILE", metavar="FILE") - parser.add_option("-v", "--verbose", action="store_true", dest="verbose") - - return parser.parse_args() - -def error(err): - print err - -def void_reply(): - pass - -def change_folder(session, new_dir): - for node in new_dir.split("/"): - session.ChangeFolder(node) - -def list_folder(session): - for i in session.ListFolder(): - if i["Type"] == "folder": - print "%s/" % (i["Name"]) - else: - print "%s" % (i["Name"]) - -def put_file(session, filename): - session.PutFile(os.path.abspath(filename), - os.path.basename(filename), - reply_handler=void_reply, - error_handler=error) - -def get_file(session, filename): - session.GetFile(os.path.abspath(filename), - os.path.basename(filename), - reply_handler=void_reply, - error_handler=error) - -def remove_file(session, filename): - session.Delete(filename, - reply_handler=void_reply, - error_handler=error) - -def move_file(session, filename, destname): - session.MoveFile(filename, - destname, - reply_handler=void_reply, - error_handler=error) - -def copy_file(session, filename, destname): - session.CopyFile(filename, - destname, - reply_handler=void_reply, - error_handler=error) + parser.add_option("-d", "--device", dest="device", + help="Device to connect", metavar="DEVICE") + parser.add_option("-c", "--chdir", dest="new_dir", + help="Change current directory to DIR", metavar="DIR") + parser.add_option("-l", "--list", action="store_true", dest="list_dir", + help="List the current directory") + parser.add_option("-g", "--get", dest="get_file", + help="Get FILE", metavar="FILE") + parser.add_option("-p", "--put", dest="put_file", + help="Put FILE", metavar="FILE") + parser.add_option("-y", "--copy", dest="copy_file", + help="Copy FILE", metavar="FILE") + parser.add_option("-m", "--move", dest="move_file", + help="Move FILE", metavar="FILE") + parser.add_option("-n", "--destname", dest="dest_file", + help="Destination FILE", metavar="FILE") + parser.add_option("-r", "--remove", dest="remove_file", + help="Remove FILE", metavar="FILE") + parser.add_option("-v", "--verbose", action="store_true", + dest="verbose") + + return parser.parse_args() + +class FtpClient: + def __init__(self, session_path, verbose=False): + self.progress = 0 + self.transfer_path = None + self.transfer_size = 0 + self.verbose = verbose + bus = dbus.SessionBus() + obj = bus.get_object("org.bluez.obex.client", session_path) + self.session = dbus.Interface(obj, "org.bluez.obex.Session") + self.ftp = dbus.Interface(obj, "org.bluez.obex.FileTransfer") + bus.add_signal_receiver(self.transfer_complete, + dbus_interface="org.bluez.obex.Transfer", + signal_name="Complete", + path_keyword="path") + bus.add_signal_receiver(self.transfer_error, + dbus_interface="org.bluez.obex.Transfer", + signal_name="Error", + path_keyword="path") + if self.verbose: + bus.add_signal_receiver(self.transfer_progress, + dbus_interface="org.bluez.obex.Transfer", + signal_name="PropertyChanged", + path_keyword="path") + + def create_transfer_reply(self, reply): + (path, properties) = reply + self.transfer_path = path + self.transfer_size = properties["Size"] + if self.verbose: + print "Transfer created: %s" % path + + def generic_reply(self): + if self.verbose: + print "Operation succeeded" + + def error(self, err): + print err + mainloop.quit() + + def transfer_complete(self, path): + if path != self.transfer_path: + return + if self.verbose: + print "Transfer finished" + mainloop.quit() + + def transfer_error(self, code, message, path): + if path != self.transfer_path: + return + print "Transfer finished with error %s: %s" % (code, message) + mainloop.quit() + + def transfer_progress(self, prop, value, path): + if path != self.transfer_path: + return + + if prop != "Progress": + return + + speed = (value - self.progress) / 1000 + print "Transfer progress %d/%d at %d kBps" % (value, + self.transfer_size, + speed) + self.progress = value + + def change_folder(self, new_dir): + for node in new_dir.split("/"): + self.ftp.ChangeFolder(node) + + def list_folder(self): + for i in self.ftp.ListFolder(): + if i["Type"] == "folder": + print "%s/" % (i["Name"]) + else: + print "%s" % (i["Name"]) + + def put_file(self, filename): + self.ftp.PutFile(os.path.abspath(filename), + os.path.basename(filename), + reply_handler=self.create_transfer_reply, + error_handler=self.error) + + def get_file(self, filename): + self.ftp.GetFile(os.path.abspath(filename), + os.path.basename(filename), + reply_handler=self.create_transfer_reply, + error_handler=self.error) + + def remove_file(self, filename): + self.ftp.Delete(filename, + reply_handler=self.generic_reply, + error_handler=self.error) + + def move_file(self, filename, destname): + self.ftp.MoveFile(filename, destname, + reply_handler=self.generic_reply, + error_handler=self.error) + + def copy_file(self, filename, destname): + self.ftp.CopyFile(filename, destname, + reply_handler=self.generic_reply, + error_handler=self.error) if __name__ == '__main__': - dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) - - parser = OptionParser() - - (options, args) = parse_options() - - if not options.device: - parser.print_help() - sys.exit(0) + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) - bus = dbus.SessionBus() - mainloop = gobject.MainLoop() + parser = OptionParser() - path = "/test/agent" - agent = Agent(bus, path, options.verbose) + (options, args) = parse_options() - client = dbus.Interface(bus.get_object("org.openobex.client", "/"), - "org.openobex.Client") + if not options.device: + parser.print_help() + sys.exit(0) - session_path = client.CreateSession({ "Destination": options.device, - "Target": "ftp"}) + bus = dbus.SessionBus() + mainloop = gobject.MainLoop() - session = dbus.Interface(bus.get_object("org.openobex.client", session_path), - "org.openobex.Session") + client = dbus.Interface(bus.get_object("org.bluez.obex.client", "/"), + "org.bluez.obex.Client") - session.AssignAgent(path) + print "Creating Session" + path = client.CreateSession(options.device, { "Target": "ftp" }) - ftp = dbus.Interface(bus.get_object("org.openobex.client", session_path), - "org.openobex.FileTransfer") + ftp_client = FtpClient(path, options.verbose) - if options.new_dir: - change_folder(ftp, options.new_dir) + if options.new_dir: + ftp_client.change_folder(options.new_dir) - if options.list_dir: - list_folder(ftp) + if options.list_dir: + ftp_client.list_folder() - if options.get_file: - get_file(ftp, options.get_file) + if options.get_file: + ftp_client.get_file(options.get_file) - if options.put_file: - put_file(ftp, options.put_file) + if options.put_file: + ftp_client.put_file(options.put_file) - if options.move_file: - move_file(ftp, options.move_file, options.dest_file) + if options.move_file: + ftp_client.move_file(options.move_file, options.dest_file) - if options.copy_file: - copy_file(ftp, options.copy_file, options.dest_file) + if options.copy_file: + ftp_client.copy_file(options.copy_file, options.dest_file) - if options.remove_file: - remove_file(ftp, options.remove_file) + if options.remove_file: + ftp_client.remove_file(options.remove_file) - mainloop.run() + mainloop.run() diff -Nru obexd-0.46/test/list-folders obexd-0.48/test/list-folders --- obexd-0.46/test/list-folders 2010-04-23 17:52:33.000000000 +0200 +++ obexd-0.48/test/list-folders 2012-07-26 19:09:25.000000000 +0200 @@ -6,13 +6,13 @@ def list_folder(folder): bus = dbus.SessionBus() - client = dbus.Interface(bus.get_object("org.openobex.client", "/"), - "org.openobex.Client") + client = dbus.Interface(bus.get_object("org.bluez.obex.client", "/"), + "org.bluez.obex.Client") - session_path = client.CreateSession({ "Destination": sys.argv[1], "Target": "ftp"}) + path = client.CreateSession(sys.argv[1], { "Target": "ftp" }) - ftp = dbus.Interface(bus.get_object("org.openobex.client", session_path), - "org.openobex.FileTransfer") + ftp = dbus.Interface(bus.get_object("org.bluez.obex.client", path), + "org.bluez.obex.FileTransfer") if folder: for node in folder.split("/"): diff -Nru obexd-0.46/test/map-client obexd-0.48/test/map-client --- obexd-0.46/test/map-client 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/test/map-client 2012-11-30 08:59:13.000000000 +0100 @@ -2,61 +2,206 @@ import gobject +import sys +import os import dbus import dbus.mainloop.glib from optparse import OptionParser +from pprint import pformat + +def unwrap(x): + """Hack to unwrap D-Bus values, so that they're easier to read when + printed. Taken from d-feet """ + + if isinstance(x, list): + return map(unwrap, x) + + if isinstance(x, tuple): + return tuple(map(unwrap, x)) + + if isinstance(x, dict): + return dict([(unwrap(k), unwrap(v)) for k, v in x.iteritems()]) + + for t in [unicode, str, long, int, float, bool]: + if isinstance(x, t): + return t(x) + + return x + def parse_options(): - parser.add_option("-d", "--device", dest="device", - help="Device to connect", metavar="DEVICE") - parser.add_option("-c", "--chdir", dest="new_dir", - help="Change current directory to DIR", metavar="DIR") - parser.add_option("-l", "--lsdir", action="store_true", dest="ls_dir", - help="List folders in current directory") - parser.add_option("-v", "--verbose", action="store_true", dest="verbose") - parser.add_option("-L", "--lsmsg", action="store", dest="ls_msg", - help="List messages in supplied CWD subdir") + parser.add_option("-d", "--device", dest="device", + help="Device to connect", metavar="DEVICE") + parser.add_option("-c", "--chdir", dest="new_dir", + help="Change current directory to DIR", metavar="DIR") + parser.add_option("-l", "--lsdir", action="store_true", dest="ls_dir", + help="List folders in current directory") + parser.add_option("-v", "--verbose", action="store_true", dest="verbose") + parser.add_option("-L", "--lsmsg", action="store", dest="ls_msg", + help="List messages in supplied CWD subdir") + parser.add_option("-g", "--get", action="store", dest="get_msg", + help="Get message contents") + parser.add_option("--get-properties", action="store", dest="get_msg_properties", + help="Get message properties") + parser.add_option("--mark-read", action="store", dest="mark_msg_read", + help="Marks the messages as read") + parser.add_option("--mark-unread", action="store", dest="mark_msg_unread", + help="Marks the messages as unread") + parser.add_option("--mark-deleted", action="store", dest="mark_msg_deleted", + help="Deletes the message from the folder") + parser.add_option("--mark-undeleted", action="store", dest="mark_msg_undeleted", + help="Undeletes the message") + parser.add_option("-u", "--update-inbox", action="store_true", dest="update_inbox", + help="Checks for new mails") - return parser.parse_args() + return parser.parse_args() def set_folder(session, new_dir): - for node in new_dir.split("/"): - session.SetFolder(node) + session.SetFolder(new_dir) + +class MapClient: + def __init__(self, session_path, verbose=False): + self.progress = 0 + self.transfer_path = None + self.props = dict() + self.verbose = verbose + self.path = session_path + bus = dbus.SessionBus() + obj = bus.get_object("org.bluez.obex.client", session_path) + self.session = dbus.Interface(obj, "org.bluez.obex.Session") + self.map = dbus.Interface(obj, "org.bluez.obex.MessageAccess") + bus.add_signal_receiver(self.transfer_complete, + dbus_interface="org.bluez.obex.Transfer", + signal_name="Complete", + path_keyword="path") + bus.add_signal_receiver(self.transfer_error, + dbus_interface="org.bluez.obex.Transfer", + signal_name="Error", + path_keyword="path") + + def create_transfer_reply(self, reply): + (path, properties) = reply + self.transfer_path = path + self.props[path] = properties + if self.verbose: + print "Transfer created: %s (file %s)" % (path, + properties["Filename"]) + + def generic_reply(self): + if self.verbose: + print "Operation succeeded" + + def error(self, err): + print err + mainloop.quit() + + def transfer_complete(self, path): + if path != self.transfer_path: + return + if self.verbose: + print "Transfer finished" + properties = self.props.get(path) + if properties == None: + return + f = open(properties["Filename"], "r") + os.remove(properties["Filename"]) + print f.readlines() + + def transfer_error(self, code, message, path): + if path != self.transfer_path: + return + print "Transfer finished with error %s: %s" % (code, message) + mainloop.quit() + + def set_folder(self, new_dir): + self.map.SetFolder(new_dir) + + def list_folders(self): + for i in self.map.ListFolders(dict()): + print "%s/" % (i["Name"]) + + def list_messages(self, folder): + ret = self.map.ListMessages(folder, dict()) + print pformat(unwrap(ret)) + + def get_message(self, handle): + self.map.ListMessages("", dict()) + path = self.path + "/message" + handle + obj = bus.get_object("org.bluez.obex.client", path) + msg = dbus.Interface(obj, "org.bluez.obex.Message") + msg.Get("", True, reply_handler=self.create_transfer_reply, + error_handler=self.error) + + def get_message_properties(self, handle): + self.map.ListMessages("", dict()) + path = self.path + "/message" + handle + obj = bus.get_object("org.bluez.obex.client", path) + msg = dbus.Interface(obj, "org.bluez.obex.Message") + ret = msg.GetProperties() + print pformat(unwrap(ret)) + + def set_message_property(self, handle, prop, flag): + self.map.ListMessages("", dict()) + path = self.path + "/message" + handle + obj = bus.get_object("org.bluez.obex.client", path) + msg = dbus.Interface(obj, "org.bluez.obex.Message") + msg.SetProperty (prop, flag); + + def update_inbox(self): + self.map.UpdateInbox() + if __name__ == '__main__': - dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + parser = OptionParser() + + (options, args) = parse_options() + + if not options.device: + parser.print_help() + exit(0) + + bus = dbus.SessionBus() + mainloop = gobject.MainLoop() + + client = dbus.Interface(bus.get_object("org.bluez.obex.client", "/"), + "org.bluez.obex.Client") + + print "Creating Session" + path = client.CreateSession(options.device, { "Target": "map" }) - parser = OptionParser() + map_client = MapClient(path, options.verbose) - (options, args) = parse_options() + if options.new_dir: + map_client.set_folder(options.new_dir) - if not options.device: - parser.print_help() - exit(0) + if options.ls_dir: + map_client.list_folders() - bus = dbus.SessionBus() - mainloop = gobject.MainLoop() + if options.ls_msg is not None: + map_client.list_messages(options.ls_msg) - client = dbus.Interface(bus.get_object("org.openobex.client", "/"), - "org.openobex.Client") + if options.get_msg is not None: + map_client.get_message(options.get_msg) - session_path = client.CreateSession({ "Destination": options.device, - "Target": "map"}) + if options.get_msg_properties is not None: + map_client.get_message_properties(options.get_msg_properties) - session = dbus.Interface(bus.get_object("org.openobex.client", session_path), - "org.openobex.Session") + if options.mark_msg_read is not None: + map_client.set_message_property(options.mark_msg_read, "Read", True) - map = dbus.Interface(bus.get_object("org.openobex.client", session_path), - "org.openobex.MessageAccess") + if options.mark_msg_unread is not None: + map_client.set_message_property(options.mark_msg_unread, "Read", False) - if options.new_dir: - set_folder(map, options.new_dir) + if options.mark_msg_deleted is not None: + map_client.set_message_property(options.mark_msg_deleted, "Deleted", True) - if options.ls_dir: - print map.GetFolderListing(dict()) + if options.mark_msg_undeleted is not None: + map_client.set_message_property(options.mark_msg_undeleted, "Deleted", False) - if options.ls_msg is not None: - print map.GetMessageListing(options.ls_msg, dict()) + if options.update_inbox: + map_client.update_inbox() - mainloop.run() + mainloop.run() diff -Nru obexd-0.46/test/opp-client obexd-0.48/test/opp-client --- obexd-0.46/test/opp-client 1970-01-01 01:00:00.000000000 +0100 +++ obexd-0.48/test/opp-client 2012-07-26 19:09:25.000000000 +0200 @@ -0,0 +1,121 @@ +#!/usr/bin/python + +import sys +import dbus +import gobject +import dbus.mainloop.glib +import os.path +from optparse import OptionParser + +def parse_options(): + parser.add_option("-d", "--device", dest="device", + help="Device to connect", metavar="DEVICE") + parser.add_option("-p", "--pull", dest="pull_to_file", + help="Pull vcard and store in FILE", metavar="FILE") + parser.add_option("-s", "--send", dest="send_file", + help="Send FILE", metavar="FILE") + parser.add_option("-v", "--verbose", action="store_true", + dest="verbose") + + return parser.parse_args() + +class OppClient: + def __init__(self, session_path, verbose=False): + self.progress = 0 + self.transfer_path = None + self.verbose = verbose + bus = dbus.SessionBus() + obj = bus.get_object("org.bluez.obex.client", session_path) + self.session = dbus.Interface(obj, "org.bluez.obex.Session") + self.opp = dbus.Interface(obj, "org.bluez.obex.ObjectPush") + bus.add_signal_receiver(self.transfer_complete, + dbus_interface="org.bluez.obex.Transfer", + signal_name="Complete", + path_keyword="path") + bus.add_signal_receiver(self.transfer_error, + dbus_interface="org.bluez.obex.Transfer", + signal_name="Error", + path_keyword="path") + if self.verbose: + bus.add_signal_receiver(self.transfer_progress, + dbus_interface="org.bluez.obex.Transfer", + signal_name="PropertyChanged", + path_keyword="path") + + def create_transfer_reply(self, reply): + (path, properties) = reply + self.transfer_path = path + self.transfer_size = properties["Size"] + if self.verbose: + print "Transfer created: %s" % path + + def error(self, err): + print err + mainloop.quit() + + def transfer_complete(self, path): + if path != self.transfer_path: + return + if self.verbose: + print "Transfer finished" + mainloop.quit() + + def transfer_error(self, code, message, path): + if path != self.transfer_path: + return + print "Transfer finished with error %s: %s" % (code, message) + mainloop.quit() + + def transfer_progress(self, prop, value, path): + if path != self.transfer_path: + return + + if prop != "Progress": + return + + speed = (value - self.progress) / 1000 + print "Transfer progress %d/%d at %d kBps" % (value, + self.transfer_size, + speed) + self.progress = value + + def pull_business_card(self, filename): + self.opp.PullBusinessCard(os.path.abspath(filename), + reply_handler=self.create_transfer_reply, + error_handler=self.error) + + def send_file(self, filename): + self.opp.SendFile(os.path.abspath(filename), + reply_handler=self.create_transfer_reply, + error_handler=self.error) + +if __name__ == '__main__': + + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + parser = OptionParser() + + (options, args) = parse_options() + + if not options.device: + parser.print_help() + sys.exit(0) + + bus = dbus.SessionBus() + mainloop = gobject.MainLoop() + + client = dbus.Interface(bus.get_object("org.bluez.obex.client", "/"), + "org.bluez.obex.Client") + + print "Creating Session" + path = client.CreateSession(options.device, { "Target": "OPP" }) + + opp_client = OppClient(path, options.verbose) + + if options.pull_to_file: + opp_client.pull_business_card(options.pull_to_file) + + if options.send_file: + opp_client.send_file(options.send_file) + + mainloop.run() diff -Nru obexd-0.46/test/pbap-client obexd-0.48/test/pbap-client --- obexd-0.46/test/pbap-client 2010-12-18 18:42:11.000000000 +0100 +++ obexd-0.48/test/pbap-client 2012-11-30 08:59:13.000000000 +0100 @@ -1,41 +1,157 @@ #!/usr/bin/python +import gobject + import sys +import os import dbus +import dbus.service +import dbus.mainloop.glib + +class Transfer: + def __init__(self, callback_func): + self.callback_func = callback_func + self.path = None + self.filename = None + +class PbapClient: + def __init__(self, session_path): + self.transfers = 0 + self.props = dict() + self.flush_func = None + bus = dbus.SessionBus() + obj = bus.get_object("org.bluez.obex.client", session_path) + self.session = dbus.Interface(obj, "org.bluez.obex.Session") + self.pbap = dbus.Interface(obj, + "org.bluez.obex.PhonebookAccess") + bus.add_signal_receiver(self.transfer_complete, + dbus_interface="org.bluez.obex.Transfer", + signal_name="Complete", + path_keyword="path") + bus.add_signal_receiver(self.transfer_error, + dbus_interface="org.bluez.obex.Transfer", + signal_name="Error", + path_keyword="path") + + def register(self, reply, transfer): + (path, properties) = reply + transfer.path = path + transfer.filename = properties["Filename"] + self.props[path] = transfer + print "Transfer created: %s (file %s)" % (path, + transfer.filename) + + def error(self, err): + print err + mainloop.quit() + + def transfer_complete(self, path): + req = self.props.get(path) + if req == None: + return + self.transfers -= 1 + print "Transfer %s finished" % path + f = open(req.filename, "r") + os.remove(req.filename) + lines = f.readlines() + del self.props[path] + req.callback_func(lines) + + if (len(self.props) == 0) and (self.transfers == 0): + if self.flush_func != None: + f = self.flush_func + self.flush_func = None + f() + + def transfer_error(self, code, message, path): + req = self.props.get(path) + if req == None: + return + print "Transfer finished with error %s: %s" % (code, message) + mainloop.quit() + + def pull(self, vcard, params, func): + req = Transfer(func) + self.pbap.Pull(vcard, "", params, + reply_handler=lambda r: self.register(r, req), + error_handler=self.error) + self.transfers += 1 + + def pull_all(self, params, func): + req = Transfer(func) + self.pbap.PullAll("", params, + reply_handler=lambda r: self.register(r, req), + error_handler=self.error) + self.transfers += 1 + + def flush_transfers(self, func): + if (len(self.props) == 0) and (self.transfers == 0): + return + self.flush_func = func + + def interface(self): + return self.pbap + +if __name__ == '__main__': + + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + bus = dbus.SessionBus() + mainloop = gobject.MainLoop() + + client = dbus.Interface(bus.get_object("org.bluez.obex.client", "/"), + "org.bluez.obex.Client") + + if (len(sys.argv) < 2): + print "Usage: %s " % (sys.argv[0]) + sys.exit(1) + + print "Creating Session" + session_path = client.CreateSession(sys.argv[1], { "Target": "PBAP" }) + + pbap_client = PbapClient(session_path) + + def process_result(lines, header): + if header != None: + print header + for line in lines: + print line, + print + + def test_paths(paths): + if len(paths) == 0: + print + print "FINISHED" + mainloop.quit() + return + + path = paths[0] + + print "\n--- Select Phonebook %s ---\n" % (path) + pbap_client.interface().Select("int", path) + + print "\n--- GetSize ---\n" + ret = pbap_client.interface().GetSize() + print "Size = %d\n" % (ret) + + print "\n--- List vCard ---\n" + try: + ret = pbap_client.interface().List(dbus.Dictionary()) + except: + ret = [] + + params = dbus.Dictionary({ "Format" : "vcard30", + "Fields" : [ "VERSION", "FN", "TEL"] }) + for item in ret: + print "%s : %s" % (item[0], item[1]) + pbap_client.pull(item[0], params, + lambda x: process_result(x, None)) + + pbap_client.pull_all(params, lambda x: process_result(x, + "\n--- PullAll ---\n")) -bus = dbus.SessionBus() + pbap_client.flush_transfers(lambda: test_paths(paths[1:])) -client = dbus.Interface(bus.get_object("org.openobex.client", "/"), - "org.openobex.Client") + test_paths(["PB", "ICH", "OCH", "MCH", "CCH"]) -print "Creating Session" -session_path = client.CreateSession({"Destination": sys.argv[1], "Target": "PBAP"}) -pbap = dbus.Interface(bus.get_object("org.openobex.client", session_path), - "org.openobex.PhonebookAccess") -session = dbus.Interface(bus.get_object("org.openobex.client", session_path), - "org.openobex.Session") - -paths = ["PB", "ICH", "OCH", "MCH", "CCH"] - -for path in paths: - print "\n--- Select Phonebook %s ---\n" % (path) - pbap.Select("int", path) - - print "\n--- GetSize ---\n" - ret = pbap.GetSize() - print "Size = %d\n" % (ret) - - print "\n--- List vCard ---\n" - ret = pbap.List() - for item in ret: - print "%s : %s" % (item[0], item[1]) - pbap.SetFormat("vcard30") - pbap.SetFilter(["VERSION", "FN", "TEL"]); - ret = pbap.Pull(item[0]) - print "%s" % (ret) - - print "\n--- PullAll ---\n" - pbap.SetFormat("vcard30") - pbap.SetFilter(["VERSION", "FN", "TEL"]); - ret = pbap.PullAll() - print "%s" % (ret) + mainloop.run() diff -Nru obexd-0.46/test/pull-business-card obexd-0.48/test/pull-business-card --- obexd-0.46/test/pull-business-card 2010-05-23 14:34:01.000000000 +0200 +++ obexd-0.48/test/pull-business-card 1970-01-01 01:00:00.000000000 +0100 @@ -1,34 +0,0 @@ -#!/usr/bin/python - -import sys -import dbus -import gobject -import dbus.mainloop.glib - -def success(): - mainloop.quit() - return - -def failure(error): - print error - mainloop.quit() - return - - -if __name__ == '__main__': - dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) - - mainloop = gobject.MainLoop() - - bus = dbus.SessionBus() - client = dbus.Interface(bus.get_object("org.openobex.client", "/"), - "org.openobex.Client") - - if (len(sys.argv) < 3): - print "Usage: %s " % (sys.argv[0]) - sys.exit(1) - - client.PullBusinessCard({ "Destination": sys.argv[1] }, sys.argv[2], - reply_handler=success, error_handler=failure) - - mainloop.run() diff -Nru obexd-0.46/test/send-files obexd-0.48/test/send-files --- obexd-0.46/test/send-files 2010-04-23 17:52:33.000000000 +0200 +++ obexd-0.48/test/send-files 1970-01-01 01:00:00.000000000 +0100 @@ -1,82 +0,0 @@ -#!/usr/bin/python - -import gobject - -import os -import sys -import time -import dbus -import dbus.service -import dbus.mainloop.glib - -class Agent(dbus.service.Object): - def __init__(self, conn=None, obj_path=None): - dbus.service.Object.__init__(self, conn, obj_path) - - @dbus.service.method("org.openobex.Agent", - in_signature="o", out_signature="s") - def Request(self, path): - print "Transfer Request" - self.transfer = dbus.Interface(bus.get_object("org.openobex.client", - path), "org.openobex.Transfer") - properties = self.transfer.GetProperties() - for key in properties.keys(): - print " %s = %s" % (key, properties[key]) - self.start = True - return "" - - @dbus.service.method("org.openobex.Agent", - in_signature="ot", out_signature="") - def Progress(self, path, transferred): - if (self.start): - print "Transfer Started" - properties = self.transfer.GetProperties() - self.transfer_size = properties['Size'] - self.start_time = time.time() - self.start = False - else: - speed = transferred / abs((time.time() - self.start_time) * 1000) - progress = "(" + str(transferred) + "/" + str(self.transfer_size) + " bytes) @ " + str(int(speed)) + " kB/s" - out = "\rTransfer progress " + progress - sys.stdout.write(out) - sys.stdout.flush() - return - - @dbus.service.method("org.openobex.Agent", - in_signature="o", out_signature="") - def Complete(self, path): - print "\nTransfer finished" - return - - @dbus.service.method("org.openobex.Agent", - in_signature="os", out_signature="") - def Error(self, path, error): - print "\nTransfer finished with an error: %s" % (error) - return - - @dbus.service.method("org.openobex.Agent", - in_signature="", out_signature="") - def Release(self): - mainloop.quit() - return - -if __name__ == '__main__': - dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) - - bus = dbus.SessionBus() - client = dbus.Interface(bus.get_object("org.openobex.client", "/"), - "org.openobex.Client") - - if (len(sys.argv) < 3): - print "Usage: %s [file*]" % (sys.argv[0]) - sys.exit(1) - - path = "/test/agent" - agent = Agent(bus, path) - - mainloop = gobject.MainLoop() - files = [os.path.realpath(f) for f in sys.argv[2:]] - - client.SendFiles({ "Destination": sys.argv[1] }, files, path) - - mainloop.run() diff -Nru obexd-0.46/test/simple-agent obexd-0.48/test/simple-agent --- obexd-0.46/test/simple-agent 2009-05-02 17:52:30.000000000 +0200 +++ obexd-0.48/test/simple-agent 2012-07-26 19:09:25.000000000 +0200 @@ -12,8 +12,8 @@ dbus.service.Object.__init__(self, conn, obj_path) self.pending_auth = False - @dbus.service.method("org.openobex.Agent", - in_signature="osssii", out_signature="s") + @dbus.service.method("org.bluez.obex.Agent", in_signature="osssii", + out_signature="s") def Authorize(self, dpath, device, filename, ftype, length, time): global transfers @@ -23,8 +23,9 @@ if auth == "n" or auth == "N": self.pending_auth = False - raise dbus.DBusException("org.openobex.Error.Rejected: " - "Not Autorized") + raise dbus.DBusException( + "org.bluez.obex.Error.Rejected: " + "Not Autorized") print "Full filename (including path):" self.pending_auth = False @@ -32,8 +33,8 @@ transfers.append(Transfer(dpath, filename, 0, length)) return raw_input().strip("\n ") - @dbus.service.method("org.openobex.Agent", - in_signature="", out_signature="") + @dbus.service.method("org.bluez.obex.Agent", in_signature="", + out_signature="") def Cancel(self): print "Authorization Canceled" self.pending_auth = False @@ -53,9 +54,9 @@ self.size = total def cancel(self): - transfer_iface = dbus.Interface(bus.get_object("org.openobex", - self.dpath), - "org.openobex.Transfer") + transfer_iface = dbus.Interface(bus.get_object( + "org.bluez.obex", self.dpath), + "org.bluez.obex.Transfer") transfer_iface.Cancel() def __str__(self): @@ -71,9 +72,9 @@ def new_transfer(dpath): print "new transfer" bus.add_signal_receiver(progress, - dbus_interface="org.openobex.Transfer", - signal_name="Progress", - path_keyword="dpath") + dbus_interface="org.bluez.obex.Transfer", + signal_name="Progress", + path_keyword="dpath") def transfer_completed(dpath, success): global transfers @@ -96,15 +97,15 @@ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) bus = dbus.SessionBus() - manager = dbus.Interface(bus.get_object("org.openobex", "/"), - "org.openobex.Manager") + manager = dbus.Interface(bus.get_object("org.bluez.obex", "/"), + "org.bluez.obex.Manager") bus.add_signal_receiver(new_transfer, - dbus_interface="org.openobex.Manager", - signal_name="TransferStarted") + dbus_interface="org.bluez.obex.Manager", + signal_name="TransferStarted") bus.add_signal_receiver(transfer_completed, - dbus_interface="org.openobex.Manager", - signal_name="TransferCompleted") + dbus_interface="org.bluez.obex.Manager", + signal_name="TransferCompleted") path = "/test/agent" agent = Agent(bus, path) diff -Nru obexd-0.46/tools/test-client.c obexd-0.48/tools/test-client.c --- obexd-0.46/tools/test-client.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/tools/test-client.c 2012-11-30 08:59:13.000000000 +0100 @@ -181,7 +181,7 @@ G_OBEX_HDR_NAME, argv[1], G_OBEX_HDR_INVALID); if (err != NULL) { - g_printerr("put failed: %s\n", err->message); + g_printerr("get failed: %s\n", err->message); g_error_free(err); close(data->fd); g_free(data); @@ -344,69 +344,66 @@ transport_connect(io, transport); } -static GIOChannel *bluetooth_connect(GObexTransportType transport) +static GIOChannel *l2cap_connect(GObexTransportType transport, GError **err) { - GIOChannel *io; - GError *err = NULL; - BtIOType type; - BtIOOption option; - - if (option_dest == NULL || option_channel < 0) - return NULL; - - if (option_channel > 31) { - type = option_packet ? BT_IO_L2CAP : BT_IO_L2ERTM; - option = BT_IO_OPT_PSM; - } else { - type = BT_IO_RFCOMM; - option = BT_IO_OPT_CHANNEL; - } - - if (option_source) { - if (type == BT_IO_L2CAP) { - io = bt_io_connect(type, conn_callback, + if (option_source) + return bt_io_connect(conn_callback, GUINT_TO_POINTER(transport), - NULL, &err, + NULL, err, BT_IO_OPT_SOURCE, option_source, BT_IO_OPT_DEST, option_dest, - option, option_channel, + BT_IO_OPT_PSM, option_channel, BT_IO_OPT_MODE, BT_IO_MODE_ERTM, BT_IO_OPT_OMTU, option_omtu, BT_IO_OPT_IMTU, option_imtu, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); - } else { - io = bt_io_connect(type, conn_callback, + + return bt_io_connect(conn_callback, GUINT_TO_POINTER(transport), - NULL, &err, - BT_IO_OPT_SOURCE, option_source, + NULL, err, BT_IO_OPT_DEST, option_dest, - option, option_channel, + BT_IO_OPT_PSM, option_channel, + BT_IO_OPT_MODE, BT_IO_MODE_ERTM, + BT_IO_OPT_OMTU, option_omtu, + BT_IO_OPT_IMTU, option_imtu, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); - } - } else { - if (type == BT_IO_L2CAP) { - io = bt_io_connect(type, conn_callback, +} + +static GIOChannel *rfcomm_connect(GObexTransportType transport, GError **err) +{ + if (option_source) + return bt_io_connect(conn_callback, GUINT_TO_POINTER(transport), - NULL, &err, + NULL, err, + BT_IO_OPT_SOURCE, option_source, BT_IO_OPT_DEST, option_dest, - option, option_channel, - BT_IO_OPT_MODE, BT_IO_MODE_ERTM, - BT_IO_OPT_OMTU, option_omtu, - BT_IO_OPT_IMTU, option_imtu, + BT_IO_OPT_CHANNEL, option_channel, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); - } else { - io = bt_io_connect(type, conn_callback, + + return bt_io_connect(conn_callback, GUINT_TO_POINTER(transport), - NULL, &err, + NULL, err, BT_IO_OPT_DEST, option_dest, - option, option_channel, + BT_IO_OPT_CHANNEL, option_channel, BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW, BT_IO_OPT_INVALID); - } - } +} + +static GIOChannel *bluetooth_connect(GObexTransportType transport) +{ + GIOChannel *io; + GError *err = NULL; + + if (option_dest == NULL || option_channel < 0) + return NULL; + + if (option_channel > 31) + io = l2cap_connect(transport, &err); + else + io = rfcomm_connect(transport, &err); if (io != NULL) return io; diff -Nru obexd-0.46/tools/test-server.c obexd-0.48/tools/test-server.c --- obexd-0.46/tools/test-server.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/tools/test-server.c 2012-11-30 08:59:13.000000000 +0100 @@ -308,40 +308,40 @@ return FALSE; } +static GIOChannel *l2cap_listen(GError **err) +{ + return bt_io_listen(bluetooth_accept, NULL, NULL, + NULL, err, + BT_IO_OPT_PSM, option_channel, + BT_IO_OPT_MODE, BT_IO_MODE_ERTM, + BT_IO_OPT_OMTU, option_omtu, + BT_IO_OPT_IMTU, option_imtu, + BT_IO_OPT_INVALID); +} + +static GIOChannel *rfcomm_listen(GError **err) +{ + return bt_io_listen(bluetooth_accept, NULL, NULL, + NULL, err, + BT_IO_OPT_CHANNEL, option_channel, + BT_IO_OPT_INVALID); +} + static guint bluetooth_listen(void) { GIOChannel *io; guint id; GError *err = NULL; - BtIOType type; - BtIOOption option; if (option_channel == -1) { g_printerr("Bluetooth channel not set\n"); return 0; } - if (option_packet || option_channel > 31) { - type = option_packet ? BT_IO_L2CAP : BT_IO_L2ERTM; - option = BT_IO_OPT_PSM; - } else { - type = BT_IO_RFCOMM; - option = BT_IO_OPT_CHANNEL; - } - - if (type == BT_IO_L2CAP) - io = bt_io_listen(type, bluetooth_accept, NULL, NULL, - NULL, &err, - option, option_channel, - BT_IO_OPT_MODE, BT_IO_MODE_ERTM, - BT_IO_OPT_OMTU, option_omtu, - BT_IO_OPT_IMTU, option_imtu, - BT_IO_OPT_INVALID); + if (option_packet || option_channel > 31) + io = l2cap_listen(&err); else - io = bt_io_listen(type, bluetooth_accept, NULL, NULL, - NULL, &err, - option, option_channel, - BT_IO_OPT_INVALID); + io = rfcomm_listen(&err); if (io == NULL) { g_printerr("%s\n", err->message); diff -Nru obexd-0.46/unit/test-gobex-apparam.c obexd-0.48/unit/test-gobex-apparam.c --- obexd-0.46/unit/test-gobex-apparam.c 1970-01-01 01:00:00.000000000 +0100 +++ obexd-0.48/unit/test-gobex-apparam.c 2012-11-30 08:59:13.000000000 +0100 @@ -0,0 +1,422 @@ +/* + * + * OBEX library with GLib integration + * + * Copyright (C) 2012 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include + +#include + +#include "util.h" + +#define TAG_U8 0x00 +#define TAG_U16 0x01 +#define TAG_U32 0x02 +#define TAG_U64 0x03 +#define TAG_STRING 0x04 +#define TAG_BYTES 0x05 + +static uint8_t tag_nval_short[] = { TAG_U8 }; +static uint8_t tag_nval_data[] = { TAG_U8, 0x01 }; +static uint8_t tag_nval2_short[] = { TAG_U8, 0x01, 0x1, TAG_U16 }; +static uint8_t tag_nval2_data[] = { TAG_U8, 0x01, 0x1, TAG_U16, 0x02 }; +static uint8_t tag_uint8[] = { TAG_U8, 0x01, 0x01 }; +static uint8_t tag_uint16[] = { TAG_U16, 0x02, 0x01, 0x02 }; +static uint8_t tag_uint32[] = { TAG_U32, 0x04, 0x01, 0x02, 0x03, 0x04 }; +static uint8_t tag_uint64[] = { TAG_U64, 0x08, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08 }; +static uint8_t tag_string[] = { TAG_STRING, 0x04, 'A', 'B', 'C', '\0' }; +static uint8_t tag_bytes[257] = { TAG_BYTES, 0xFF }; +static uint8_t tag_multi[] = { TAG_U8, 0x01, 0x01, + TAG_U16, 0x02, 0x01, 0x02, + TAG_U32, 0x04, 0x01, 0x02, 0x03, 0x04, + TAG_U64, 0x08, 0x01, 0x02, 0x03, 0x04, + 0x05, 0x06, 0x07, 0x08, + TAG_STRING, 0x04, 'A', 'B', 'C', '\0' }; + + +static GObexApparam *parse_and_decode(const void *data, gsize size) +{ + GObexApparam *apparam; + guint8 encoded[1024]; + gsize len; + + apparam = g_obex_apparam_decode(data, size); + + g_assert(apparam != NULL); + + len = g_obex_apparam_encode(apparam, encoded, sizeof(encoded)); + + assert_memequal(data, size, encoded, len); + + return apparam; +} + +static void test_apparam_nval_short(void) +{ + GObexApparam *apparam; + + apparam = g_obex_apparam_decode(tag_nval_short, + sizeof(tag_nval_short)); + + g_assert(apparam == NULL); +} + +static void test_apparam_nval_data(void) +{ + GObexApparam *apparam; + + apparam = g_obex_apparam_decode(tag_nval_data, + sizeof(tag_nval_data)); + + g_assert(apparam == NULL); +} + +static void test_apparam_nval2_short(void) +{ + GObexApparam *apparam; + + apparam = g_obex_apparam_decode(tag_nval2_short, + sizeof(tag_nval2_short)); + + g_assert(apparam == NULL); +} + +static void test_apparam_nval2_data(void) +{ + GObexApparam *apparam; + + apparam = g_obex_apparam_decode(tag_nval2_data, + sizeof(tag_nval2_data)); + + g_assert(apparam == NULL); +} + +static void test_apparam_get_uint8(void) +{ + GObexApparam *apparam; + guint8 data; + gboolean ret; + + apparam = parse_and_decode(tag_uint8, sizeof(tag_uint8)); + + ret = g_obex_apparam_get_uint8(apparam, TAG_U8, &data); + + g_assert(ret == TRUE); + g_assert(data == 0x01); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_get_uint16(void) +{ + GObexApparam *apparam; + uint16_t data; + gboolean ret; + + apparam = parse_and_decode(tag_uint16, sizeof(tag_uint16)); + + ret = g_obex_apparam_get_uint16(apparam, TAG_U16, &data); + + g_assert(ret == TRUE); + g_assert(data == 0x0102); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_get_uint32(void) +{ + GObexApparam *apparam; + uint32_t data; + gboolean ret; + + apparam = parse_and_decode(tag_uint32, sizeof(tag_uint32)); + + ret = g_obex_apparam_get_uint32(apparam, TAG_U32, &data); + + g_assert(ret == TRUE); + g_assert(data == 0x01020304); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_get_uint64(void) +{ + GObexApparam *apparam; + uint64_t data; + gboolean ret; + + apparam = parse_and_decode(tag_uint64, sizeof(tag_uint64)); + + ret = g_obex_apparam_get_uint64(apparam, TAG_U64, &data); + + g_assert(ret == TRUE); + g_assert(data == 0x0102030405060708); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_get_string(void) +{ + GObexApparam *apparam; + char *string; + + apparam = parse_and_decode(tag_string, sizeof(tag_string)); + + string = g_obex_apparam_get_string(apparam, TAG_STRING); + + g_assert(string != NULL); + g_assert_cmpstr(string, ==, "ABC"); + + g_free(string); + g_obex_apparam_free(apparam); +} + +static void test_apparam_get_bytes(void) +{ + GObexApparam *apparam; + const uint8_t *data; + gsize len; + gboolean ret; + + apparam = parse_and_decode(tag_bytes, sizeof(tag_bytes)); + + ret = g_obex_apparam_get_bytes(apparam, TAG_BYTES, &data, &len); + + g_assert(ret == TRUE); + assert_memequal(tag_bytes + 2, sizeof(tag_bytes) - 2, data, len); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_get_multi(void) +{ + GObexApparam *apparam; + char *string; + uint8_t data8; + uint16_t data16; + uint32_t data32; + uint64_t data64; + gboolean ret; + + apparam = g_obex_apparam_decode(tag_multi, sizeof(tag_multi)); + + g_assert(apparam != NULL); + + ret = g_obex_apparam_get_uint8(apparam, TAG_U8, &data8); + + g_assert(ret == TRUE); + g_assert(data8 == 0x01); + + ret = g_obex_apparam_get_uint16(apparam, TAG_U16, &data16); + + g_assert(ret == TRUE); + g_assert(data16 == 0x0102); + + ret = g_obex_apparam_get_uint32(apparam, TAG_U32, &data32); + + g_assert(ret == TRUE); + g_assert(data32 == 0x01020304); + + ret = g_obex_apparam_get_uint64(apparam, TAG_U64, &data64); + + g_assert(ret == TRUE); + g_assert(data64 == 0x0102030405060708); + + string = g_obex_apparam_get_string(apparam, TAG_STRING); + + g_assert(string != NULL); + g_assert_cmpstr(string, ==, "ABC"); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_set_uint8(void) +{ + GObexApparam *apparam; + guint8 buf[1024]; + gsize len; + + apparam = g_obex_apparam_set_uint8(NULL, TAG_U8, 0x01); + g_assert(apparam != NULL); + + len = g_obex_apparam_encode(apparam, buf, sizeof(buf)); + assert_memequal(tag_uint8, sizeof(tag_uint8), buf, len); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_set_uint16(void) +{ + GObexApparam *apparam; + guint8 buf[1024]; + gsize len; + + apparam = g_obex_apparam_set_uint16(NULL, TAG_U16, 0x0102); + g_assert(apparam != NULL); + + len = g_obex_apparam_encode(apparam, buf, sizeof(buf)); + assert_memequal(tag_uint16, sizeof(tag_uint16), buf, len); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_set_uint32(void) +{ + GObexApparam *apparam; + guint8 buf[1024]; + gsize len; + + apparam = g_obex_apparam_set_uint32(NULL, TAG_U32, 0x01020304); + g_assert(apparam != NULL); + + len = g_obex_apparam_encode(apparam, buf, sizeof(buf)); + assert_memequal(tag_uint32, sizeof(tag_uint32), buf, len); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_set_uint64(void) +{ + GObexApparam *apparam; + guint8 buf[1024]; + gsize len; + + apparam = g_obex_apparam_set_uint64(NULL, TAG_U64, 0x0102030405060708); + g_assert(apparam != NULL); + + len = g_obex_apparam_encode(apparam, buf, sizeof(buf)); + assert_memequal(tag_uint64, sizeof(tag_uint64), buf, len); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_set_string(void) +{ + GObexApparam *apparam; + guint8 buf[1024]; + gsize len; + + apparam = g_obex_apparam_set_string(NULL, TAG_STRING, "ABC"); + g_assert(apparam != NULL); + + len = g_obex_apparam_encode(apparam, buf, sizeof(buf)); + assert_memequal(tag_string, sizeof(tag_string), buf, len); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_set_bytes(void) +{ + GObexApparam *apparam; + guint8 buf[1024]; + gsize len; + + apparam = g_obex_apparam_set_bytes(NULL, TAG_BYTES, tag_bytes + 2, 255); + g_assert(apparam != NULL); + + len = g_obex_apparam_encode(apparam, buf, sizeof(buf)); + assert_memequal(tag_bytes, sizeof(tag_bytes), buf, len); + + g_obex_apparam_free(apparam); +} + +static void test_apparam_set_multi(void) +{ + GObexApparam *apparam; + guint8 buf[1024]; + gsize len; + + apparam = g_obex_apparam_set_uint8(NULL, TAG_U8, 0x01); + + g_assert(apparam != NULL); + + apparam = g_obex_apparam_set_uint16(apparam, TAG_U16, 0x0102); + + g_assert(apparam != NULL); + + apparam = g_obex_apparam_set_uint32(apparam, TAG_U32, 0x01020304); + + g_assert(apparam != NULL); + + apparam = g_obex_apparam_set_uint64(apparam, TAG_U64, + 0x0102030405060708); + + g_assert(apparam != NULL); + + apparam = g_obex_apparam_set_string(apparam, TAG_STRING, "ABC"); + + g_assert(apparam != NULL); + + len = g_obex_apparam_encode(apparam, buf, sizeof(buf)); + + g_assert_cmpuint(len, ==, sizeof(tag_multi)); + + g_obex_apparam_free(apparam); +} + +int main(int argc, char *argv[]) +{ + g_test_init(&argc, &argv, NULL); + + g_test_add_func("/gobex/test_apparam_nval_short", + test_apparam_nval_short); + g_test_add_func("/gobex/test_apparam_nval_data", + test_apparam_nval_data); + + g_test_add_func("/gobex/test_apparam_nval2_short", + test_apparam_nval2_short); + g_test_add_func("/gobex/test_apparam_nval2_data", + test_apparam_nval2_data); + + g_test_add_func("/gobex/test_apparam_get_uint8", + test_apparam_get_uint8); + g_test_add_func("/gobex/test_apparam_get_uint16", + test_apparam_get_uint16); + g_test_add_func("/gobex/test_apparam_get_uint32", + test_apparam_get_uint32); + g_test_add_func("/gobex/test_apparam_get_uint64", + test_apparam_get_uint64); + g_test_add_func("/gobex/test_apparam_get_string", + test_apparam_get_string); + g_test_add_func("/gobex/test_apparam_get_bytes", + test_apparam_get_bytes); + g_test_add_func("/gobex/test_apparam_get_multi", + test_apparam_get_multi); + + g_test_add_func("/gobex/test_apparam_set_uint8", + test_apparam_set_uint8); + g_test_add_func("/gobex/test_apparam_set_uint16", + test_apparam_set_uint16); + g_test_add_func("/gobex/test_apparam_set_uint32", + test_apparam_set_uint32); + g_test_add_func("/gobex/test_apparam_set_uint64", + test_apparam_set_uint64); + g_test_add_func("/gobex/test_apparam_set_string", + test_apparam_set_string); + g_test_add_func("/gobex/test_apparam_set_bytes", + test_apparam_set_bytes); + g_test_add_func("/gobex/test_apparam_set_multi", + test_apparam_set_multi); + + g_test_run(); + + return 0; +} diff -Nru obexd-0.46/unit/test-gobex-header.c obexd-0.48/unit/test-gobex-header.c --- obexd-0.46/unit/test-gobex-header.c 2012-05-17 17:12:17.000000000 +0200 +++ obexd-0.48/unit/test-gobex-header.c 2012-11-30 08:59:13.000000000 +0100 @@ -47,6 +47,8 @@ 0x01, 0x02, 0x03 }; static uint8_t hdr_bytes_nval_data[] = { G_OBEX_HDR_BODY, 0xab }; static uint8_t hdr_bytes_nval_len[] = { G_OBEX_HDR_BODY, 0x00, 0x00 }; +static uint8_t hdr_apparam[] = { G_OBEX_HDR_APPARAM, 0x00, 0x09, 0x00, 0x04, + 0x01, 0x02, 0x03, 0x04 }; static void test_header_name_empty(void) { @@ -115,6 +117,27 @@ g_obex_header_free(header); } +static void test_header_apparam(void) +{ + GObexHeader *header; + GObexApparam *apparam; + uint8_t buf[1024]; + size_t len; + + apparam = g_obex_apparam_set_uint32(NULL, 0, 0x01020304); + g_assert(apparam != NULL); + + header = g_obex_header_new_apparam(apparam); + g_assert(header != NULL); + + len = g_obex_header_encode(header, buf, sizeof(buf)); + + assert_memequal(hdr_apparam, sizeof(hdr_apparam), buf, len); + + g_obex_apparam_free(apparam); + g_obex_header_free(header); +} + static void test_header_uint8(void) { GObexHeader *header; @@ -247,6 +270,26 @@ g_obex_header_free(header); } +static void test_header_encode_apparam(void) +{ + GObexHeader *header; + GObexApparam *apparam; + gboolean ret; + guint32 data; + + header = parse_and_encode(hdr_apparam, sizeof(hdr_apparam)); + + apparam = g_obex_header_get_apparam(header); + g_assert(apparam != NULL); + + ret = g_obex_apparam_get_uint32(apparam, 0x00, &data); + g_assert(ret == TRUE); + g_assert(data == 0x01020304); + + g_obex_apparam_free(apparam); + g_obex_header_free(header); +} + static void test_header_encode_actionid(void) { GObexHeader *header; @@ -507,6 +550,8 @@ test_header_encode_body); g_test_add_func("/gobex/test_header_encode_connid", test_header_encode_actionid); + g_test_add_func("/gobex/test_header_encode_apparam", + test_header_encode_apparam); g_test_add_func("/gobex/test_header_name_empty", test_header_name_empty); @@ -517,6 +562,7 @@ g_test_add_func("/gobex/test_header_bytes", test_header_bytes); g_test_add_func("/gobex/test_header_uint8", test_header_uint8); g_test_add_func("/gobex/test_header_uint32", test_header_uint32); + g_test_add_func("/gobex/test_header_apparam", test_header_apparam); g_test_run();