+
+ if (dbus_flags & MODEST_DBUS_SEARCH_BODY) {
+ search.flags |= MODEST_SEARCH_BODY;
+ search.body = query;
+ }
+
+ if (sd_v > 0) {
+ search.flags |= MODEST_SEARCH_BEFORE;
+ search.start_date = start_date;
+ }
+
+ if (ed_v > 0) {
+ search.flags |= MODEST_SEARCH_AFTER;
+ search.end_date = end_date;
+ }
+
+ if (size_v > 0) {
+ search.flags |= MODEST_SEARCH_SIZE;
+ search.minsize = size_v;
+ }
+
+#ifdef MODEST_HAVE_OGS
+ search.flags |= MODEST_SEARCH_USE_OGS;
+ g_debug ("%s: Starting search for %s", __FUNCTION__, search.query);
+#endif
+
+ /* Note that this currently gets folders and messages from the servers,
+ * which can take a long time. libmodest_dbus_client_search() can timeout,
+ * reporting no results, if this takes a long time: */
+ hits = modest_search_all_accounts (&search);
+
+ reply = dbus_message_new_method_return (message);
+
+ search_result_to_message (reply, hits);
+
+ if (reply == NULL) {
+ g_warning ("%s: Could not create reply.", __FUNCTION__);
+ }
+
+ if (reply) {
+ dbus_uint32_t serial = 0;
+ dbus_connection_send (con, reply, &serial);
+ dbus_connection_flush (con);
+ dbus_message_unref (reply);
+ }
+
+ g_list_free (hits);
+}
+
+
+/* A complex D-Bus type (like a struct),
+ * used to return various information about a folder.
+ */
+#define GET_FOLDERS_RESULT_DBUS_TYPE \
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING \
+ DBUS_TYPE_STRING_AS_STRING /* Folder Name */ \
+ DBUS_TYPE_STRING_AS_STRING /* Folder URI */ \
+ DBUS_STRUCT_END_CHAR_AS_STRING
+
+static DBusMessage *
+get_folders_result_to_message (DBusMessage *reply,
+ GList *folder_ids)
+{
+ DBusMessageIter iter;
+ dbus_message_iter_init_append (reply, &iter);
+
+ DBusMessageIter array_iter;
+ dbus_message_iter_open_container (&iter,
+ DBUS_TYPE_ARRAY,
+ GET_FOLDERS_RESULT_DBUS_TYPE,
+ &array_iter);
+
+ GList *list_iter = folder_ids;
+ for (list_iter = folder_ids; list_iter; list_iter = list_iter->next) {
+
+ const gchar *folder_name = (const gchar*)list_iter->data;
+ if (folder_name) {
+ /* g_debug ("DEBUG: %s: Adding folder: %s", __FUNCTION__, folder_name); */
+
+ DBusMessageIter struct_iter;
+ dbus_message_iter_open_container (&array_iter,
+ DBUS_TYPE_STRUCT,
+ NULL,
+ &struct_iter);
+
+ /* name: */
+ dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING,
+ &folder_name); /* The string will be copied. */
+
+ /* URI: This is maybe not needed by osso-global-search: */
+ const gchar *folder_uri = "TODO:unimplemented";
+ dbus_message_iter_append_basic (&struct_iter,
+ DBUS_TYPE_STRING,
+ &folder_uri); /* The string will be copied. */
+
+ dbus_message_iter_close_container (&array_iter,
+ &struct_iter);
+ }
+ }
+
+ dbus_message_iter_close_container (&iter, &array_iter);
+
+ return reply;
+}
+
+static void
+add_single_folder_to_list (TnyFolder *folder, GList** list)
+{
+ if (!folder)
+ return;
+
+ if (TNY_IS_MERGE_FOLDER (folder)) {
+ const gchar * folder_name;
+ /* Ignore these because their IDs ares
+ * a) not always unique or sensible.
+ * b) not human-readable, and currently need a human-readable
+ * ID here, because the osso-email-interface API does not allow
+ * us to return both an ID and a display name.
+ *
+ * This is actually the merged outbox folder.
+ * We could hack our D-Bus API to understand "outbox" as the merged outboxes,
+ * but that seems unwise. murrayc.
+ */
+ folder_name = tny_folder_get_name (folder);
+ if (folder_name && !strcmp (folder_name, "Outbox")) {
+ *list = g_list_append(*list, g_strdup ("MAND:outbox"));
+ }
+ return;
+ }
+
+ /* Add this folder to the list: */
+ /*
+ const gchar * folder_name = tny_folder_get_name (folder);
+ if (folder_name)
+ *list = g_list_append(*list, g_strdup (folder_name));
+ else {
+ */
+ /* osso-global-search only uses one string,
+ * so ID is the only thing that could possibly identify a folder.
+ * TODO: osso-global search should probably be changed to
+ * take an ID and a Name.
+ */
+ const gchar * id = tny_folder_get_id (folder);
+ if (id && strlen(id)) {
+ const gchar *prefix = NULL;
+ TnyFolderType folder_type;
+
+ /* dbus global search api expects a prefix identifying the type of
+ * folder here. Mandatory folders should have MAND: prefix, and
+ * other user created folders should have USER: prefix
+ */
+ folder_type = modest_tny_folder_guess_folder_type (folder);
+ switch (folder_type) {
+ case TNY_FOLDER_TYPE_INBOX:
+ prefix = "MY:";
+ break;
+ case TNY_FOLDER_TYPE_OUTBOX:
+ case TNY_FOLDER_TYPE_DRAFTS:
+ case TNY_FOLDER_TYPE_SENT:
+ case TNY_FOLDER_TYPE_ARCHIVE:
+ prefix = "MAND:";
+ break;
+ case TNY_FOLDER_TYPE_INVALID:
+ g_warning ("%s: BUG: TNY_FOLDER_TYPE_INVALID", __FUNCTION__);
+ return; /* don't add it */
+ default:
+ prefix = "USER:";
+
+ }
+
+
+ *list = g_list_append(*list, g_strdup_printf ("%s%s", prefix, id));
+ }
+}
+
+static void
+add_folders_to_list (TnyFolderStore *folder_store, GList** list)
+{
+ if (!folder_store)
+ return;
+
+ /* Add this folder to the list: */
+ if (TNY_IS_FOLDER (folder_store)) {
+ add_single_folder_to_list (TNY_FOLDER (folder_store), list);
+ }
+
+ /* Recurse into child folders: */
+
+ /* Get the folders list: */
+ /*
+ TnyFolderStoreQuery *query = tny_folder_store_query_new ();
+ tny_folder_store_query_add_item (query, NULL,
+ TNY_FOLDER_STORE_QUERY_OPTION_SUBSCRIBED);
+ */
+ TnyList *all_folders = tny_simple_list_new ();
+ tny_folder_store_get_folders (folder_store,
+ all_folders,
+ NULL /* query */,
+ NULL /* error */);
+
+ TnyIterator *iter = tny_list_create_iterator (all_folders);
+ while (!tny_iterator_is_done (iter)) {
+
+ /* Do not recurse, because the osso-global-search UI specification
+ * does not seem to want the sub-folders, though that spec seems to
+ * be generally unsuitable for Modest.
+ */
+ TnyFolder *folder = TNY_FOLDER (tny_iterator_get_current (iter));
+ if (folder) {
+ add_single_folder_to_list (TNY_FOLDER (folder), list);
+
+ #if 0
+ if (TNY_IS_FOLDER_STORE (folder))
+ add_folders_to_list (TNY_FOLDER_STORE (folder), list);
+ else {
+ add_single_folder_to_list (TNY_FOLDER (folder), list);
+ }
+ #endif
+
+ /* tny_iterator_get_current() gave us a reference. */
+ g_object_unref (folder);
+ }
+
+ tny_iterator_next (iter);
+ }
+ g_object_unref (G_OBJECT (iter));
+}
+
+
+/* return >1 for a special folder, 0 for a user-folder */
+static gint
+get_rank (const gchar *folder)
+{
+ if (strcmp (folder, "INBOX") == 0)
+ return 1;
+ if (strcmp (folder, modest_local_folder_info_get_type_name(TNY_FOLDER_TYPE_SENT)) == 0)
+ return 2;
+ if (strcmp (folder, modest_local_folder_info_get_type_name(TNY_FOLDER_TYPE_DRAFTS)) == 0)
+ return 3;
+ if (strcmp (folder, modest_local_folder_info_get_type_name(TNY_FOLDER_TYPE_OUTBOX)) == 0)
+ return 4;
+ return 0;
+}
+
+static gint
+folder_name_compare_func (const gchar* folder1, const gchar* folder2)
+{
+ gint r1 = get_rank (folder1);
+ gint r2 = get_rank (folder2);
+
+ if (r1 > 0 && r2 > 0)
+ return r1 - r2;
+ if (r1 > 0 && r2 == 0)
+ return -1;
+ if (r1 == 0 && r2 > 0)
+ return 1;