Diff between 6172e3e51f90fc3dddc6ebfa8b35b89cc1a1a21c and 3a1e6b3e8dc13264650e4506c7db77f2d196bcf7

Changed Files

File Additions Deletions Status
obexd/client/pbap.c +194 -1 modified

Full Patch

diff --git a/obexd/client/pbap.c b/obexd/client/pbap.c
index f92e4b6..0436715 100644
--- a/obexd/client/pbap.c
+++ b/obexd/client/pbap.c
@@ -74,6 +74,42 @@
 
 #define get_be16(val)	GUINT16_FROM_BE(bt_get_unaligned((guint16 *) val))
 
+static const char *filter_list[] = {
+	"VERSION",
+	"FN",
+	"N",
+	"PHOTO",
+	"BDAY",
+	"ADR",
+	"LABEL",
+	"TEL",
+	"EMAIL",
+	"MAILER",
+	"TZ",
+	"GEO",
+	"TITLE",
+	"ROLE",
+	"LOGO",
+	"AGENT",
+	"ORG",
+	"NOTE",
+	"REV",
+	"SOUND",
+	"URL",
+	"UID",
+	"KEY",
+	"NICKNAME",
+	"CATEGORIES",
+	"PROID",
+	"CLASS",
+	"SORT-STRING",
+	"X-IRMC-CALL-DATETIME",
+	NULL
+};
+
+#define FILTER_BIT_MAX	63
+#define FILTER_ALL	0xFFFFFFFFFFFFFFFFULL
+
 struct pullphonebook_apparam {
 	uint8_t     filter_tag;
 	uint8_t     filter_len;
@@ -526,6 +562,85 @@ static int set_order(struct session_data *session, const char *orderstr)
 	return 0;
 }
 
+static uint64_t get_filter_mask(const char *filterstr)
+{
+	int i, bit = -1;
+
+	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;
+
+	if (strlen(filterstr) < 4 || strlen(filterstr) > 5
+			|| g_ascii_strncasecmp(filterstr, "bit", 3) != 0)
+		return 0;
+
+	sscanf(&filterstr[3], "%d", &bit);
+	if (bit >= 0 && bit <= FILTER_BIT_MAX)
+		return 1ULL << bit;
+	else
+		return 0;
+}
+
+static int add_filter(struct session_data *session, const char *filterstr)
+{
+	struct pbap_data *pbapdata = session->pbapdata;
+	uint64_t mask;
+
+	mask = get_filter_mask(filterstr);
+
+	if (mask == 0)
+		return -EINVAL;
+
+	pbapdata->filter |= mask;
+	return 0;
+}
+
+static int remove_filter(struct session_data *session, const char *filterstr)
+{
+	struct pbap_data *pbapdata = session->pbapdata;
+	uint64_t mask;
+
+	mask = get_filter_mask(filterstr);
+
+	if (mask == 0)
+		return -EINVAL;
+
+	pbapdata->filter &= ~mask;
+	return 0;
+}
+
+static gchar **get_filters(uint64_t filter, gint *size)
+{
+	gchar **list, **item;
+	gint i;
+	gint filter_list_size = sizeof(filter_list) / sizeof(filter_list[0]) - 1;
+
+	list = g_try_malloc0(sizeof(gchar **) * (FILTER_BIT_MAX + 2));
+
+	if (!list)
+		return NULL;
+
+	item = list;
+
+	for (i = 0; i < filter_list_size; i++)
+		if (filter & (1ULL << i))
+			*(item++) = g_strdup(filter_list[i]);
+
+	for (i = filter_list_size; 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_select(DBusConnection *connection,
 					DBusMessage *message, void *user_data)
 {
@@ -724,11 +839,85 @@ static DBusMessage *pbap_set_order(DBusConnection *connection,
 
 	if (set_order(session, order) < 0)
 		return g_dbus_create_error(message,
-				ERROR_INF ".InvalidArguments", "InvalidOrder");
+				ERROR_INF ".InvalidArguments", "InvalidFilter");
 
 	return dbus_message_new_method_return(message);
 }
 
+static DBusMessage *pbap_add_filter(DBusConnection *connection,
+					DBusMessage *message, void *user_data)
+{
+	struct session_data *session = user_data;
+	const char *filter;
+
+	if (dbus_message_get_args(message, NULL,
+			DBUS_TYPE_STRING, &filter,
+			DBUS_TYPE_INVALID) == FALSE)
+		return g_dbus_create_error(message,
+				ERROR_INF ".InvalidArguments", NULL);
+
+	if (add_filter(session, filter) < 0)
+		return g_dbus_create_error(message,
+				ERROR_INF ".InvalidArguments", "InvalidFilter");
+
+	return dbus_message_new_method_return(message);
+}
+
+static DBusMessage *pbap_remove_filter(DBusConnection *connection,
+					DBusMessage *message, void *user_data)
+{
+	struct session_data *session = user_data;
+	const char *filter;
+
+	if (dbus_message_get_args(message, NULL,
+			DBUS_TYPE_STRING, &filter,
+			DBUS_TYPE_INVALID) == FALSE)
+		return g_dbus_create_error(message,
+				ERROR_INF ".InvalidArguments", NULL);
+
+	if (remove_filter(session, filter) < 0)
+		return g_dbus_create_error(message,
+				ERROR_INF ".InvalidArguments", "InvalidFilter");
+
+	return dbus_message_new_method_return(message);
+}
+
+static DBusMessage *pbap_get_filters(DBusConnection *connection,
+					DBusMessage *message, void *user_data)
+{
+	struct session_data *session = user_data;
+	struct pbap_data *pbapdata = session->pbapdata;
+	gchar **filters = NULL;
+	gint size;
+	DBusMessage *reply;
+
+	filters = get_filters(pbapdata->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);
+
+	g_strfreev(filters);
+	return reply;
+}
+
+static DBusMessage *pbap_list_all_filters(DBusConnection *connection,
+					DBusMessage *message, void *user_data)
+{
+	gchar **filters = NULL;
+	gint size;
+	DBusMessage *reply;
+
+	filters = get_filters(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 GDBusMethodTable pbap_methods[] = {
 	{ "Select",	"ss",	"",	pbap_select },
 	{ "PullAll",	"",	"s",	pbap_pull_all,
@@ -743,6 +932,10 @@ static GDBusMethodTable pbap_methods[] = {
 					G_DBUS_METHOD_FLAG_ASYNC },
 	{ "SetFormat",	"s",	"",	pbap_set_format },
 	{ "SetOrder",	"s",	"",	pbap_set_order },
+	{ "AddFilter",	"s",	"",	pbap_add_filter },
+	{ "RemoveFilter",	"s",	"",	pbap_remove_filter },
+	{ "GetFilters",	"",	"as",	pbap_get_filters },
+	{ "ListAllFilters", "",	"as",	pbap_list_all_filters },
 	{ }
 };