Diff between 9561c462f0c549d1d722dfde188602155f5b07b7 and f53123b6a1a26128ae0bc3e2ad40bfd57933ba14

Changed Files

File Additions Deletions Status
obexd/plugins/filesystem.c +16 -15 modified
obexd/plugins/ftp.c +3 -3 modified
obexd/plugins/opp.c +1 -1 modified
obexd/plugins/pbap.c +130 -42 modified
obexd/plugins/phonebook-dummy.c +4 -1 modified
obexd/plugins/phonebook-ebook.c +4 -1 modified
obexd/plugins/phonebook.h +8 -2 modified
obexd/plugins/syncevolution.c +3 -2 modified
obexd/src/mimetype.h +2 -1 modified
obexd/src/obex.c +27 -4 modified
obexd/src/obex.h +4 -1 modified

Full Patch

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
@@ -124,7 +124,7 @@ static gchar *file_stat_line(gchar *filename, struct stat *fstat,
 }
 
 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;
@@ -247,7 +247,7 @@ static int capability_exec(const char **argv, int *output, int *err)
 }
 
 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;
@@ -306,9 +306,10 @@ fail:
 	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;
@@ -323,9 +324,9 @@ static gpointer folder_open(const char *folder, int oflag, mode_t mode,
 
 	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;
@@ -334,10 +335,10 @@ static gpointer folder_open(const char *folder, int oflag, mode_t mode,
 
 	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) {
@@ -347,20 +348,20 @@ static gpointer folder_open(const char *folder, int oflag, mode_t mode,
 	}
 
 	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);
@@ -370,20 +371,20 @@ static gpointer folder_open(const char *folder, int oflag, mode_t mode,
 		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
@@ -165,10 +165,10 @@ static gint get_by_type(struct ftp_session *ftp, const gchar *type)
 		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;
 }
@@ -195,7 +195,7 @@ static gint ftp_prepare_get(struct ftp_session *ftp, gchar *file)
 			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
@@ -177,7 +177,7 @@ static int opp_get(struct obex_session *os, obex_object_t *obj,
 		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
@@ -78,11 +78,6 @@
 
 #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\" ?>	\
@@ -126,21 +121,17 @@
   </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] = {
@@ -154,6 +145,81 @@ static void set_folder(struct pbap_session *pbap, const char *new_folder)
 	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;
@@ -176,7 +242,10 @@ static int pbap_get(struct obex_session *os, obex_object_t *obj,
 	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)
@@ -200,7 +269,27 @@ static int pbap_get(struct obex_session *os, obex_object_t *obj,
 	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;
@@ -246,6 +335,11 @@ static void pbap_disconnect(struct obex_session *os,
 
 	manager_unregister_session(os);
 
+	if (pbap->params) {
+		g_free(pbap->params->searchval);
+		g_free(pbap->params);
+	}
+
 	g_free(pbap->folder);
 	g_free(pbap);
 }
@@ -274,67 +368,61 @@ struct obex_service_driver 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
@@ -43,6 +43,7 @@
 struct dummy_data {
 	phonebook_cb	cb;
 	gpointer	user_data;
+	const struct apparam_field *apparams;
 };
 
 int phonebook_init(void)
@@ -69,13 +70,15 @@ int phonebook_set_folder(const gchar *current_folder,
 	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
@@ -53,6 +53,7 @@
 #define QUERY_PHONE "(contains \"phone\" \"%s\")"
 
 struct query_data {
+	const struct apparam_field *params;
 	phonebook_cb cb;
 	gpointer user_data;
 };
@@ -161,7 +162,8 @@ int phonebook_set_folder(const gchar *current_folder,
 	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;
@@ -170,6 +172,7 @@ gint phonebook_query(const gchar *name, phonebook_cb cb, gpointer user_data)
 
 	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
@@ -22,10 +22,15 @@
  */
 
 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;
@@ -40,4 +45,5 @@ void phonebook_exit(void);
 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
@@ -230,7 +230,7 @@ static int synce_put(struct obex_session *os, gpointer user_data)
 
 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)
@@ -255,8 +255,9 @@ static void synce_disconnect(struct obex_session *os, gpointer 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
@@ -27,8 +27,9 @@ typedef gboolean (*obex_object_io_func) (gpointer object, int flags, int err,
 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
@@ -456,18 +456,20 @@ static void cmd_setpath(struct obex_session *os,
 	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;
@@ -480,6 +482,7 @@ int obex_stream_start(struct obex_session *os, const gchar *filename)
 fail:
 	if (object)
 		os->driver->close(object);
+
 	return err;
 }
 
@@ -544,9 +547,10 @@ gint obex_prepare_put(struct obex_session *os, const gchar *filename)
 	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;
@@ -1170,3 +1174,22 @@ char *obex_get_id(struct obex_session *os)
 
 	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
@@ -42,7 +42,8 @@ struct obex_session;
 
 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);
@@ -54,6 +55,8 @@ const char *obex_get_capability_path(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);