diff options
Diffstat (limited to 'filter/filter-driver.c')
-rw-r--r-- | filter/filter-driver.c | 297 |
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; } |