aboutsummaryrefslogtreecommitdiff
path: root/libsylph/virtual.c
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2005-12-19 06:41:50 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2005-12-19 06:41:50 +0000
commitd55459c79d6ddfa0b006c5696d408a7e388cf8c8 (patch)
tree98e8ea35bfce5bc235adbc544de8aba1f754b8ac /libsylph/virtual.c
parent1ca5b9aa126b860d9198f85e44104f857513bef5 (diff)
implemented query search and virtual folder (merged from newsearch branch).
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@836 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'libsylph/virtual.c')
-rw-r--r--libsylph/virtual.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/libsylph/virtual.c b/libsylph/virtual.c
new file mode 100644
index 00000000..897a7070
--- /dev/null
+++ b/libsylph/virtual.c
@@ -0,0 +1,297 @@
+/*
+ * LibSylph -- E-Mail client library
+ * Copyright (C) 1999-2005 Hiroyuki Yamamoto
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "defs.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#undef MEASURE_TIME
+
+#include "folder.h"
+#include "virtual.h"
+#include "procmsg.h"
+#include "procheader.h"
+#include "filter.h"
+#include "utils.h"
+
+typedef struct _VirtualSearchInfo VirtualSearchInfo;
+
+struct _VirtualSearchInfo {
+ FilterRule *rule;
+ GSList *mlist;
+};
+
+static void virtual_folder_init (Folder *folder,
+ const gchar *name,
+ const gchar *path);
+
+static GSList *virtual_search_folder (FilterRule *rule,
+ FolderItem *item);
+static gboolean virtual_search_recursive_func
+ (GNode *node,
+ gpointer data);
+
+static Folder *virtual_folder_new (const gchar *name,
+ const gchar *path);
+static void virtual_folder_destroy (Folder *folder);
+
+static GSList *virtual_get_msg_list (Folder *folder,
+ FolderItem *item,
+ gboolean use_cache);
+static gchar *virtual_fetch_msg (Folder *folder,
+ FolderItem *item,
+ gint num);
+static MsgInfo *virtual_get_msginfo (Folder *folder,
+ FolderItem *item,
+ gint num);
+static gint virtual_close (Folder *folder,
+ FolderItem *item);
+
+static gint virtual_scan_folder (Folder *folder,
+ FolderItem *item);
+
+static FolderClass virtual_class =
+{
+ F_VIRTUAL,
+
+ virtual_folder_new,
+ virtual_folder_destroy,
+
+ NULL,
+ NULL,
+
+ virtual_get_msg_list,
+ virtual_fetch_msg,
+ virtual_get_msginfo,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ virtual_close,
+ virtual_scan_folder,
+
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+
+FolderClass *virtual_get_class(void)
+{
+ return &virtual_class;
+}
+
+static Folder *virtual_folder_new(const gchar *name, const gchar *path)
+{
+ Folder *folder;
+
+ folder = (Folder *)g_new0(VirtualFolder, 1);
+ virtual_folder_init(folder, name, path);
+
+ return folder;
+}
+
+static void virtual_folder_destroy(Folder *folder)
+{
+ folder_local_folder_destroy(LOCAL_FOLDER(folder));
+}
+
+static void virtual_folder_init(Folder *folder, const gchar *name,
+ const gchar *path)
+{
+ folder->klass = virtual_get_class();
+ folder_local_folder_init(folder, name, path);
+}
+
+static GSList *virtual_search_folder(FilterRule *rule, FolderItem *item)
+{
+ GSList *match_list = NULL;
+ GSList *mlist;
+ GSList *cur;
+ FilterInfo fltinfo;
+ gboolean full_headers;
+
+ g_return_val_if_fail(rule != NULL, NULL);
+ g_return_val_if_fail(item != NULL, NULL);
+
+ /* prevent circular reference */
+ if (item->stype == F_VIRTUAL)
+ return NULL;
+
+ mlist = folder_item_get_msg_list(item, TRUE);
+
+ memset(&fltinfo, 0, sizeof(FilterInfo));
+
+ debug_print("start query search: %s\n", item->path ? item->path : "");
+
+ full_headers = filter_rule_requires_full_headers(rule);
+
+ for (cur = mlist; cur != NULL; cur = cur->next) {
+ MsgInfo *msginfo = (MsgInfo *)cur->data;
+ GSList *hlist;
+
+ fltinfo.flags = msginfo->flags;
+ if (full_headers) {
+ gchar *file;
+
+ file = procmsg_get_message_file(msginfo);
+ hlist = procheader_get_header_list_from_file(file);
+ g_free(file);
+ } else
+ hlist = procheader_get_header_list_from_msginfo
+ (msginfo);
+ if (!hlist)
+ continue;
+
+ if (filter_match_rule(rule, msginfo, hlist, &fltinfo)) {
+ match_list = g_slist_prepend(match_list, msginfo);
+ cur->data = NULL;
+ }
+
+ procheader_header_list_destroy(hlist);
+ }
+
+ procmsg_msg_list_free(mlist);
+
+ return g_slist_reverse(match_list);
+}
+
+static gboolean virtual_search_recursive_func(GNode *node, gpointer data)
+{
+ VirtualSearchInfo *info = (VirtualSearchInfo *)data;
+ FolderItem *item;
+ GSList *mlist;
+
+ g_return_val_if_fail(node->data != NULL, FALSE);
+
+ item = FOLDER_ITEM(node->data);
+
+ if (!item->path)
+ return FALSE;
+
+ mlist = virtual_search_folder(info->rule, item);
+ info->mlist = g_slist_concat(info->mlist, mlist);
+
+ return FALSE;
+}
+
+static GSList *virtual_get_msg_list(Folder *folder, FolderItem *item,
+ gboolean use_cache)
+{
+ GSList *mlist = NULL;
+ GSList *flist;
+ GSList *cur;
+ FilterRule *rule;
+ gchar *rule_file;
+ gchar *path;
+ FolderItem *target;
+ gint new = 0, unread = 0, total = 0;
+
+ g_return_val_if_fail(item != NULL, NULL);
+ g_return_val_if_fail(item->stype == F_VIRTUAL, NULL);
+
+ path = folder_item_get_path(item);
+ rule_file = g_strconcat(path, G_DIR_SEPARATOR_S, "filter.xml", NULL);
+ flist = filter_read_file(rule_file);
+ g_free(rule_file);
+
+ g_free(path);
+
+ if (!flist) {
+ g_warning("filter rule not found\n");
+ return NULL;
+ }
+
+ rule = (FilterRule *)flist->data;
+ target = folder_find_item_from_identifier(rule->target_folder);
+
+ if (!target || target == item) {
+ g_warning("invalid target folder\n");
+ goto finish;
+ }
+
+ if (rule->recursive) {
+ VirtualSearchInfo info;
+
+ info.rule = rule;
+ info.mlist = NULL;
+ g_node_traverse(target->node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
+ virtual_search_recursive_func, &info);
+ mlist = info.mlist;
+ } else
+ mlist = virtual_search_folder(rule, target);
+
+ for (cur = mlist; cur != NULL; cur = cur->next) {
+ MsgInfo *msginfo = (MsgInfo *)cur->data;
+
+ if (MSG_IS_NEW(msginfo->flags))
+ ++new;
+ if (MSG_IS_UNREAD(msginfo->flags))
+ ++unread;
+ ++total;
+ }
+
+ item->new = new;
+ item->unread = unread;
+ item->total = total;
+ item->updated = TRUE;
+
+finish:
+ filter_rule_list_free(flist);
+ return mlist;
+}
+
+static gchar *virtual_fetch_msg(Folder *folder, FolderItem *item, gint num)
+{
+ return NULL;
+}
+
+static MsgInfo *virtual_get_msginfo(Folder *folder, FolderItem *item, gint num)
+{
+ return NULL;
+}
+
+static gint virtual_close(Folder *folder, FolderItem *item)
+{
+ return 0;
+}
+
+static gint virtual_scan_folder(Folder *folder, FolderItem *item)
+{
+ /* do search */
+ return 0;
+}