diff --git a/obexd/plugins/filesystem.c b/obexd/plugins/filesystem.c
index c110c80..c88d965 100644
--- a/obexd/plugins/filesystem.c
+++ b/obexd/plugins/filesystem.c
}
static gpointer filesystem_open(const char *name, int oflag, mode_t mode,
- size_t *size, struct obex_session *os, int *err)
+ gpointer context, size_t *size, int *err)
{
struct stat stats;
struct statvfs buf;
}
static gpointer capability_open(const char *name, int oflag, mode_t mode,
- size_t *size, struct obex_session *os, int *err)
+ gpointer context, size_t *size, int *err)
{
struct capability_object *object = NULL;
gchar *buf;
return NULL;
}
-static gpointer folder_open(const char *folder, int oflag, mode_t mode,
- size_t *size, struct obex_session *os, int *err)
+static gpointer folder_open(const char *name, int oflag, mode_t mode,
+ gpointer context, size_t *size, int *err)
{
+ struct obex_session *os = context;
struct stat fstat, dstat;
struct dirent *ep;
GString *object;
object = g_string_append(object, FL_BODY_BEGIN);
- root = g_str_equal(folder, obex_get_root_folder(os));
+ root = g_str_equal(name, obex_get_root_folder(os));
- dp = opendir(folder);
+ dp = opendir(name);
if (dp == NULL) {
if (err)
*err = -ENOENT;
symlinks = obex_get_symlinks(os);
if (root && symlinks)
- ret = stat(folder, &dstat);
+ ret = stat(name, &dstat);
else {
object = g_string_append(object, FL_PARENT_FOLDER_ELEMENT);
- ret = lstat(folder, &dstat);
+ ret = lstat(name, &dstat);
}
if (ret < 0) {
}
while ((ep = readdir(dp))) {
- gchar *name;
+ gchar *filename;
gchar *fullname;
gchar *line;
if (ep->d_name[0] == '.')
continue;
- name = g_filename_to_utf8(ep->d_name, -1, NULL, NULL, NULL);
+ filename = g_filename_to_utf8(ep->d_name, -1, NULL, NULL, NULL);
if (name == NULL) {
error("g_filename_to_utf8: invalid filename");
continue;
}
- fullname = g_build_filename(folder, ep->d_name, NULL);
+ fullname = g_build_filename(name, ep->d_name, NULL);
if (root && symlinks)
ret = stat(fullname, &fstat);
if (ret < 0) {
debug("%s: %s(%d)", root ? "stat" : "lstat",
strerror(errno), errno);
- g_free(name);
+ g_free(filename);
g_free(fullname);
continue;
}
g_free(fullname);
- line = file_stat_line(name, &fstat, &dstat, root, pcsuite);
+ line = file_stat_line(filename, &fstat, &dstat, root, pcsuite);
if (line == NULL) {
- g_free(name);
+ g_free(filename);
continue;
}
- g_free(name);
+ g_free(filename);
object = g_string_append(object, line);
g_free(line);
diff --git a/obexd/plugins/ftp.c b/obexd/plugins/ftp.c
index cbb3db2..7b70ed0 100644
--- a/obexd/plugins/ftp.c
+++ b/obexd/plugins/ftp.c
return -ENOENT;
if (g_str_equal(type, CAP_TYPE))
- return obex_stream_start(os, capability);
+ return obex_stream_start(os, capability, NULL);
if (g_str_equal(type, LST_TYPE))
- return obex_stream_start(os, ftp->folder);
+ return obex_stream_start(os, ftp->folder, os);
return -ENOENT;
}
return -EPERM;
}
- return obex_stream_start(os, file);
+ return obex_stream_start(os, file, NULL);
}
static gpointer ftp_connect(struct obex_session *os, int *err)
diff --git a/obexd/plugins/opp.c b/obexd/plugins/opp.c
index f9448d1..a28b0e9 100644
--- a/obexd/plugins/opp.c
+++ b/obexd/plugins/opp.c
return -EPERM;
if (g_str_equal(type, VCARD_TYPE)) {
- if (obex_stream_start(os, VCARD_FILE) < 0)
+ if (obex_stream_start(os, VCARD_FILE, NULL) < 0)
return -ENOENT;
} else
diff --git a/obexd/plugins/pbap.c b/obexd/plugins/pbap.c
index 579995e..95dbc14 100644
--- a/obexd/plugins/pbap.c
+++ b/obexd/plugins/pbap.c
#define APPARAM_HDR_SIZE 2
-#define get_be64(val) GUINT64_FROM_BE(bt_get_unaligned((guint64 *) val))
-#define get_be16(val) GUINT16_FROM_BE(bt_get_unaligned((guint16 *) val))
-
-#define put_be16(val, ptr) bt_put_unaligned(GUINT16_TO_BE(val), (guint16 *) ptr)
-
#define PBAP_CHANNEL 15
#define PBAP_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
</attribute> \
</record>"
-struct apparam_hdr {
+struct aparam_header {
uint8_t tag;
uint8_t len;
uint8_t val[0];
} __attribute__ ((packed));
-struct phonebook_query {
- const char *type;
- GString *buffer;
- struct obex_session *os;
-};
-
struct pbap_session {
struct obex_session *os;
+ struct apparam_field *params;
gchar *folder;
+ GString *buffer;
};
static const guint8 PBAP_TARGET[TARGET_SIZE] = {
pbap->folder = new_folder ? g_strdup(new_folder) : NULL;
}
+static struct apparam_field *parse_aparam(const guint8 *buffer, guint32 hlen)
+{
+ struct apparam_field *param;
+ struct aparam_header *hdr;
+ guint32 len = 0;
+ guint16 val16;
+ guint64 val64;
+
+ 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:
+ 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;
+
+ 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;
+ }
+
+ len += hdr->len + sizeof(struct aparam_header);
+ }
+
+ return param;
+
+failed:
+ g_free(param);
+
+ return NULL;
+}
+
static gpointer pbap_connect(struct obex_session *os, int *err)
{
struct pbap_session *pbap;
struct pbap_session *pbap = user_data;
const gchar *type = obex_get_type(os);
const gchar *name = obex_get_name(os);
+ struct apparam_field *params;
+ const guint8 *buffer;
gchar *path;
+ ssize_t rsize;
gint ret;
if (type == NULL)
else
return -EBADR;
- ret = obex_stream_start(os, path);
+ rsize = obex_aparam_read(os, obj, &buffer);
+ if (rsize < 0) {
+ ret = -EBADR;
+ goto failed;
+ }
+
+ params = parse_aparam(buffer, rsize);
+ if (params == NULL) {
+ ret = -EBADR;
+ goto failed;
+ }
+
+ if (pbap->params) {
+ g_free(pbap->params->searchval);
+ g_free(pbap->params);
+ }
+
+ pbap->params = params;
+ ret = obex_stream_start(os, path, pbap);
+
+failed:
g_free(path);
return ret;
manager_unregister_session(os);
+ if (pbap->params) {
+ g_free(pbap->params->searchval);
+ g_free(pbap->params);
+ }
+
g_free(pbap->folder);
g_free(pbap);
}
static void query_result(const gchar *buffer, size_t bufsize,
gint vcards, gint missed, gpointer user_data)
{
- struct phonebook_query *query = user_data;
+ struct pbap_session *pbap = user_data;
- if (!query->buffer)
- query->buffer = g_string_new_len(buffer, bufsize);
+ if (!pbap->buffer)
+ pbap->buffer = g_string_new_len(buffer, bufsize);
else
- query->buffer = g_string_append_len(query->buffer, buffer, bufsize);
+ pbap->buffer = g_string_append_len(pbap->buffer, buffer, bufsize);
- obex_object_set_io_flags(query, G_IO_IN, 0);
+ obex_object_set_io_flags(pbap, G_IO_IN, 0);
}
static gpointer vobject_open(const char *name, int oflag, mode_t mode,
- size_t *size, struct obex_session *os, int *err)
+ gpointer context, size_t *size, int *err)
{
- const gchar *type = obex_get_type(os);
- struct phonebook_query *query;
+ struct pbap_session *pbap = context;
+ int ret;
- if (oflag != O_RDONLY)
+ if (oflag != O_RDONLY) {
+ ret = -EPERM;
goto fail;
+ }
- /* TODO: mch? */
-
- /* TODO: get application parameter */
- query = g_new0(struct phonebook_query, 1);
- query->type = type;
- query->os = os;
-
- if (phonebook_query(name, query_result, query) < 0) {
- g_free(query);
+ ret = phonebook_pull(name, pbap->params, query_result, pbap);
+ if (ret < 0)
goto fail;
- }
if (size)
*size = OBJECT_SIZE_UNKNOWN;
- return query;
+ return pbap;
fail:
if (err)
- *err = -EPERM;
+ *err = ret;
return NULL;
}
static ssize_t vobject_read(gpointer object, void *buf, size_t count)
{
- struct phonebook_query *query = object;
+ struct pbap_session *pbap = object;
- if (query->buffer)
- return string_read(query->buffer, buf, count);
+ if (pbap->buffer)
+ return string_read(pbap->buffer, buf, count);
return -EAGAIN;
}
static int vobject_close(gpointer object)
{
- struct phonebook_query *query = object;
+ struct pbap_session *pbap = object;
- if (query->buffer)
- string_free(query->buffer);
-
- g_free(query);
+ if (pbap->buffer) {
+ string_free(pbap->buffer);
+ pbap->buffer = NULL;
+ }
return 0;
}
diff --git a/obexd/plugins/phonebook-dummy.c b/obexd/plugins/phonebook-dummy.c
index 3915f87..8bff79d 100644
--- a/obexd/plugins/phonebook-dummy.c
+++ b/obexd/plugins/phonebook-dummy.c
struct dummy_data {
phonebook_cb cb;
gpointer user_data;
+ const struct apparam_field *apparams;
};
int phonebook_init(void)
return 0;
}
-int phonebook_query(const gchar *name, phonebook_cb cb, gpointer user_data)
+int phonebook_pull(const gchar *name, const struct apparam_field *params,
+ phonebook_cb cb, gpointer user_data)
{
struct dummy_data *dummy;
dummy = g_new0(struct dummy_data, 1);
dummy->cb = cb;
dummy->user_data = user_data;
+ dummy->apparams = params;
g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
dummy_result, dummy, g_free);
diff --git a/obexd/plugins/phonebook-ebook.c b/obexd/plugins/phonebook-ebook.c
index 66e2462..f47d3fd 100644
--- a/obexd/plugins/phonebook-ebook.c
+++ b/obexd/plugins/phonebook-ebook.c
#define QUERY_PHONE "(contains \"phone\" \"%s\")"
struct query_data {
+ const struct apparam_field *params;
phonebook_cb cb;
gpointer user_data;
};
return ret;
}
-gint phonebook_query(const gchar *name, phonebook_cb cb, gpointer user_data)
+gint phonebook_pull(const gchar *name, const struct apparam_field *params,
+ phonebook_cb cb, gpointer user_data)
{
struct query_data *data;
EBookQuery *query;
data = g_new0(struct query_data, 1);
data->cb = cb;
+ data->params = params;
data->user_data = user_data;
e_book_async_get_contacts(ebook, query, ebookpull_cb, data);
diff --git a/obexd/plugins/phonebook.h b/obexd/plugins/phonebook.h
index b5bc10e..9eaf095 100644
--- a/obexd/plugins/phonebook.h
+++ b/obexd/plugins/phonebook.h
*/
struct apparam_field {
- guint64 filter;
+ /* list and pull attributes */
guint16 maxlistcount;
guint16 liststartoffset;
+
+ /* pull and vcard attributes */
+ guint64 filter;
guint8 format;
+
+ /* list attributes only */
guint8 order;
guint8 searchattrib;
guint8 *searchval;
int phonebook_set_folder(const gchar *current_folder,
const gchar *new_folder, guint8 flags);
-int phonebook_query(const gchar *name, phonebook_cb cb, gpointer user_data);
+int phonebook_pull(const gchar *name, const struct apparam_field *params,
+ phonebook_cb cb, gpointer user_data);
diff --git a/obexd/plugins/syncevolution.c b/obexd/plugins/syncevolution.c
index a352ede..411cdf2 100644
--- a/obexd/plugins/syncevolution.c
+++ b/obexd/plugins/syncevolution.c
static int synce_get(struct obex_session *os, obex_object_t *obj, gpointer user_data)
{
- return 0;
+ return obex_stream_start(os, NULL, os);
}
static void close_cb(DBusPendingCall *call, void *user_data)
}
static gpointer synce_open(const char *name, int oflag, mode_t mode,
- size_t *size, struct obex_session *os, int *err)
+ gpointer user_data, size_t *size, int *err)
{
+ struct obex_session *os = user_data;
DBusConnection *conn;
struct synce_context *context;
diff --git a/obexd/src/mimetype.h b/obexd/src/mimetype.h
index 69059cf..248b1b4 100644
--- a/obexd/src/mimetype.h
+++ b/obexd/src/mimetype.h
struct obex_mime_type_driver {
const guint8 *target;
const char *mimetype;
+ gpointer context;
gpointer (*open) (const char *name, int oflag, mode_t mode,
- size_t *size, struct obex_session *os, int *err);
+ gpointer context, size_t *size, int *err);
int (*close) (gpointer object);
ssize_t (*read) (gpointer object, void *buf, size_t count);
ssize_t (*write) (gpointer object, const void *buf, size_t count);
diff --git a/obexd/src/obex.c b/obexd/src/obex.c
index 59e30e0..717b264 100644
--- a/obexd/src/obex.c
+++ b/obexd/src/obex.c
os_set_response(obj, err);
}
-int obex_stream_start(struct obex_session *os, const gchar *filename)
+int obex_stream_start(struct obex_session *os,
+ const gchar *filename, gpointer context)
{
gint err;
gpointer object;
size_t size;
- object = os->driver->open(filename, O_RDONLY, 0, &size, os, &err);
+ object = os->driver->open(filename, O_RDONLY, 0, context, &size, &err);
if (object == NULL) {
error("open(%s): %s (%d)", filename, strerror(-err), -err);
goto fail;
}
+ os->driver->context = context;
os->object = object;
os->offset = 0;
os->size = size;
fail:
if (object)
os->driver->close(object);
+
return err;
}
gint len;
int err;
- os->object = os->driver->open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600,
+ os->object = os->driver->open(filename, O_WRONLY | O_CREAT | O_TRUNC,
+ 0600, os->driver->context,
os->size != OBJECT_SIZE_UNKNOWN ?
- (size_t *) &os->size : NULL, os, &err);
+ (size_t *) &os->size : NULL, &err);
if (os->object == NULL) {
error("open(%s): %s (%d)", filename, strerror(-err), -err);
return -EPERM;
return g_strdup_printf("%s+%d", address, channel);
}
+
+ssize_t obex_aparam_read(struct obex_session *os,
+ obex_object_t *obj, const guint8 **buffer)
+{
+ obex_headerdata_t hd;
+ guint8 hi;
+ guint32 hlen;
+
+ OBEX_ObjectReParseHeaders(os->obex, obj);
+
+ while (OBEX_ObjectGetNextHeader(os->obex, obj, &hi, &hd, &hlen)) {
+ if (hi == OBEX_HDR_APPARAM) {
+ *buffer = hd.bs;
+ return hlen;
+ }
+ }
+
+ return -EBADR;
+}
diff --git a/obexd/src/obex.h b/obexd/src/obex.h
index 7a8942a..f1a4f07 100644
--- a/obexd/src/obex.h
+++ b/obexd/src/obex.h
void obex_connect_cb(GIOChannel *io, GError *err, gpointer user_data);
-int obex_stream_start(struct obex_session *os, const gchar *filename);
+int obex_stream_start(struct obex_session *os,
+ const gchar *filename, gpointer user_data);
gint obex_prepare_put(struct obex_session *os, const gchar *filename);
const char *obex_get_name(struct obex_session *os);
ssize_t obex_get_size(struct obex_session *os);
gboolean obex_get_auto_accept(struct obex_session *os);
int obex_remove(struct obex_session *os, const char *path);
char *obex_get_id(struct obex_session *os);
+ssize_t obex_aparam_read(struct obex_session *os,
+ obex_object_t *obj, const guint8 **buffer);
int tty_init(gint service, const gchar *folder, const gchar *capability,
gboolean symlinks, const gchar *devnode);