Skip to contentSkip to conversation

MAP Tracker: Fix folder and path handling

PATCH In review Bartosz Szatkowski 2 participants 11 messages Sep 2, 2011 – Sep 27, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/8 MAP Tracker: Fix folder and path handling

---
 plugins/messages-tracker.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)
plugins/messages-tracker.c +7 -4
index 43321f6..eebfca3 100644
@@ -124,13 +124,13 @@ static void create_folder_tree()
 {
 	struct message_folder *parent, *child;
 
-	folder_tree = create_folder("/", NULL);
+	folder_tree = create_folder("/", "FILTER (!BOUND(?msg))");
 
-	parent = create_folder("telecom", NULL);
+	parent = create_folder("telecom", "FILTER (!BOUND(?msg))");
 	folder_tree->subfolders = g_slist_append(folder_tree->subfolders,
 								parent);
 
-	child = create_folder("msg", NULL);
+	child = create_folder("msg", "FILTER (!BOUND(?msg))");
 	parent->subfolders = g_slist_append(parent->subfolders, child);
 
 	parent = child;
@@ -217,7 +217,10 @@ int messages_set_folder(void *s, const char *name, gboolean cdup)
 									NULL);
 	g_free(tmp);
 
-	newabs = g_build_filename("/", newrel, NULL);
+	if (newrel[0] != '/')
+		newabs = g_build_filename("/", newrel, NULL);
+	else
+		newabs = g_strdup(newrel);
 
 	session->folder = get_folder(newabs);
 	if (session->folder == NULL) {
Signature · 1 line
1.7.4.1
#1 lore raw

PATCH 2/8 MAP Tracker: Fix memory issue in folder listing

---
 plugins/messages-tracker.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
plugins/messages-tracker.c +3 -2
index eebfca3..218a016 100644
@@ -40,7 +40,7 @@ struct message_folder {
 struct session {
 	char *cwd;
 	struct message_folder *folder;
-	const char *name;
+	char *name;
 	uint16_t max;
 	uint16_t offset;
 	void *user_data;
@@ -279,6 +279,7 @@ static gboolean async_get_folder_listing(void *s) {
 							session->user_data);
 
 	g_free(path);
+	g_free(session->name);
 
 	return FALSE;
 }
@@ -289,7 +290,7 @@ int messages_get_folder_listing(void *s, const char *name,
 					void *user_data)
 {
 	struct session *session = s;
-	session->name = name;
+	session->name = g_strdup(name);
 	session->max = max;
 	session->offset = offset;
 	session->folder_list_cb = callback;
Signature · 1 line
1.7.4.1
#2 lore raw

PATCH 3/8 MAP Tracker: Add support for DBus connection

In reply to Bartosz Szatkowski
---
 plugins/messages-tracker.c |   32 ++++++++++++++++++++++++++++++++
 1 files changed, 32 insertions(+), 0 deletions(-)
plugins/messages-tracker.c +32 -0
index 218a016..efcd007 100644
@@ -28,7 +28,9 @@
 #include <errno.h>
 #include <glib.h>
 #include <string.h>
+#include <gdbus.h>
 
+#include "log.h"
 #include "messages.h"
 
 struct message_folder {
@@ -49,6 +51,7 @@ struct session {
 };
 
 static struct message_folder *folder_tree = NULL;
+static DBusConnection *session_connection = NULL;
 
 static struct message_folder *get_folder(const char *folder)
 {
@@ -148,8 +151,37 @@ static void create_folder_tree()
 	parent->subfolders = g_slist_append(parent->subfolders, child);
 }
 
+static DBusConnection *dbus_get_connection(DBusBusType type)
+{
+	DBusError err;
+	DBusConnection *tmp;
+
+	dbus_error_init(&err);
+
+	tmp = dbus_bus_get(type, &err);
+
+	if (dbus_error_is_set(&err))
+		error("Connection Error (%s)", err.message);
+
+	if (!tmp)
+		error("Error when getting on bus");
+
+	dbus_error_free(&err);
+
+	return tmp;
+}
+
 int messages_init(void)
 {
+	DBusError err;
+	dbus_error_init(&err);
+
+	if (session_connection == NULL)
+		session_connection = dbus_get_connection(DBUS_BUS_SESSION);
+
+	if (!session_connection)
+		return -1;
+
 	create_folder_tree();
 
 	return 0;
Signature · 1 line
1.7.4.1
#3 lore raw

Re: [PATCH obexd 3/8] MAP Tracker: Add support for DBus connection

Hi Bartosz,

Quoted 3 lines · Bartosz Szatkowski
---
 plugins/messages-tracker.c |   32 ++++++++++++++++++++++++++++++++
 1 files changed, 32 insertions(+), 0 deletions(-)

I think you might be breaking some record for "number of issues per lines of code" with this patch. If you're not already doing internal patch reviews you should probably consider starting this practice.

Quoted 9 lines
plugins/messages-tracker.c +9 -0
+static DBusConnection *dbus_get_connection(DBusBusType type)
+{
+	DBusError err;
+	DBusConnection *tmp;
+
+	dbus_error_init(&err);
+
+	tmp = dbus_bus_get(type, &err);
+

plugins/messages-tracker.c static void create_folder_tree() · line 172

Quoted 10 lines
plugins/messages-tracker.c +10 -0
+	if (dbus_error_is_set(&err))
+		error("Connection Error (%s)", err.message);
+
+	if (!tmp)
+		error("Error when getting on bus");
+
+	dbus_error_free(&err);
+
+	return tmp;
+}

- Just get rid of this helper function and call dbus_bus_get() directly in messages_init

- Avoid variables with generic names like tmp. Instead call it e.g. conn. I saw this elsewhere in your patches too -- please fix those.

- Your error handling is messed up. You should only call dbus_error_free when you know that dbus_error_is_set is true. Also, if you check for the DBusError you shouldn't need to check for NULL.

Review

Quoted 4 lines

int messages_init(void)
{

(quoted diff) +2 -0
+	DBusError err;
+	dbus_error_init(&err);

What's the purpose of err? All you do with it is call dbus_error_init. It's not used anywhere later in this function.

In its simplest form all you would have needed is:

	if (session_bus == NULL)
		session_bus = dbus_but_get(DBUS_BUS_SESSION, NULL);

	if (session_bus == NULL) {
		error("Unable to connect to the session bus");
		return -1;
	}

Is it valid behavior for messages_init to be called multiple times? If not then the first NULL-check isn't really needed (at most you could have an assert there).

plugins/messages-tracker.c static void create_folder_tree() · line 184

Quoted 6 lines
plugins/messages-tracker.c +6 -0
+	if (session_connection == NULL)
+		session_connection = dbus_get_connection(DBUS_BUS_SESSION);
+
+	if (!session_connection)
+		return -1;
+

Either check for NULL with == or with ! but don't mix them. I know we have inconsistencies within the source tree but try to at least be consistent within your own code.

Also, you're introducing a memory leak: you should call dbus_connection_unref and set session_bus to NULL in the messages_exit function.

Johan

#4 lore raw

PATCH 4/8 MAP Tracker Add basic support for messages listing

In reply to Bartosz Szatkowski
---
 plugins/messages-tracker.c |  447 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 438 insertions(+), 9 deletions(-)
plugins/messages-tracker.c +438 -9
index efcd007..96a180e 100644
@@ -33,6 +33,81 @@
 #include "log.h"
 #include "messages.h"
 
+#define TRACKER_SERVICE "org.freedesktop.Tracker1"
+#define TRACKER_RESOURCES_PATH "/org/freedesktop/Tracker1/Resources"
+#define TRACKER_RESOURCES_INTERFACE "org.freedesktop.Tracker1.Resources"
+
+#define QUERY_RESPONSE_SIZE 13
+#define MESSAGE_HANDLE_SIZE 16
+#define MESSAGE_HANDLE_PREFIX_LEN 8
+
+/*
+ * As stated in MAP errata bmessage-body-content-length-property should be
+ * length of: "BEGIN:MSG<CRLF>" + <message content> + "END:MSG<CRLF>"
+ */
+#define BMESSAGE_BASE_LEN (9 + 2 + 2 + 7 + 2)
+
+#define MESSAGE_HANDLE 0
+#define MESSAGE_SUBJECT 1
+#define MESSAGE_SDATE 2
+#define MESSAGE_RDATE 3
+#define MESSAGE_FROM_N 4
+#define MESSAGE_FROM_LASTN 5
+#define MESSAGE_FROM_PHONE 6
+#define MESSAGE_TO_N 7
+#define MESSAGE_TO_LASTN 8
+#define MESSAGE_TO_PHONE 9
+#define MESSAGE_READ 10
+#define MESSAGE_SENT 11
+#define MESSAGE_CONTENT 12
+
+#define LIST_MESSAGES_QUERY						\
+"SELECT "								\
+"?msg "									\
+"nmo:messageSubject(?msg) "						\
+"nmo:sentDate(?msg) "							\
+"nmo:receivedDate(?msg) "						\
+"nco:nameGiven(?from_c) "						\
+"nco:nameFamily(?from_c) "						\
+"nco:phoneNumber(?from_phone) "						\
+"nco:nameGiven(?to_c) "							\
+"nco:nameFamily(?to_c) "						\
+"nco:phoneNumber(?to_phone) "						\
+"nmo:isRead(?msg) "							\
+"nmo:isSent(?msg) "							\
+"nie:plainTextContent(?msg) "						\
+"WHERE { "								\
+	"?msg a nmo:SMSMessage . "					\
+	"%s "								\
+	"%s "								\
+	"OPTIONAL { "							\
+		"?msg nmo:from ?from . "				\
+		"?from nco:hasPhoneNumber ?from_phone . "		\
+		"?from_phone maemo:localPhoneNumber ?from_lphone . "	\
+		"OPTIONAL { "						\
+			"?from_c a nco:PersonContact . "		\
+			"OPTIONAL {?from_c nco:hasPhoneNumber ?phone .} "\
+			"OPTIONAL {?from_c nco:hasAffiliation ?af . "	\
+				"?af nco:hasPhoneNumber ?phone . } "	\
+			"?phone maemo:localPhoneNumber ?from_lphone . "	\
+		"} "							\
+	"} "								\
+	"OPTIONAL { "							\
+		"?msg nmo:to ?to . "					\
+		"?to nco:hasPhoneNumber ?to_phone . "			\
+		"?to_phone maemo:localPhoneNumber ?to_lphone . "	\
+		"OPTIONAL { "						\
+			"?to_c a nco:PersonContact . "			\
+			"OPTIONAL {?to_c nco:hasPhoneNumber ?phone1 .} "\
+			"OPTIONAL {?to_c nco:hasAffiliation ?af . "	\
+				"?af nco:hasPhoneNumber ?phone1 . } "	\
+			"?phone1 maemo:localPhoneNumber ?to_lphone "	\
+		"} "							\
+	"} "								\
+"} ORDER BY DESC(nmo:sentDate(?msg)) "
+
+typedef void (*reply_list_foreach_cb)(const char **reply, void *user_data);
+
 struct message_folder {
 	char *name;
 	GSList *subfolders;
@@ -45,14 +120,183 @@ struct session {
 	char *name;
 	uint16_t max;
 	uint16_t offset;
+	uint16_t size;
 	void *user_data;
-	void (*folder_list_cb)(void *session, int err, uint16_t size,
-					const char *name, void *user_data);
+	gboolean count;
+	gboolean new_message;
+	gboolean aborted;
+	reply_list_foreach_cb generate_response;
+	union {
+		messages_folder_listing_cb folder_list;
+		messages_get_messages_listing_cb messages_list;
+	} cb;
 };
 
 static struct message_folder *folder_tree = NULL;
 static DBusConnection *session_connection = NULL;
 
+static gboolean trace_call(void *data)
+{
+	DBusPendingCall *call = data;
+
+	if (dbus_pending_call_get_completed(call) == TRUE) {
+		dbus_pending_call_unref(call);
+
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static void new_call(DBusPendingCall *call)
+{
+	g_timeout_add_seconds(5, trace_call, call);
+}
+
+static void free_msg_data(struct messages_message *msg)
+{
+	g_free(msg->handle);
+	g_free(msg->subject);
+	g_free(msg->datetime);
+	g_free(msg->sender_name);
+	g_free(msg->sender_addressing);
+	g_free(msg->replyto_addressing);
+	g_free(msg->recipient_name);
+	g_free(msg->recipient_addressing);
+	g_free(msg->type);
+	g_free(msg->reception_status);
+	g_free(msg->size);
+	g_free(msg->attachment_size);
+
+	g_free(msg);
+}
+
+static char **string_array_from_iter(DBusMessageIter iter, int array_len)
+{
+	DBusMessageIter sub;
+	char **result;
+	int i;
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+		return NULL;
+
+	result = g_new0(char *, array_len + 1);
+
+	dbus_message_iter_recurse(&iter, &sub);
+
+	i = 0;
+	while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+		char *arg;
+
+		if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
+			g_free(result);
+
+			return NULL;
+		}
+
+		dbus_message_iter_get_basic(&sub, &arg);
+
+		result[i++] = arg;
+
+		dbus_message_iter_next(&sub);
+	}
+
+	return result;
+}
+
+static void query_reply(DBusPendingCall *call, void *user_data)
+{
+	DBusMessage *reply = dbus_pending_call_steal_reply(call);
+	struct session *session = user_data;
+	DBusMessageIter iter, element;
+	DBusError derr;
+
+	dbus_error_init(&derr);
+	if (dbus_set_error_from_message(&derr, reply)) {
+		error("Replied with an error: %s, %s", derr.name, derr.message);
+		dbus_error_free(&derr);
+
+		goto done;
+	}
+
+	dbus_message_iter_init(reply, &iter);
+
+	if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+		error("SparqlQuery reply is not an array");
+
+		goto done;
+	}
+
+	dbus_message_iter_recurse(&iter, &element);
+
+	while (dbus_message_iter_get_arg_type(&element) != DBUS_TYPE_INVALID) {
+		char **node;
+
+		if (dbus_message_iter_get_arg_type(&element)
+							!= DBUS_TYPE_ARRAY) {
+			error("Element is not an array\n");
+
+			goto done;
+		}
+
+		node = string_array_from_iter(element, QUERY_RESPONSE_SIZE);
+
+		session->generate_response((const char **) node, session);
+
+		g_free(node);
+
+		dbus_message_iter_next(&element);
+	}
+
+done:
+	session->generate_response(NULL, session);
+
+	dbus_message_unref(reply);
+}
+
+static DBusPendingCall *query_tracker(char *query, void *user_data, int *err)
+{
+	DBusPendingCall *call;
+	DBusMessage *msg;
+
+	msg = dbus_message_new_method_call(TRACKER_SERVICE,
+						TRACKER_RESOURCES_PATH,
+						TRACKER_RESOURCES_INTERFACE,
+						"SparqlQuery");
+	if (msg == NULL) {
+		if (err)
+			*err = -EPERM;
+
+		return NULL;
+	}
+
+	dbus_message_append_args(msg, DBUS_TYPE_STRING, &query,
+							 DBUS_TYPE_INVALID);
+
+	if (dbus_connection_send_with_reply(session_connection, msg, &call,
+								-1) == FALSE) {
+		error("Could not send dbus message");
+
+		dbus_message_unref(msg);
+		if (err)
+			*err = -EPERM;
+
+		return NULL;
+	}
+
+	dbus_pending_call_set_notify(call, query_reply, user_data, NULL);
+
+	dbus_message_unref(msg);
+
+	return call;
+}
+
+static char *folder2query(const struct message_folder *folder,
+							const char *query)
+{
+	return g_strdup_printf(query, folder->query, "");
+}
+
 static struct message_folder *get_folder(const char *folder)
 {
 	GSList *folders = folder_tree->subfolders;
@@ -151,6 +395,24 @@ static void create_folder_tree()
 	parent->subfolders = g_slist_append(parent->subfolders, child);
 }
 
+static char *merge_names(const char *name, const char *lastname)
+{
+	char *tmp = NULL;
+
+	if (strlen(lastname) != 0) {
+		if (strlen(name) == 0)
+			tmp = g_strdup(lastname);
+		else
+			tmp = g_strdup_printf("%s %s", name, lastname);
+
+	} else if (strlen(name) != 0)
+		tmp = g_strdup(name);
+	else
+		tmp = g_strdup("");
+
+	return tmp;
+}
+
 static DBusConnection *dbus_get_connection(DBusBusType type)
 {
 	DBusError err;
@@ -171,6 +433,120 @@ static DBusConnection *dbus_get_connection(DBusBusType type)
 	return tmp;
 }
 
+static struct messages_message *pull_message_data(const char **reply)
+{
+	struct messages_message *data = g_new0(struct messages_message, 1);
+
+	data->handle = g_strdup(reply[MESSAGE_HANDLE]
+						+ MESSAGE_HANDLE_PREFIX_LEN);
+
+	if (strlen(reply[MESSAGE_SUBJECT]) != 0)
+		data->subject = g_strdup(reply[MESSAGE_SUBJECT]);
+	else
+		data->subject = g_strdup(reply[MESSAGE_CONTENT]);
+
+	data->mask |= PMASK_SUBJECT;
+
+	if (strlen(reply[MESSAGE_SDATE]) != 0) {
+		char **date = g_strsplit_set(reply[MESSAGE_SDATE], ":-Z", -1);
+
+		data->datetime = g_strjoinv(NULL, date);
+		g_strfreev(date);
+	} else if (strlen(reply[MESSAGE_RDATE]) != 0) {
+		char **date = g_strsplit_set(reply[MESSAGE_RDATE], ":-Z", -1);
+
+		data->datetime = g_strjoinv(NULL, date);
+		g_strfreev(date);
+	} else {
+		data->datetime = g_strdup("");
+	}
+
+	data->mask |= PMASK_DATETIME;
+
+	data->sender_name = merge_names(reply[MESSAGE_FROM_N],
+					reply[MESSAGE_FROM_LASTN]);
+	data->mask |= PMASK_SENDER_NAME;
+
+	data->sender_addressing = g_strdup(reply[MESSAGE_FROM_PHONE]);
+	data->mask |= PMASK_SENDER_ADDRESSING;
+
+	data->recipient_name = merge_names(reply[MESSAGE_TO_N],
+						reply[MESSAGE_TO_LASTN]);
+	data->mask |= PMASK_RECIPIENT_NAME;
+
+	data->recipient_addressing = g_strdup(reply[MESSAGE_TO_PHONE]);
+	data->mask |= PMASK_RECIPIENT_ADDRESSING;
+
+	data->type = g_strdup("SMS_GSM");
+	data->mask |= PMASK_TYPE;
+
+	data->size = g_strdup_printf("%d", strlen(reply[MESSAGE_CONTENT]) +
+					BMESSAGE_BASE_LEN);
+	data->mask |= PMASK_SIZE;
+
+	data->text = TRUE;
+	data->mask |= PMASK_TEXT;
+
+	data->reception_status = g_strdup("complete");
+	data->mask |= PMASK_RECEPTION_STATUS;
+
+	data->attachment_size = g_strdup("0");
+	data->mask |= PMASK_ATTACHMENT_SIZE;
+
+	data->priority = FALSE;
+	data->mask |= PMASK_PRIORITY;
+
+	data->read = g_strcmp0(reply[MESSAGE_READ], "true") == 0 ? TRUE : FALSE;
+	data->mask |= PMASK_READ;
+
+	data->sent = g_strcmp0(reply[MESSAGE_SENT], "true") == 0 ? TRUE : FALSE;
+	data->mask |= PMASK_SENT;
+
+	data->protect = FALSE;
+	data->mask |= PMASK_PROTECTED;
+
+	return data;
+}
+
+static void get_messages_listing_resp(const char **reply, void *user_data)
+{
+	struct session *session = user_data;
+	struct messages_message *msg_data;
+
+	DBG("reply %p", reply);
+
+	if (reply == NULL)
+		goto done;
+
+	if (session->aborted)
+		return;
+
+	msg_data = pull_message_data(reply);
+
+	session->size++;
+
+	if (!msg_data->read)
+			session->new_message = TRUE;
+
+	if (session->count == TRUE) {
+		free_msg_data(msg_data);
+		return;
+	}
+
+	if (session->size > session->offset)
+		session->cb.messages_list(session, -EAGAIN, 1,
+						session->new_message, msg_data,
+						session->user_data);
+
+	free_msg_data(msg_data);
+	return;
+
+done:
+	session->cb.messages_list(session, 0, session->size,
+						session->new_message, NULL,
+						session->user_data);
+}
+
 int messages_init(void)
 {
 	DBusError err;
@@ -302,12 +678,12 @@ static gboolean async_get_folder_listing(void *s) {
 		struct message_folder *dir_data = dir->data;
 
 		if (count == FALSE && session->offset <= folder_count)
-			session->folder_list_cb(session, -EAGAIN, 0,
+			session->cb.folder_list(session, -EAGAIN, 1,
 					dir_data->name, session->user_data);
 	}
 
  done:
-	session->folder_list_cb(session, 0, folder_count, NULL,
+	session->cb.folder_list(session, 0, folder_count, NULL,
 							session->user_data);
 
 	g_free(path);
@@ -325,7 +701,7 @@ int messages_get_folder_listing(void *s, const char *name,
 	session->name = g_strdup(name);
 	session->max = max;
 	session->offset = offset;
-	session->folder_list_cb = callback;
+	session->cb.folder_list = callback;
 	session->user_data = user_data;
 
 	g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, async_get_folder_listing,
@@ -334,14 +710,64 @@ int messages_get_folder_listing(void *s, const char *name,
 	return 0;
 }
 
-int messages_get_messages_listing(void *session,
-				const char *name,
+int messages_get_messages_listing(void *s, const char *name,
 				uint16_t max, uint16_t offset,
 				const struct messages_filter *filter,
 				messages_get_messages_listing_cb callback,
 				void *user_data)
 {
-	return -EINVAL;
+	struct session *session = s;
+	char *path, *query;
+	struct message_folder *folder = NULL;
+	DBusPendingCall *call;
+	int err = 0;
+
+	if (name == NULL || strlen(name) == 0) {
+		path = g_strdup(session->cwd);
+
+		folder = session->folder;
+		if (folder == NULL)
+			folder = get_folder(path);
+	} else {
+		if (strchr(name, '/') != NULL)
+			return -EBADR;
+
+		path = g_build_filename(session->cwd, name, NULL);
+		folder = get_folder(path);
+	}
+
+	g_free(path);
+
+	if (folder == NULL)
+		return -ENOENT;
+
+	query = folder2query(folder, LIST_MESSAGES_QUERY);
+	if (query == NULL)
+		return -ENOENT;
+
+	session->generate_response = get_messages_listing_resp;
+	session->cb.messages_list = callback;
+	session->offset = offset;
+	session->max = max;
+	session->user_data = user_data;
+	session->new_message = FALSE;
+	session->count = FALSE;
+	session->size = 0;
+	session->aborted = FALSE;
+
+	if (max == 0) {
+		session->max = 0xffff;
+		session->offset = 0;
+		session->count = TRUE;
+	}
+
+	call = query_tracker(query, session, &err);
+	if (err == 0)
+		new_call(call);
+
+	g_free(query);
+
+	return err;
 }
 
 int messages_get_message(void *session,
@@ -353,6 +779,9 @@ int messages_get_message(void *session,
 	return -EINVAL;
 }
 
-void messages_abort(void *session)
+void messages_abort(void *s)
 {
+	struct session *session = s;
+
+	session->aborted = TRUE;
 }
Signature · 1 line
1.7.4.1
#5 lore raw

PATCH 5/8 MAP Tracker Add filter support in messages listing

In reply to Bartosz Szatkowski
---
 plugins/messages-tracker.c |  102 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 101 insertions(+), 1 deletions(-)
plugins/messages-tracker.c +101 -1
index 96a180e..8624381 100644
@@ -126,6 +126,7 @@ struct session {
 	gboolean new_message;
 	gboolean aborted;
 	reply_list_foreach_cb generate_response;
+	struct messages_filter *filter;
 	union {
 		messages_folder_listing_cb folder_list;
 		messages_get_messages_listing_cb messages_list;
@@ -171,6 +172,22 @@ static void free_msg_data(struct messages_message *msg)
 	g_free(msg);
 }
 
+static struct messages_filter *copy_messages_filter(
+					const struct messages_filter *orig)
+{
+	struct messages_filter *filter = g_new0(struct messages_filter, 1);
+	filter->parameter_mask = orig->parameter_mask;
+	filter->type = orig->type;
+	filter->period_begin = g_strdup(orig->period_begin);
+	filter->period_end = g_strdup(orig->period_end);
+	filter->read_status = orig->read_status;
+	filter->recipient = g_strdup(orig->recipient);
+	filter->originator = g_strdup(orig->originator);
+	filter->priority = orig->priority;
+
+	return filter;
+}
+
 static char **string_array_from_iter(DBusMessageIter iter, int array_len)
 {
 	DBusMessageIter sub;
@@ -433,6 +450,81 @@ static DBusConnection *dbus_get_connection(DBusBusType type)
 	return tmp;
 }
 
+static gboolean filter_message(struct messages_message *message,
+						struct messages_filter *filter)
+{
+	if (filter->type != 0) {
+		if (g_strcmp0(message->type, "SMS_GSM") == 0 &&
+				(filter->type & 0x01))
+			return FALSE;
+
+		if (g_strcmp0(message->type, "SMS_CDMA") == 0 &&
+				(filter->type & 0x02))
+			return FALSE;
+
+		if (g_strcmp0(message->type, "SMS_EMAIL") == 0 &&
+				(filter->type & 0x04))
+			return FALSE;
+
+		if (g_strcmp0(message->type, "SMS_MMS") == 0 &&
+				(filter->type & 0x08))
+			return FALSE;
+	}
+
+	if (filter->read_status != 0) {
+		if (filter->read_status == 0x01 && message->read != FALSE)
+			return FALSE;
+
+		if (filter->read_status == 0x02 && message->read != TRUE)
+			return FALSE;
+	}
+
+	if (filter->priority != 0) {
+		if (filter->priority == 0x01 && message->priority == FALSE)
+			return FALSE;
+
+		if (filter->priority == 0x02 && message->priority == TRUE)
+			return FALSE;
+	}
+
+	if (filter->period_begin != NULL &&
+			g_strcmp0(filter->period_begin, message->datetime) > 0)
+		return FALSE;
+
+	if (filter->period_end != NULL &&
+			g_strcmp0(filter->period_end, message->datetime) < 0)
+		return FALSE;
+
+	if (filter->originator != NULL) {
+		char *orig = g_strdup_printf("*%s*", filter->originator);
+
+		if (g_pattern_match_simple(orig,
+					message->sender_addressing) == FALSE &&
+				g_pattern_match_simple(orig,
+					message->sender_name) == FALSE) {
+			g_free(orig);
+			return FALSE;
+		}
+		g_free(orig);
+	}
+
+	if (filter->recipient != NULL) {
+		char *recip = g_strdup_printf("*%s*", filter->recipient);
+
+		if (g_pattern_match_simple(recip,
+					message->recipient_addressing) == FALSE
+				&& g_pattern_match_simple(recip,
+					message->recipient_name) == FALSE) {
+			g_free(recip);
+			return FALSE;
+		}
+
+		g_free(recip);
+	}
+
+	return TRUE;
+}
+
 static struct messages_message *pull_message_data(const char **reply)
 {
 	struct messages_message *data = g_new0(struct messages_message, 1);
@@ -533,7 +625,8 @@ static void get_messages_listing_resp(const char **reply, void *user_data)
 		return;
 	}
 
-	if (session->size > session->offset)
+	if (session->size > session->offset &&
+				filter_message(msg_data, session->filter))
 		session->cb.messages_list(session, -EAGAIN, 1,
 						session->new_message, msg_data,
 						session->user_data);
@@ -545,6 +638,12 @@ done:
 	session->cb.messages_list(session, 0, session->size,
 						session->new_message, NULL,
 						session->user_data);
+
+	g_free(session->filter->period_begin);
+	g_free(session->filter->period_end);
+	g_free(session->filter->originator);
+	g_free(session->filter->recipient);
+	g_free(session->filter);
 }
 
 int messages_init(void)
@@ -745,6 +844,7 @@ int messages_get_messages_listing(void *s, const char *name,
 	if (query == NULL)
 		return -ENOENT;
 
+	session->filter = copy_messages_filter(filter);
 	session->generate_response = get_messages_listing_resp;
 	session->cb.messages_list = callback;
 	session->offset = offset;
Signature · 1 line
1.7.4.1
#6 lore raw

PATCH 6/8 MAP Tracker: Add support for pulling messages

In reply to Bartosz Szatkowski
---
 Makefile.am                |    3 +-
 plugins/bmsg.c             |  322 ++++++++++++++++++++++++++++++++++++++++++++
 plugins/bmsg.h             |   86 ++++++++++++
 plugins/messages-tracker.c |  171 ++++++++++++++++++++++--
 4 files changed, 569 insertions(+), 13 deletions(-)
 create mode 100644 plugins/bmsg.c
 create mode 100644 plugins/bmsg.h
Makefile.am +2 -1
index 374fa1d..9cf3d02 100644
@@ -66,7 +66,8 @@ builtin_sources += plugins/pbap.c plugins/phonebook.h \
 			plugins/vcard.h plugins/vcard.c
 
 builtin_modules += mas
-builtin_sources += plugins/mas.c plugins/messages.h
+builtin_sources += plugins/mas.c plugins/messages.h \
+			   plugins/bmsg.h plugins/bmsg.c
 
 builtin_modules += irmc
 builtin_sources += plugins/irmc.c
plugins/bmsg.c new file +322 -0

322 lines not on this page · raw message

plugins/bmsg.h new file +86 -0

86 lines not on this page · raw message

plugins/messages-tracker.c +159 -12

223 lines not on this page · raw message

Signature · 1 line
1.7.4.1
#7 lore raw

PATCH 6/8 MAP Tracker: Add support for pulling messages

---
 Makefile.am                |    3 +-
 plugins/bmsg.c             |  322 ++++++++++++++++++++++++++++++++++++++++++++
 plugins/bmsg.h             |   86 ++++++++++++
 plugins/messages-tracker.c |  171 ++++++++++++++++++++++--
 4 files changed, 569 insertions(+), 13 deletions(-)
 create mode 100644 plugins/bmsg.c
 create mode 100644 plugins/bmsg.h
Makefile.am +2 -1
index 374fa1d..9cf3d02 100644
@@ -66,7 +66,8 @@ builtin_sources += plugins/pbap.c plugins/phonebook.h \
 			plugins/vcard.h plugins/vcard.c
 
 builtin_modules += mas
-builtin_sources += plugins/mas.c plugins/messages.h
+builtin_sources += plugins/mas.c plugins/messages.h \
+			   plugins/bmsg.h plugins/bmsg.c
 
 builtin_modules += irmc
 builtin_sources += plugins/irmc.c
plugins/bmsg.c new file +322 -0

322 lines not on this page · raw message

plugins/bmsg.h new file +86 -0

86 lines not on this page · raw message

plugins/messages-tracker.c +159 -12

223 lines not on this page · raw message

Signature · 1 line
1.7.6.1
#8 lore raw

PATCH 7/8 MAP Tracker: Add abort support in folder listing

In reply to Bartosz Szatkowski
---
 plugins/messages-tracker.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)
plugins/messages-tracker.c +7 -1
index f00ab6d..29f3ccd 100644
@@ -869,6 +869,9 @@ static gboolean async_get_folder_listing(void *s) {
 	if (session->name && strchr(session->name, '/') != NULL)
 		goto done;
 
+	if (session->aborted)
+		goto aborted;
+
 	path = g_build_filename(session->cwd, session->name, NULL);
 
 	if (path == NULL || strlen(path) == 0)
@@ -895,11 +898,13 @@ static gboolean async_get_folder_listing(void *s) {
 					dir_data->name, session->user_data);
 	}
 
- done:
+done:
 	session->cb.folder_list(session, 0, folder_count, NULL,
 							session->user_data);
 
 	g_free(path);
+
+aborted:
 	g_free(session->name);
 
 	return FALSE;
@@ -916,6 +921,7 @@ int messages_get_folder_listing(void *s, const char *name,
 	session->offset = offset;
 	session->cb.folder_list = callback;
 	session->user_data = user_data;
+	session->aborted = FALSE;
 
 	g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, async_get_folder_listing,
 						session, NULL);
Signature · 1 line
1.7.4.1
#9 lore raw

PATCH 8/8 MAP Tracker: Refactor session struct

In reply to Bartosz Szatkowski

Session struct grown to rather large size, and it become necessary to reset some flags and counter for each request. After refactorization there is one struct exclusive for each request and it is freed after request is completed.

---
 plugins/messages-tracker.c |  154 ++++++++++++++++++++++++++------------------
 1 files changed, 90 insertions(+), 64 deletions(-)
plugins/messages-tracker.c +90 -64
index 29f3ccd..ada4a42 100644
@@ -113,9 +113,7 @@ struct message_folder {
 	char *query;
 };
 
-struct session {
-	char *cwd;
-	struct message_folder *folder;
+struct request {
 	char *name;
 	uint16_t max;
 	uint16_t offset;
@@ -134,6 +132,14 @@ struct session {
 	} cb;
 };
 
+struct session {
+	char *cwd;
+	struct message_folder *folder;
+	gboolean aborted;
+	void *event_user_data;
+	struct request *request;
+};
+
 static struct message_folder *folder_tree = NULL;
 static DBusConnection *session_connection = NULL;
 
@@ -280,7 +286,7 @@ static void query_reply(DBusPendingCall *call, void *user_data)
 		node = string_array_from_iter(element, QUERY_RESPONSE_SIZE);
 
 		if (node != NULL)
-			session->generate_response((const char **) node,
+			session->request->generate_response((const char **) node,
 								session);
 
 		g_free(node);
@@ -289,7 +295,7 @@ static void query_reply(DBusPendingCall *call, void *user_data)
 	}
 
 done:
-	session->generate_response(NULL, session);
+	session->request->generate_response(NULL, session);
 
 	dbus_message_unref(reply);
 }
@@ -659,6 +665,7 @@ static struct messages_message *pull_message_data(const char **reply)
 static void get_messages_listing_resp(const char **reply, void *user_data)
 {
 	struct session *session = user_data;
+	struct request *request = session->request;
 	struct messages_message *msg_data;
 
 	DBG("reply %p", reply);
@@ -667,44 +674,48 @@ static void get_messages_listing_resp(const char **reply, void *user_data)
 		goto done;
 
 	if (session->aborted)
-		return;
+		goto aborted;
 
 	msg_data = pull_message_data(reply);
 
-	session->size++;
+	request->size++;
 
 	if (!msg_data->read)
-			session->new_message = TRUE;
+			request->new_message = TRUE;
 
-	if (session->count == TRUE) {
+	if (request->count == TRUE) {
 		free_msg_data(msg_data);
 		return;
 	}
 
-	if (session->size > session->offset &&
-				filter_message(msg_data, session->filter))
-		session->cb.messages_list(session, -EAGAIN, 1,
-						session->new_message, msg_data,
-						session->user_data);
+	if (request->size > request->offset && filter_message(msg_data,
+							request->filter))
+		request->cb.messages_list(session, -EAGAIN, 1,
+						request->new_message, msg_data,
+						request->user_data);
 
 	free_msg_data(msg_data);
 	return;
 
 done:
-	session->cb.messages_list(session, 0, session->size,
-						session->new_message, NULL,
-						session->user_data);
-
-	g_free(session->filter->period_begin);
-	g_free(session->filter->period_end);
-	g_free(session->filter->originator);
-	g_free(session->filter->recipient);
-	g_free(session->filter);
+	request->cb.messages_list(session, 0, request->size,
+						request->new_message, NULL,
+						request->user_data);
+
+aborted:
+	g_free(request->filter->period_begin);
+	g_free(request->filter->period_end);
+	g_free(request->filter->originator);
+	g_free(request->filter->recipient);
+	g_free(request->filter);
+
+	g_free(request);
 }
 
 static void get_message_resp(const char **reply, void *s)
 {
 	struct session *session = s;
+	struct request *request = session->request;
 	struct messages_message *msg_data;
 	struct bmsg *bmsg;
 	char *final_bmsg, *status, *folder, *handle;
@@ -738,26 +749,27 @@ static void get_message_resp(const char **reply, void *s)
 
 	final_bmsg = bmsg_text(bmsg);
 
-	session->cb.message(session, 0, FALSE, final_bmsg, session->user_data);
+	request->cb.message(session, 0, FALSE, final_bmsg, request->user_data);
 
 	bmsg_destroy(bmsg);
 	g_free(folder);
 	g_free(final_bmsg);
 
-	session->count++;
+	request->count++;
 
 	return;
 
 done:
-	if (session->count == 0)
+	if (request->count == 0)
 		err = -ENOENT;
 	else
 		err = 0;
 
-	session->cb.message(session, err, FALSE, NULL, session->user_data);
+	request->cb.message(session, err, FALSE, NULL, request->user_data);
 
 aborted:
-	g_free(session->name);
+	g_free(request->name);
+	g_free(request);
 }
 
 int messages_init(void)
@@ -860,19 +872,20 @@ int messages_set_folder(void *s, const char *name, gboolean cdup)
 
 static gboolean async_get_folder_listing(void *s) {
 	struct session *session = s;
+	struct request *request = session->request;
 	gboolean count = FALSE;
 	int folder_count = 0;
 	char *path = NULL;
 	struct message_folder *folder;
 	GSList *dir;
 
-	if (session->name && strchr(session->name, '/') != NULL)
-		goto done;
-
 	if (session->aborted)
 		goto aborted;
 
-	path = g_build_filename(session->cwd, session->name, NULL);
+	if (request->name && strchr(request->name, '/') != NULL)
+		goto done;
+
+	path = g_build_filename(session->cwd, request->name, NULL);
 
 	if (path == NULL || strlen(path) == 0)
 		goto done;
@@ -882,30 +895,32 @@ static gboolean async_get_folder_listing(void *s) {
 	if (folder == NULL)
 		goto done;
 
-	if (session->max == 0) {
-		session->max = 0xffff;
-		session->offset = 0;
+	if (request->max == 0) {
+		request->max = 0xffff;
+		request->offset = 0;
 		count = TRUE;
 	}
 
 	for (dir = folder->subfolders; dir &&
-				(folder_count - session->offset) < session->max;
+				(folder_count - request->offset) < request->max;
 				folder_count++, dir = g_slist_next(dir)) {
 		struct message_folder *dir_data = dir->data;
 
-		if (count == FALSE && session->offset <= folder_count)
-			session->cb.folder_list(session, -EAGAIN, 1,
-					dir_data->name, session->user_data);
+		if (count == FALSE && request->offset <= folder_count)
+			request->cb.folder_list(session, -EAGAIN, 1,
+							dir_data->name,
+							request->user_data);
 	}
 
 done:
-	session->cb.folder_list(session, 0, folder_count, NULL,
-							session->user_data);
+	request->cb.folder_list(session, 0, folder_count, NULL,
+							request->user_data);
 
 	g_free(path);
 
 aborted:
-	g_free(session->name);
+	g_free(request->name);
+	g_free(request);
 
 	return FALSE;
 }
@@ -916,12 +931,16 @@ int messages_get_folder_listing(void *s, const char *name,
 					void *user_data)
 {
 	struct session *session = s;
-	session->name = g_strdup(name);
-	session->max = max;
-	session->offset = offset;
-	session->cb.folder_list = callback;
-	session->user_data = user_data;
+	struct request *request = g_new0(struct request, 1);
+
+	request->name = g_strdup(name);
+	request->max = max;
+	request->offset = offset;
+	request->cb.folder_list = callback;
+	request->user_data = user_data;
+
 	session->aborted = FALSE;
+	session->request = request;
 
 	g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, async_get_folder_listing,
 						session, NULL);
@@ -936,6 +955,7 @@ int messages_get_messages_listing(void *s, const char *name,
 				void *user_data)
 {
 	struct session *session = s;
+	struct request *request;
 	char *path, *query;
 	struct message_folder *folder = NULL;
 	DBusPendingCall *call;
@@ -964,21 +984,22 @@ int messages_get_messages_listing(void *s, const char *name,
 	if (query == NULL)
 		return -ENOENT;
 
-	session->filter = copy_messages_filter(filter);
-	session->generate_response = get_messages_listing_resp;
-	session->cb.messages_list = callback;
-	session->offset = offset;
-	session->max = max;
-	session->user_data = user_data;
-	session->new_message = FALSE;
-	session->count = FALSE;
-	session->size = 0;
+	request = g_new0(struct request, 1);
+
+	request->filter = copy_messages_filter(filter);
+	request->generate_response = get_messages_listing_resp;
+	request->cb.messages_list = callback;
+	request->offset = offset;
+	request->max = max;
+	request->user_data = user_data;
+
 	session->aborted = FALSE;
+	session->request = request;
 
 	if (max == 0) {
-		session->max = 0xffff;
-		session->offset = 0;
-		session->count = TRUE;
+		request->max = 0xffff;
+		request->offset = 0;
+		request->count = TRUE;
 	}
 
 	call = query_tracker(query, session, &err);
@@ -994,6 +1015,7 @@ int messages_get_message(void *s, const char *h, unsigned long flags,
 				messages_get_message_cb cb, void *user_data)
 {
 	struct session *session = s;
+	struct request *request;
 	DBusPendingCall *call;
 	int err = 0;
 	char *handle = strip_handle(h);
@@ -1013,12 +1035,16 @@ int messages_get_message(void *s, const char *h, unsigned long flags,
 		goto failed;
 	}
 
-	session->name = g_strdup(handle);
-	session->flags = flags;
-	session->cb.message = cb;
-	session->generate_response = get_message_resp;
-	session->user_data = user_data;
+	request = g_new0(struct request, 1);
+
+	request->name = g_strdup(handle);
+	request->flags = flags;
+	request->cb.message = cb;
+	request->generate_response = get_message_resp;
+	request->user_data = user_data;
+
 	session->aborted = FALSE;
+	session->request = request;
 
 	call = query_tracker(query, session, &err);
 	if (err == 0)
Signature · 1 line
1.7.4.1
#10 lore raw
In reply to Bartosz Szatkowski

Hi Bartosz,

Quoted 3 lines · Bartosz Szatkowski
---
 plugins/messages-tracker.c |   11 +++++++----
 1 files changed, 7 insertions(+), 4 deletions(-)

Patches 1 and 2 have been applied. I didn't see any response to the issues raised for patch 3 (I might have forgotten though if that discussion happened on IRC).

Johan