aboutsummaryrefslogtreecommitdiffstats
path: root/filter/filter-driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'filter/filter-driver.c')
-rw-r--r--filter/filter-driver.c297
1 files changed, 232 insertions, 65 deletions
diff --git a/filter/filter-driver.c b/filter/filter-driver.c
index eb852b3cc2..37509d0bc9 100644
--- a/filter/filter-driver.c
+++ b/filter/filter-driver.c
@@ -23,6 +23,31 @@
extern int filter_find_arg(FilterArg *a, char *name);
+struct exec_context {
+ GHashTable *globals; /* global variables */
+
+ GList *matches; /* all messages which match current rule */
+
+ GList *deleted; /* messages to be deleted */
+ GHashTable *terminated; /* messages for which processing is terminated */
+ GHashTable *processed; /* all messages that were processed in some way */
+
+ CamelSession *session;
+ CamelStore *store;
+ CamelFolder *folder; /* temporary input folder */
+ CamelException *ex;
+};
+
+/*
+
+ foreach rule
+ find matches
+
+ foreach action
+ get all matches
+
+ */
+
/*
splices ${cc} lines into a single string
*/
@@ -37,6 +62,8 @@ expand_variables(GString *out, char *source, GList *args, GHashTable *globals)
int len=0;
int ok = 0;
+ printf("expanding %s\n", source);
+
start = source;
while ( (newstart = strstr(start, "${"))
&& (end = strstr(newstart+2, "}")) ) {
@@ -47,6 +74,7 @@ expand_variables(GString *out, char *source, GList *args, GHashTable *globals)
}
memcpy(name, newstart+2, len);
name[len] = 0;
+ printf("looking for name '%s'\n", name);
argl = g_list_find_custom(args, name, (GCompareFunc) filter_find_arg);
if (argl) {
int i, count;
@@ -75,7 +103,7 @@ expand_variables(GString *out, char *source, GList *args, GHashTable *globals)
} else {
ok = 1;
tmp = g_strdup_printf("%.*s", end-start+1, start);
- printf("appending: %s\n", tmp);
+ printf("appending: '%s'\n", tmp);
g_string_append(out, tmp);
g_free(tmp);
}
@@ -90,7 +118,7 @@ expand_variables(GString *out, char *source, GList *args, GHashTable *globals)
build an expression for the filter
*/
static void
-expand_filter_option(GString *s, struct filter_option *op)
+expand_filter_option(GString *s, GString *action, struct filter_option *op)
{
GList *optionl;
FilterArg *arg;
@@ -106,25 +134,33 @@ expand_filter_option(GString *s, struct filter_option *op)
struct filter_optionrule *or = optionl->data;
if (or->rule->type == FILTER_XML_MATCH
|| or->rule->type == FILTER_XML_EXCEPT) {
+ if (or->args) {
+ arg = or->args->data;
+ if (arg) {
+ printf("arg = %s\n", arg->name);
+ }
+ }
expand_variables(s, or->rule->code, or->args, globals);
}
optionl = g_list_next(optionl);
}
g_string_append(s, ")");
-#if 0
+
+ g_string_append(action, "(begin ");
optionl = op->options;
while (optionl) {
struct filter_optionrule *or = optionl->data;
if (or->rule->type == FILTER_XML_ACTION) {
- g_string_append(s, or->rule->code);
- g_string_append(s, " ");
+ expand_variables(action, or->rule->code, or->args, globals);
+ g_string_append(action, " ");
}
optionl = g_list_next(optionl);
}
- g_string_append(s, ")))");
-#endif
+ g_string_append(action, ")");
+
printf("combined rule '%s'\n", s->str);
+ printf("combined action '%s'\n", action->str);
}
struct filter_optionrule *
@@ -144,86 +180,217 @@ find_optionrule(struct filter_option *option, char *name)
return NULL;
}
+static ESExpResult *
+do_delete(struct _ESExp *f, int argc, struct _ESExpResult **argv, struct exec_context *x)
+{
+ GList *m;
+
+ printf("doing delete\n");
+ m = x->matches;
+ while (m) {
+ printf(" %s\n", m->data);
+ x->deleted = g_list_append(x->deleted, g_strdup(m->data));
+ m = m->next;
+ }
+ return NULL;
+}
+
+static ESExpResult *
+do_forward(struct _ESExp *f, int argc, struct _ESExpResult **argv, struct exec_context *x)
+{
+ GList *m;
+
+ printf("doing forward on the following messages:\n");
+ m = x->matches;
+ while (m) {
+ printf(" %s\n", m->data);
+ m = m->next;
+ }
+ return NULL;
+}
+
+static ESExpResult *
+do_copy(struct _ESExp *f, int argc, struct _ESExpResult **argv, struct exec_context *x)
+{
+ GList *m;
+ int i;
+
+ printf("doing copy on the following messages to:");
+ for (i=0;i<argc;i++) {
+ if (argv[i]->type == ESEXP_RES_STRING) {
+ char *folder = argv[i]->value.string;
+ CamelFolder *outbox;
+
+ /* FIXME: this might have to find another store, based on
+ the folder as a url??? */
+ printf("opening outpbox %s\n", folder);
+ outbox = camel_store_get_folder (x->store, folder, x->ex);
+ if (!camel_folder_exists(outbox, x->ex)) {
+ camel_folder_create(outbox, x->ex);
+ }
+
+ camel_folder_open (outbox, FOLDER_OPEN_WRITE, x->ex);
+
+ m = x->matches;
+ while (m) {
+ CamelMimeMessage *mm;
+
+ printf("appending message %s\n", m->data);
+
+ mm = camel_folder_get_message_by_uid(x->folder, m->data, x->ex);
+ camel_folder_append_message(outbox, mm, x->ex);
+ gtk_object_unref((GtkObject *)mm);
+
+ printf(" %s\n", m->data);
+ m = m->next;
+ }
+ camel_folder_close (outbox, FALSE, x->ex);
+ }
+ }
+
+ return NULL;
+}
+
+static ESExpResult *
+do_stop(struct _ESExp *f, int argc, struct _ESExpResult **argv, struct exec_context *x)
+{
+ GList *m;
+
+ printf("doing stop on the following messages:\n");
+ m = x->matches;
+ while (m) {
+ printf(" %s\n", m->data);
+ g_hash_table_insert(x->terminated, g_strdup(m->data), (void *)1);
+ m = m->next;
+ }
+ return NULL;
+}
+
+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 *)do_forward, 0 },
+ { "copy-to", (ESExpFunc *)do_copy, 0 },
+ { "stop", (ESExpFunc *)do_stop, 0 },
+};
+
+static char *
+auth_callback(char *prompt, gboolean secret,
+ CamelService *service, char *item,
+ CamelException *ex)
+{
+ printf ("auth_callback called: %s\n", prompt);
+ return NULL;
+}
+
+static struct exec_context *
+start(void)
+{
+ struct exec_context *x;
+ char *store_url = "mbox:///tmp/evmail";
+
+ x = g_malloc0(sizeof(*x));
+
+ /* just hack up this for now */
+ x->ex = camel_exception_new ();
+ camel_provider_register_as_module ("../camel/providers/mbox/.libs/libcamelmbox.so.0");
+ x->session = camel_session_new (auth_callback);
+ x->store = camel_session_get_store (x->session, store_url, x->ex);
+ x->folder = camel_store_get_folder (x->store, "Inbox", x->ex);
+ camel_folder_open (x->folder, FOLDER_OPEN_READ, x->ex);
+ x->terminated = g_hash_table_new(g_str_hash, g_str_equal);
+ x->processed = g_hash_table_new(g_str_hash, g_str_equal);
+ return x;
+}
+
int main(int argc, char **argv)
{
ESExp *f;
ESExpResult *r;
GList *rules, *options, *options2;
- xmlDocPtr doc, out, optionset, filteroptions;
- GString *s;
+ xmlDocPtr doc, out;
+ GString *s, *a;
+ GList *all, *m;
+ struct exec_context *x;
+ int i;
+ ESExp *eval;
gnome_init("Test", "0.0", argc, argv);
-#if 0
- gdk_rgb_init ();
- gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
- gtk_widget_set_default_visual (gdk_rgb_get_visual ());
-
- create_dialogue();
-#endif
+ camel_init();
doc = xmlParseFile("filterdescription.xml");
rules = filter_load_ruleset(doc);
- options = filter_load_optionset(doc, rules);
- options2 = options;
+ options2 = filter_load_optionset(doc, rules);
+
out = xmlParseFile("saveoptions.xml");
options = filter_load_optionset(out, rules);
-#if 0
-#if 0
- option_current = options->data;
- fill_rules(list_global, rules, options->data, FILTER_XML_MATCH);
-#else
- option_current = NULL;
- fill_options(list_global, options2);
-#endif
- gtk_main();
+ x = start();
+
+ eval = e_sexp_new();
+ /* Load in builtin symbols? */
+ for(i=0;i<sizeof(symbols)/sizeof(symbols[0]);i++) {
+ if (symbols[i].type == 1) {
+ e_sexp_add_ifunction(eval, 0, symbols[i].name, (ESExpIFunc *)symbols[i].func, x);
+ } else {
+ e_sexp_add_function(eval, 0, symbols[i].name, symbols[i].func, x);
+ }
+ }
while (options) {
struct filter_option *fo = options->data;
- GList *optionrulel;
- optionrulel = fo->options;
- while (optionrulel) {
- struct filter_optionrule *or = optionrulel->data;
+ s = g_string_new("");
+ a = g_string_new("");
+ expand_filter_option(s, a, fo);
+
+ printf("searching expression %s\n", s->str);
+ x->matches = camel_folder_search_by_expression (x->folder, s->str, x->ex);
+
+ /* remove uid's for which processing is complete ... */
+ m = x->matches;
+ while (m) {
+ GList *n = m->next;
+
+ /* for all matching id's, so we can work out what to default */
+ if (g_hash_table_lookup(x->processed, m->data) == NULL) {
+ g_hash_table_insert(x->processed, g_strdup(m->data), (void *)1);
+ }
- printf("formatting rule: %s\n", or->rule->name);
+ if (g_hash_table_lookup(x->terminated, m->data)) {
+ printf("removing terminated message %s\n", m->data);
+ x->matches = g_list_remove_link(x->matches, m);
+ }
+ m = n;
+ }
- /*filter_description_text(or->rule->description, or->args);*/
- filter_description_html_write(or->rule->description, or->args, NULL, NULL);
+ printf("applying actions ... '%s'\n", a->str);
+ e_sexp_input_text(eval, a->str, strlen(a->str));
+ e_sexp_parse(eval);
+ r = e_sexp_eval(eval);
+ e_sexp_result_free(r);
- optionrulel = g_list_next(optionrulel);
- }
+ g_string_free(s, TRUE);
+ g_string_free(a, TRUE);
+
options = g_list_next(options);
}
- return 0;
-#endif
-
- s = g_string_new("");
- expand_filter_option(s, options->data);
- g_string_append(s, "");
-
- printf("total rule = '%s'\n", s->str);
-
- f = e_sexp_new();
- e_sexp_add_variable(f, 0, "sender", NULL);
- e_sexp_add_variable(f, 0, "receipient", NULL);
- e_sexp_add_variable(f, 0, "folder", NULL);
-
- /* simple functions */
- e_sexp_add_function(f, 0, "header-get", NULL, NULL);
- e_sexp_add_function(f, 0, "header-contains", NULL, NULL);
- e_sexp_add_function(f, 0, "copy-to", NULL, NULL);
-
- e_sexp_add_ifunction(f, 0, "set", NULL, NULL);
-
- /* control functions */
- e_sexp_add_ifunction(f, 0, "match-all", NULL, NULL);
- e_sexp_add_ifunction(f, 0, "match", NULL, NULL);
- e_sexp_add_ifunction(f, 0, "action", NULL, NULL);
- e_sexp_add_ifunction(f, 0, "except", NULL, NULL);
+ /* now apply 'default' rule */
+ all = camel_folder_get_uid_list(x->folder, x->ex);
+ m = all;
+ while (m) {
+ char *uid = m->data;
+ if (g_hash_table_lookup(x->processed, uid) == NULL) {
+ printf("Applying default rule to message %s\n", uid);
+ }
+ m = m->next;
+ }
+ g_list_free(all);
- e_sexp_input_text(f, s->str, strlen(s->str));
- e_sexp_parse(f);
-
+ return 0;
}