aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--filter/ChangeLog8
-rw-r--r--filter/Makefile.am2
-rw-r--r--filter/filter-driver.c458
-rw-r--r--filter/filter-driver.h16
-rw-r--r--filter/filter-message-search.c275
-rw-r--r--filter/filter-message-search.h43
-rw-r--r--filter/filter-rule.h12
7 files changed, 525 insertions, 289 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog
index b1d0466194..0796572667 100644
--- a/filter/ChangeLog
+++ b/filter/ChangeLog
@@ -1,3 +1,11 @@
+2000-09-06 Jeffrey Stedfast <fejj@helixcode.com>
+
+ * filter-driver.c (filter_driver_run): Totally rewritten to filter
+ a single message at a time instead of filtering a folder.
+
+ * filter-message-search.c (filter_message_search): New convenience
+ function for searching a message.
+
2000-08-24 Lauris Kaplinski <lauris@helixcode.com>
* filter-folder.c: Use e_utf8 wrappers
diff --git a/filter/Makefile.am b/filter/Makefile.am
index 65927b827a..477666f4b7 100644
--- a/filter/Makefile.am
+++ b/filter/Makefile.am
@@ -42,6 +42,8 @@ libfilter_la_SOURCES = \
filter-folder.h \
filter-input.c \
filter-input.h \
+ filter-message-search.c \
+ filter-message-search.h \
filter-option.c \
filter-option.h \
filter-part.c \
diff --git a/filter/filter-driver.c b/filter/filter-driver.c
index 5cedee6e85..bc8dbd8ca2 100644
--- a/filter/filter-driver.c
+++ b/filter/filter-driver.c
@@ -22,6 +22,7 @@
*/
#include "filter-driver.h"
+#include "filter-message-search.h"
#include <glib.h>
#include <gtk/gtk.h>
@@ -32,23 +33,22 @@
#include <gnome-xml/parser.h>
#include <camel/camel.h>
-#include "mail/mail-tools.h" /*mail_tool_camel_lock_up*/
+#include "mail/mail-tools.h" /*mail_tool_camel_lock_up/down*/
#include "filter-context.h"
#include "filter-filter.h"
#include "e-util/e-sexp.h"
-#define d(x)
+#define d(x) x
/* mail-thread filter input data type */
typedef struct {
FilterDriver *driver;
- CamelFolder *source;
+ CamelMimeMessage *message;
CamelFolder *inbox;
enum _filter_source_t sourcetype;
gboolean self_destruct;
gpointer unhook_func;
gpointer unhook_data;
- gchar *path_to_unlink;
} filter_mail_input_t;
/* mail-thread filter functions */
@@ -59,27 +59,26 @@ static void cleanup_filter_mail (gpointer in_data, gpointer op_data, CamelExcept
struct _FilterDriverPrivate {
- GHashTable *globals; /* global variables */
-
+ GHashTable *globals; /* global variables */
+
FilterContext *context;
-
+
/* for callback */
FilterGetFolderFunc get_folder;
void *data;
-
+
/* run-time data */
- GHashTable *folders; /* currently open folders */
- GPtrArray *matches; /* all messages which match current rule */
- GHashTable *terminated; /* messages for which processing is terminated */
- GHashTable *processed; /* all messages that were processed in some way */
- GHashTable *copies; /* lists of folders to copy messages to */
-
- CamelFolder *source; /* temporary input folder */
-
- GList *searches; /* search results */
-
+ GHashTable *folders; /* folders that message has been copied to */
+ GHashTable *forwards; /* addresses that have been forwarded the message */
+
+ gboolean terminated; /* message processing was terminated */
+ gboolean deleted; /* message was marked for deletion */
+
+ CamelMimeMessage *message; /* input message */
+ CamelMessageInfo *info; /* message summary info */
+
CamelException *ex;
-
+
/* evaluator */
ESExp *eval;
};
@@ -93,23 +92,24 @@ static void filter_driver_finalise (GtkObject *obj);
static CamelFolder *open_folder (FilterDriver *d, const char *folder_url);
static int close_folders (FilterDriver *d);
-static ESExpResult *do_delete(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *);
-static ESExpResult *mark_forward(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *);
-static ESExpResult *mark_copy(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *);
-static ESExpResult *do_stop(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *);
-static ESExpResult *do_colour(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *);
+static ESExpResult *do_delete (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *);
+static ESExpResult *mark_forward (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *);
+static ESExpResult *mark_copy (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *);
+static ESExpResult *do_stop (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *);
+static ESExpResult *do_colour (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *);
+/* these are our filter actions - each must have a callback */
static struct {
char *name;
ESExpFunc *func;
int type; /* set to 1 if a function can perform shortcut evaluation, or
doesn't execute everything, 0 otherwise */
} symbols[] = {
- { "delete", (ESExpFunc *)do_delete, 0 },
- { "forward-to", (ESExpFunc *)mark_forward, 0 },
- { "copy-to", (ESExpFunc *)mark_copy, 0 },
- { "stop", (ESExpFunc *)do_stop, 0 },
- { "set-colour", (ESExpFunc *)do_colour, 0 },
+ { "delete", (ESExpFunc *) do_delete, 0 },
+ { "forward-to", (ESExpFunc *) mark_forward, 0 },
+ { "copy-to", (ESExpFunc *) mark_copy, 0 },
+ { "stop", (ESExpFunc *) do_stop, 0 },
+ { "set-colour", (ESExpFunc *) do_colour, 0 },
};
static GtkObjectClass *filter_driver_parent;
@@ -148,9 +148,9 @@ filter_driver_class_init (FilterDriverClass *klass)
GtkObjectClass *object_class = (GtkObjectClass *) klass;
filter_driver_parent = gtk_type_class (gtk_object_get_type ());
-
+
object_class->finalize = filter_driver_finalise;
-
+
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
}
@@ -159,9 +159,9 @@ filter_driver_init (FilterDriver *obj)
{
struct _FilterDriverPrivate *p;
int i;
-
+
p = _PRIVATE (obj) = g_malloc0 (sizeof (*p));
-
+
p->eval = e_sexp_new ();
/* Load in builtin symbols */
for (i = 0; i < sizeof (symbols) / sizeof (symbols[0]); i++) {
@@ -171,9 +171,9 @@ filter_driver_init (FilterDriver *obj)
e_sexp_add_function (p->eval, 0, symbols[i].name, symbols[i].func, obj);
}
}
-
+
p->globals = g_hash_table_new (g_str_hash, g_str_equal);
-
+
/* Will get set in filter_driver_run */
p->ex = NULL;
}
@@ -190,18 +190,14 @@ filter_driver_finalise (GtkObject *obj)
{
FilterDriver *d = (FilterDriver *) obj;
struct _FilterDriverPrivate *p = _PRIVATE (d);
-
+
g_hash_table_foreach (p->globals, free_hash_strings, d);
g_hash_table_destroy (p->globals);
-
+
gtk_object_unref (GTK_OBJECT (p->eval));
-
- /*Was set to the mail_operation_queue exception,
- * not our responsibility to free it.*/
- /*camel_exception_free (p->ex);*/
g_free (p);
-
+
((GtkObjectClass *)(filter_driver_parent))->finalize (GTK_OBJECT (obj));
}
@@ -220,25 +216,26 @@ filter_driver_new (FilterContext *context, FilterGetFolderFunc get_folder, void
{
FilterDriver *new;
struct _FilterDriverPrivate *p;
-
+
new = FILTER_DRIVER (gtk_type_new (filter_driver_get_type ()));
- p = _PRIVATE(new);
-
+ p = _PRIVATE (new);
+
p->get_folder = get_folder;
p->data = data;
p->context = context;
- gtk_object_ref((GtkObject *)context);
-
+ gtk_object_ref (GTK_OBJECT (context));
+
return new;
}
#if 0
-void filter_driver_set_global(FilterDriver *d, const char *name, const char *value)
+void
+filter_driver_set_global (FilterDriver *d, const char *name, const char *value)
{
struct _FilterDriverPrivate *p = _PRIVATE (d);
char *oldkey, *oldvalue;
-
+
if (g_hash_table_lookup_extended (p->globals, name, (void *)&oldkey, (void *)&oldvalue)) {
g_free (oldvalue);
g_hash_table_insert (p->globals, oldkey, g_strdup (value));
@@ -252,18 +249,12 @@ static ESExpResult *
do_delete (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *driver)
{
struct _FilterDriverPrivate *p = _PRIVATE (driver);
- char *uid;
- int i;
-
- printf ("doing delete\n");
- for (i = 0; i < p->matches->len; i++) {
- uid = p->matches->pdata[i];
- printf (" %s\n", uid);
-
- mail_tool_camel_lock_up ();
- camel_folder_delete_message (p->source, uid);
- mail_tool_camel_lock_down ();
+
+ if (!p->terminated) {
+ d(fprintf (stderr, "doing delete\n"));
+ p->deleted = TRUE;
}
+
return NULL;
}
@@ -271,12 +262,12 @@ static ESExpResult *
mark_forward (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *driver)
{
struct _FilterDriverPrivate *p = _PRIVATE (driver);
- int i;
-
- printf ("marking the following messages for forwarding:\n");
- for (i = 0; i < p->matches->len; i++) {
- printf (" %s\n", (char *)p->matches->pdata[i]);
+
+ if (!p->terminated) {
+ d(fprintf (stderr, "marking message for forwarding\n"));
+ /* FIXME: do stuff here */
}
+
return NULL;
}
@@ -284,33 +275,30 @@ static ESExpResult *
mark_copy (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *driver)
{
struct _FilterDriverPrivate *p = _PRIVATE (driver);
- int i, m;
- char *uid;
-
- printf ("marking for copy\n");
- for (i = 0; i < argc; i++) {
- if (argv[i]->type == ESEXP_RES_STRING) {
- char *folder = argv[i]->value.string;
- CamelFolder *outbox;
-
- outbox = open_folder (driver, folder);
- if (outbox == NULL)
- continue;
-
- for (m = 0; m < p->matches->len; m++) {
- gpointer old_key, old_value;
-
- uid = p->matches->pdata[m];
- printf (" %s\n", uid);
-
- if (g_hash_table_lookup_extended (p->copies, uid, &old_key, &old_value))
- g_hash_table_insert (p->copies, old_key, g_list_prepend (old_value, outbox));
- else
- g_hash_table_insert (p->copies, uid, g_list_append (NULL, outbox));
+ int i;
+
+ if (!p->terminated) {
+ d(fprintf (stderr, "copying message...\n"));
+ for (i = 0; i < argc; i++) {
+ if (argv[i]->type == ESEXP_RES_STRING) {
+ /* open folders we intent to copy to */
+ char *folder = argv[i]->value.string;
+ CamelFolder *outbox;
+
+ outbox = g_hash_table_lookup (p->folders, folder);
+ if (!outbox) {
+ outbox = open_folder (driver, folder);
+ if (!outbox)
+ continue;
+
+ mail_tool_camel_lock_up ();
+ camel_folder_append_message (outbox, p->message, p->info, p->ex);
+ mail_tool_camel_lock_down ();
+ }
}
}
}
-
+
return NULL;
}
@@ -318,65 +306,61 @@ static ESExpResult *
do_stop (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *driver)
{
struct _FilterDriverPrivate *p = _PRIVATE (driver);
- char *uid;
- int i;
-
- printf ("doing stop on the following messages:\n");
- for (i = 0; i < p->matches->len; i++) {
- uid = p->matches->pdata[i];
- printf (" %s\n", uid);
- g_hash_table_insert (p->terminated, uid, GINT_TO_POINTER (1));
+
+ if (!p->terminated) {
+ d(fprintf (stderr, "terminating message processing\n"));
+ p->terminated = TRUE;
}
+
return NULL;
}
static ESExpResult *
-do_colour(struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *d)
+do_colour (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterDriver *driver)
{
- int i;
- char *uid;
- struct _FilterDriverPrivate *p = _PRIVATE(d);
-
- if (argc>0 && argv[0]->type == ESEXP_RES_STRING) {
- for (i=0 ; i<p->matches->len; i++) {
- uid = p->matches->pdata[i];
- camel_folder_set_message_user_tag(p->source, uid, "colour", argv[0]->value.string);
+ struct _FilterDriverPrivate *p = _PRIVATE (driver);
+
+ if (!p->terminated) {
+ d(fprintf (stderr, "setting colour flag\n"));
+ if (argc > 0 && argv[0]->type == ESEXP_RES_STRING) {
+ camel_tag_set (&p->info->user_tags, "colour", argv[0]->value.string);
}
}
-
+
return NULL;
}
static CamelFolder *
open_folder (FilterDriver *driver, const char *folder_url)
{
- CamelFolder *camelfolder;
struct _FilterDriverPrivate *p = _PRIVATE (driver);
-
+ CamelFolder *camelfolder;
+
/* we have a lookup table of currently open folders */
camelfolder = g_hash_table_lookup (p->folders, folder_url);
if (camelfolder)
return camelfolder;
-
- camelfolder = p->get_folder(driver, folder_url, p->data);
-
+
+ camelfolder = p->get_folder (driver, folder_url, p->data);
+
if (camelfolder) {
g_hash_table_insert (p->folders, g_strdup (folder_url), camelfolder);
mail_tool_camel_lock_up ();
camel_folder_freeze (camelfolder);
mail_tool_camel_lock_down ();
}
-
+
return camelfolder;
}
static void
close_folder (void *key, void *value, void *data)
{
+
CamelFolder *folder = value;
FilterDriver *driver = data;
struct _FilterDriverPrivate *p = _PRIVATE (driver);
-
+
g_free (key);
mail_tool_camel_lock_up ();
camel_folder_sync (folder, FALSE, p->ex);
@@ -390,11 +374,11 @@ static int
close_folders (FilterDriver *driver)
{
struct _FilterDriverPrivate *p = _PRIVATE (driver);
-
+
g_hash_table_foreach (p->folders, close_folder, driver);
g_hash_table_destroy (p->folders);
p->folders = g_hash_table_new (g_str_hash, g_str_equal);
-
+
/* FIXME: status from driver */
return 0;
}
@@ -417,27 +401,26 @@ static const mail_operation_spec op_filter_mail =
};
void
-filter_driver_run (FilterDriver *d, CamelFolder *source, CamelFolder *inbox,
- enum _filter_source_t sourcetype,
- gboolean self_destruct, gpointer unhook_func, gpointer unhook_data,
- const char *path_to_unlink)
+filter_driver_run (FilterDriver *driver, CamelMimeMessage *message, CamelFolder *inbox,
+ enum _filter_source_t sourcetype, gboolean self_destruct,
+ gpointer unhook_func, gpointer unhook_data)
{
filter_mail_input_t *input;
-
+
input = g_new (filter_mail_input_t, 1);
- input->driver = d;
- input->source = source;
+ input->driver = driver;
+ input->message = message;
input->inbox = inbox;
input->sourcetype = sourcetype;
input->self_destruct = self_destruct;
input->unhook_func = unhook_func;
input->unhook_data = unhook_data;
- input->path_to_unlink = g_strdup (path_to_unlink);
-
+
mail_operation_queue (&op_filter_mail, input, TRUE);
}
-static gchar *describe_filter_mail (gpointer in_data, gboolean gerund)
+static gchar *
+describe_filter_mail (gpointer in_data, gboolean gerund)
{
filter_mail_input_t *input = (filter_mail_input_t *) in_data;
@@ -453,26 +436,26 @@ static void
setup_filter_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
filter_mail_input_t *input = (filter_mail_input_t *) in_data;
-
+
if (!input->driver) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"Bad filter driver passed to filter_mail");
return;
}
-
- if (!CAMEL_IS_FOLDER (input->source)) {
+
+ if (!CAMEL_IS_MIME_MESSAGE (input->message)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
- "Bad source folder passed to filter_mail");
+ "Bad mime message passed to filter_mail");
return;
}
-
+
if (!CAMEL_IS_FOLDER (input->inbox)) {
camel_exception_set (ex, CAMEL_EXCEPTION_INVALID_PARAM,
"Bad Inbox passed to filter_mail");
return;
}
-
- camel_object_ref (CAMEL_OBJECT (input->source));
+
+ camel_object_ref (CAMEL_OBJECT (input->message));
camel_object_ref (CAMEL_OBJECT (input->inbox));
}
@@ -480,166 +463,96 @@ static void
do_filter_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
filter_mail_input_t *input = (filter_mail_input_t *) in_data;
- FilterDriver *d = input->driver;
- CamelFolder *source = input->source;
+ FilterDriver *driver = input->driver;
+ CamelMimeMessage *message = input->message;
CamelFolder *inbox = input->inbox;
- struct _FilterDriverPrivate *p = _PRIVATE (d);
+ struct _FilterDriverPrivate *p = _PRIVATE (driver);
ESExpResult *r;
- GString *s, *a;
- GPtrArray *all;
- char *uid;
- int i;
+ GString *fsearch, *faction;
FilterFilter *rule;
- GList *l;
-
- /* FIXME: needs to check all failure cases */
- p->source = source;
-
+
+ p->ex = camel_exception_new ();
+ p->terminated = FALSE;
+ p->deleted = FALSE;
+ p->message = message;
+ p->info = g_new0 (CamelMessageInfo, 1);
+
/* setup runtime data */
- p->folders = g_hash_table_new(g_str_hash, g_str_equal);
- p->terminated = g_hash_table_new(g_str_hash, g_str_equal);
- p->processed = g_hash_table_new(g_str_hash, g_str_equal);
- p->copies = g_hash_table_new(g_str_hash, g_str_equal);
-
+ p->folders = g_hash_table_new (g_str_hash, g_str_equal);
+
mail_tool_camel_lock_up ();
- camel_folder_freeze(inbox);
+ camel_folder_freeze (inbox);
mail_tool_camel_lock_down ();
-
- s = g_string_new("");
- a = g_string_new("");
-
+
+ fsearch = g_string_new ("");
+ faction = g_string_new ("");
+
rule = NULL;
- while ( (rule = (FilterFilter *)rule_context_next_rule((RuleContext *)p->context, (FilterRule *)rule)) ) {
-
+ while ((rule = (FilterFilter *)rule_context_next_rule ((RuleContext *)p->context, (FilterRule *)rule))) {
+ gboolean matched;
+
if (((FilterRule *)rule)->source != input->sourcetype) {
- d(printf("skipping rule %s - wrong source type (%d %d)\n", ((FilterRule *)rule)->name,
- ((FilterRule *)rule)->source, input->sourcetype));
+ d(fprintf (stderr, "skipping rule %s - wrong source type (%d %d)\n", ((FilterRule *)rule)->name,
+ ((FilterRule *)rule)->source, input->sourcetype));
continue;
}
-
- g_string_truncate(s, 0);
- g_string_truncate(a, 0);
-
- filter_rule_build_code((FilterRule *)rule, s);
- filter_filter_build_action(rule, a);
-
- d(printf("applying rule %s\n action %s\n", s->str, a->str));
-
+
+ g_string_truncate (fsearch, 0);
+ g_string_truncate (faction, 0);
+
+ filter_rule_build_code (FILTER_RULE (rule), fsearch);
+ filter_filter_build_action (rule, faction);
+
+ d(fprintf (stderr, "applying rule %s\n action %s\n", fsearch->str, faction->str));
+
mail_tool_camel_lock_up ();
- p->matches = camel_folder_search_by_expression (p->source, s->str, p->ex);
+ matched = filter_message_search (p->message, p->info, fsearch->str, p->ex);
mail_tool_camel_lock_down ();
-
- /* remove uid's for which processing is complete ... */
- for (i = 0; i < p->matches->len; i++) {
- uid = p->matches->pdata[i];
-
- /* for all matching id's, so we can work out what to default */
- if (g_hash_table_lookup (p->processed, uid) == NULL) {
- g_hash_table_insert (p->processed, uid, GINT_TO_POINTER (1));
- }
-
- if (g_hash_table_lookup (p->terminated, uid)) {
- g_ptr_array_remove_index_fast (p->matches, i);
- i--;
- }
- }
-
+
+ if (!matched)
+ continue;
+
#ifndef NO_WARNINGS
#warning "Must check expression parsed and executed properly?"
#endif
- e_sexp_input_text(p->eval, a->str, strlen(a->str));
- e_sexp_parse(p->eval);
- r = e_sexp_eval(p->eval);
- e_sexp_result_free(r);
-
- p->searches = g_list_append(p->searches, p->matches);
+ e_sexp_input_text (p->eval, faction->str, strlen (faction->str));
+ e_sexp_parse (p->eval);
+ r = e_sexp_eval (p->eval);
+ e_sexp_result_free (r);
+
+ if (p->terminated)
+ break;
}
-
- g_string_free(s, TRUE);
- g_string_free(a, TRUE);
-
- /* Do any queued copies, and make sure everything is deleted from
- * the source. If we have an inbox, anything that didn't get
- * processed otherwise goes there.
- */
- mail_tool_camel_lock_up ();
- all = camel_folder_get_uids (p->source);
- mail_tool_camel_lock_down ();
- for (i = 0; i < all->len; i++) {
- char *uid = all->pdata[i], *procuid;
- GList *copies, *tmp;
- CamelMimeMessage *mm;
- const CamelMessageInfo *info;
-
- copies = g_hash_table_lookup (p->copies, uid);
- procuid = g_hash_table_lookup (p->processed, uid);
-
+
+ g_string_free (fsearch, TRUE);
+ g_string_free (faction, TRUE);
+
+ if (!p->deleted && g_hash_table_size (p->folders) == 0) {
+ /* copy it to the default inbox */
mail_tool_camel_lock_up ();
- info = camel_folder_get_message_info (p->source, uid);
-
- if (copies || !procuid) {
- mm = camel_folder_get_message (p->source, uid, p->ex);
-
- while (copies) {
- camel_folder_append_message(copies->data, mm, info, p->ex);
- tmp = copies->next;
- g_list_free_1 (copies);
- copies = tmp;
- }
-
- if (!procuid && inbox != source) {
- printf("Applying default rule to message %s\n", uid);
- camel_folder_append_message(inbox, mm, info, p->ex);
- }
-
- camel_object_unref (CAMEL_OBJECT (mm));
- }
-
- if (inbox != source)
- camel_folder_delete_message (p->source, uid);
+ camel_folder_append_message (input->inbox, p->message, p->info, p->ex);
+
+ /* warn that inbox was changed */
+ if (input->unhook_func)
+ camel_object_unhook_event (CAMEL_OBJECT (input->inbox), "folder_changed",
+ input->unhook_func, input->unhook_data);
mail_tool_camel_lock_down ();
-
}
- mail_tool_camel_lock_up ();
- camel_folder_free_uids (p->source, all);
- if (input->unhook_func)
- camel_object_unhook_event (CAMEL_OBJECT (input->inbox), "folder_changed",
- input->unhook_func, input->unhook_data);
- mail_tool_camel_lock_down ();
-
- /* now we no longer need our keys */
- l = p->searches;
- while (l) {
- camel_folder_search_free (p->source, l->data);
- l = l->next;
- }
- g_list_free (p->searches);
- g_hash_table_destroy (p->copies);
- g_hash_table_destroy (p->processed);
- g_hash_table_destroy (p->terminated);
- close_folders (d);
+ /* close all folders that were opened for appending */
+ close_folders (driver);
g_hash_table_destroy (p->folders);
+
+ /* thaw the inbox folder */
mail_tool_camel_lock_up ();
- camel_folder_sync (source, TRUE, ex);
- if (inbox != source)
- camel_folder_sync (inbox, FALSE, ex);
camel_folder_thaw (inbox);
mail_tool_camel_lock_down ();
-
- if (input->path_to_unlink) {
- struct stat sb;
-
- if (stat (input->path_to_unlink, &sb) < 0) {
- camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
- _("Couldn't stat(2) movemail folder %s"),
- input->path_to_unlink);
- return;
- }
-
- if (sb.st_size == 0)
- unlink (input->path_to_unlink);
- }
+
+ /* transfer any exceptions over to our async exception */
+ if (camel_exception_is_set (p->ex))
+ camel_exception_xfer (ex, p->ex);
+
+ camel_exception_free (p->ex);
}
static void
@@ -647,12 +560,9 @@ cleanup_filter_mail (gpointer in_data, gpointer op_data, CamelException *ex)
{
filter_mail_input_t *input = (filter_mail_input_t *) in_data;
- camel_object_unref (CAMEL_OBJECT (input->source));
+ camel_object_unref (CAMEL_OBJECT (input->message));
camel_object_unref (CAMEL_OBJECT (input->inbox));
-
- if (input->path_to_unlink)
- g_free (input->path_to_unlink);
-
+
if (input->self_destruct)
gtk_object_unref (GTK_OBJECT (input->driver));
}
diff --git a/filter/filter-driver.h b/filter/filter-driver.h
index 984780b927..5ab4d8a8a9 100644
--- a/filter/filter-driver.h
+++ b/filter/filter-driver.h
@@ -48,21 +48,19 @@ struct _FilterDriverClass {
typedef CamelFolder * (*FilterGetFolderFunc) (FilterDriver *, const char *uri, void *data);
-guint filter_driver_get_type (void);
-FilterDriver *filter_driver_new (FilterContext *ctx, FilterGetFolderFunc fetcher, void *data);
+guint filter_driver_get_type (void);
+FilterDriver *filter_driver_new (FilterContext *ctx, FilterGetFolderFunc fetcher, void *data);
-/*
- void filter_driver_set_global(FilterDriver *, const char *name, const char *value);*/
+/*void filter_driver_set_global(FilterDriver *, const char *name, const char *value);*/
/* apply rules to a folder, unmatched messages goto inbox, if not NULL */
-void filter_driver_run(FilterDriver *d, CamelFolder *source, CamelFolder *inbox,
- enum _filter_source_t sourcetype,
- gboolean self_destruct, gpointer unhook_func, gpointer unhook_data,
- const char *path_to_unlink);
+void filter_driver_run (FilterDriver *driver, CamelMimeMessage *message, CamelFolder *inbox,
+ enum _filter_source_t sourcetype,
+ gboolean self_destruct, gpointer unhook_func, gpointer unhook_data);
#if 0
/* generate the search query/action string for a filter option */
-void filter_driver_expand_option(FilterDriver *d, GString *s, GString *action, struct filter_option *op);
+void filter_driver_expand_option (FilterDriver *d, GString *s, GString *action, struct filter_option *op);
/* get info about rules (options) */
int filter_driver_rule_count(FilterDriver *d);
diff --git a/filter/filter-message-search.c b/filter/filter-message-search.c
new file mode 100644
index 0000000000..a55a7f5c4d
--- /dev/null
+++ b/filter/filter-message-search.c
@@ -0,0 +1,275 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@helixcode.com>
+ *
+ * Copyright 2000 Helix Code, Inc. (www.helixcode.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "filter-message-search.h"
+#include <e-util/e-sexp.h>
+#include <e-util/e-util.h>
+#include <regex.h>
+
+typedef struct {
+ CamelMimeMessage *message;
+ CamelMessageInfo *info;
+ CamelException *ex;
+} FilterMessageSearch;
+
+/* ESExp callbacks */
+static ESExpResult *header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
+static ESExpResult *match_all (struct _ESExp *f, int argc, struct _ESExpTerm **argv, FilterMessageSearch *fms);
+static ESExpResult *body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
+static ESExpResult *user_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
+static ESExpResult *user_tag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
+static ESExpResult *get_sent_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
+static ESExpResult *get_received_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
+static ESExpResult *get_current_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms);
+
+
+/* builtin functions */
+static struct {
+ char *name;
+ ESExpFunc *func;
+ int type; /* set to 1 if a function can perform shortcut evaluation, or
+ doesn't execute everything, 0 otherwise */
+} symbols[] = {
+ { "match-all", (ESExpFunc *) match_all, 0 },
+ { "body-contains", (ESExpFunc *) body_contains, 0 },
+ { "header-contains", (ESExpFunc *) header_contains, 0 },
+ { "user-tag", (ESExpFunc *) user_tag, 1 },
+ { "user-flag", (ESExpFunc *) user_flag, 1 },
+ { "get-sent-date", (ESExpFunc *) get_sent_date, 1 },
+ { "get-received-date", (ESExpFunc *) get_received_date, 1 },
+ { "get-current-date", (ESExpFunc *) get_current_date, 1 }
+};
+
+static ESExpResult *
+header_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
+{
+ gboolean matched = FALSE;
+ ESExpResult *r;
+
+ if (argc == 2) {
+ char *header = (argv[0])->value.string;
+ char *match = (argv[1])->value.string;
+ const char *contents;
+
+ contents = camel_medium_get_header (CAMEL_MEDIUM (fms->message), header);
+ if (contents && e_strstrcase (contents, match))
+ matched = TRUE;
+ }
+
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = matched;
+
+ return r;
+}
+
+static ESExpResult *
+match_all (struct _ESExp *f, int argc, struct _ESExpTerm **argv, FilterMessageSearch *fms)
+{
+ /* match-all: when dealing with single messages is a no-op */
+ ESExpResult *r;
+
+ /* FIXME: is this right?? */
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = TRUE;
+
+ return r;
+}
+
+static ESExpResult *
+body_contains (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
+{
+ gboolean matched = FALSE;
+ ESExpResult *r;
+
+ if (argc > 0) {
+ CamelStream *stream;
+ GByteArray *array;
+ char *match, *body;
+ regex_t regexpat; /* regex patern */
+ regmatch_t *fltmatch;
+ gint regerr = 0;
+ size_t reglen = 0;
+ gchar *regmsg;
+
+ match = (*argv)->value.string;
+
+ array = g_byte_array_new ();
+ stream = camel_stream_mem_new_with_byte_array (array);
+ camel_data_wrapper_write_to_stream (CAMEL_DATA_WRAPPER (fms->message), stream);
+ camel_stream_reset (stream);
+ g_byte_array_append (array, "", 1);
+
+ body = array->data;
+
+ regerr = regcomp (&regexpat, match, REG_EXTENDED | REG_NEWLINE | REG_ICASE);
+ if (regerr) {
+ /* regerror gets called twice to get the full error string
+ length to do proper posix error reporting */
+ reglen = regerror (regerr, &regexpat, 0, 0);
+ regmsg = g_malloc0 (reglen + 1);
+ regerror (regerr, &regexpat, regmsg, reglen);
+ camel_exception_setv (fms->ex, CAMEL_EXCEPTION_SYSTEM,
+ "Failed to perform regex search on message body: %s",
+ regmsg);
+ g_free (regmsg);
+ regfree (&regexpat);
+ } else {
+ fltmatch = g_new0 (regmatch_t, regexpat.re_nsub);
+
+ if (!regexec (&regexpat, body, regexpat.re_nsub, fltmatch, 0))
+ matched = TRUE;
+
+ g_free (fltmatch);
+ regfree (&regexpat);
+ }
+ }
+
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = matched;
+
+ return r;
+}
+
+static ESExpResult *
+user_flag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
+{
+ ESExpResult *r;
+ gboolean truth = FALSE;
+ int i;
+
+ /* performs an OR of all words */
+ for (i = 0; i < argc && !truth; i++) {
+ if (argv[i]->type == ESEXP_RES_STRING
+ && camel_flag_get (&fms->info->user_flags, argv[i]->value.string)) {
+ truth = TRUE;
+ break;
+ }
+ }
+
+ r = e_sexp_result_new (ESEXP_RES_BOOL);
+ r->value.bool = truth;
+
+ return r;
+}
+
+static ESExpResult *
+user_tag (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
+{
+ ESExpResult *r;
+ const char *tag;
+
+ tag = camel_tag_get (&fms->info->user_tags, argv[0]->value.string);
+
+ r = e_sexp_result_new (ESEXP_RES_STRING);
+ r->value.string = g_strdup (tag ? tag : "");
+
+ return r;
+}
+
+static ESExpResult *
+get_sent_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
+{
+ ESExpResult *r;
+ const char *sent_date;
+ time_t date;
+
+ sent_date = camel_mime_message_get_sent_date (fms->message);
+ date = header_decode_date (sent_date, NULL);
+
+ r = e_sexp_result_new (ESEXP_RES_INT);
+ r->value.number = date;
+
+ return r;
+}
+
+static ESExpResult *
+get_received_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
+{
+ ESExpResult *r;
+ const char *received_date;
+ time_t date;
+
+ received_date = camel_mime_message_get_received_date (fms->message);
+ date = header_decode_date (received_date, NULL);
+
+ r = e_sexp_result_new (ESEXP_RES_INT);
+ r->value.number = date;
+
+ return r;
+}
+
+static ESExpResult *
+get_current_date (struct _ESExp *f, int argc, struct _ESExpResult **argv, FilterMessageSearch *fms)
+{
+ ESExpResult *r;
+ time_t date;
+
+ date = time (NULL);
+
+ r = e_sexp_result_new (ESEXP_RES_INT);
+ r->value.number = date;
+
+ return r;
+}
+
+gboolean
+filter_message_search (CamelMimeMessage *message, CamelMessageInfo *info, const char *expression, CamelException *ex)
+{
+ FilterMessageSearch *fms;
+ ESExp *sexp;
+ ESExpResult *result;
+ gboolean retval;
+ int i;
+
+ fms = g_new (FilterMessageSearch, 1);
+ fms->message = message;
+ fms->info = info;
+ fms->ex = ex;
+
+ sexp = e_sexp_new ();
+
+ for (i = 0; i < sizeof (symbols) / sizeof (symbols[0]); i++) {
+ if (symbols[i].type == 1) {
+ e_sexp_add_ifunction (sexp, 0, symbols[i].name,
+ (ESExpIFunc *)symbols[i].func, fms);
+ } else {
+ e_sexp_add_function (sexp, 0, symbols[i].name,
+ symbols[i].func, fms);
+ }
+ }
+
+ e_sexp_input_text (sexp, expression, strlen (expression));
+ e_sexp_parse (sexp);
+ result = e_sexp_eval (sexp);
+
+ g_free (fms);
+
+ if (result->type == ESEXP_RES_BOOL)
+ retval = result->value.bool;
+ else
+ retval = FALSE;
+
+ gtk_object_unref (GTK_OBJECT (sexp));
+ e_sexp_result_free (result);
+
+ return retval;
+}
diff --git a/filter/filter-message-search.h b/filter/filter-message-search.h
new file mode 100644
index 0000000000..ce9cc57c52
--- /dev/null
+++ b/filter/filter-message-search.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@helixcode.com>
+ *
+ * Copyright 2000 Helix Code, Inc. (www.helixcode.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef FILTER_MESSAGE_SEARCH_H
+#define FILTER_MESSAGE_SEARCH_H
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+#include <glib.h>
+#include <camel.h>
+#include <camel-mime-message.h>
+#include <camel-folder-summary.h>
+
+gboolean filter_message_search (CamelMimeMessage *message, CamelMessageInfo *info,
+ const char *expression, CamelException *ex);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* ! FILTER_MESSAGE_SEARCH_H */
diff --git a/filter/filter-rule.h b/filter/filter-rule.h
index 425d0ac350..e1d5655050 100644
--- a/filter/filter-rule.h
+++ b/filter/filter-rule.h
@@ -49,9 +49,9 @@ enum _filter_source_t {
struct _FilterRule {
GtkObject parent;
struct _FilterRulePrivate *priv;
-
+
char *name;
-
+
enum _filter_grouping_t grouping;
enum _filter_source_t source;
GList *parts;
@@ -59,15 +59,15 @@ struct _FilterRule {
struct _FilterRuleClass {
GtkObjectClass parent_class;
-
+
/* virtual methods */
xmlNodePtr (*xml_encode)(FilterRule *);
int (*xml_decode)(FilterRule *, xmlNodePtr, struct _RuleContext *);
-
+
void (*build_code)(FilterRule *, GString *out);
-
+
GtkWidget *(*get_widget)(FilterRule *fr, struct _RuleContext *f);
-
+
/* signals */
};