diff options
-rw-r--r-- | filter/ChangeLog | 11 | ||||
-rw-r--r-- | filter/filter-driver.c | 297 | ||||
-rw-r--r-- | filter/filter-xml.c | 63 |
3 files changed, 276 insertions, 95 deletions
diff --git a/filter/ChangeLog b/filter/ChangeLog index 7eec85d5ee..0c0e7b097b 100644 --- a/filter/ChangeLog +++ b/filter/ChangeLog @@ -1,3 +1,14 @@ +2000-03-04 NotZed <NotZed@HelixCode.com> + + * filter-driver.c (main): Actually implement filtering, at least, + from Inbox. Copy messages to folder (in the same store only, so + far), delete, and stop processing are implemented, and the logic + to handle default processing. + + * filter-xml.c (load_optionvalue): Fix up a bug where we lost the + name of the arg (ouch). + * filter-xml.c: Wrapped printf's in debug macros. + 2000-03-02 NotZed <NotZed@HelixCode.com> * filter-druid.c (object_destroy): Disconnect the list signal, so 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; } diff --git a/filter/filter-xml.c b/filter/filter-xml.c index 83bfe06131..b25b1b77af 100644 --- a/filter/filter-xml.c +++ b/filter/filter-xml.c @@ -13,6 +13,8 @@ #include "filter-arg-types.h" #include "filter-xml.h" +#define d(x) + struct token_tab { char *name; enum filter_xml_token token; @@ -74,10 +76,10 @@ detokenise(int token) static xmlNodePtr find_node(xmlNodePtr start, char *name) { - printf("trying to find node '%s'\n", name); + d(printf("trying to find node '%s'\n", name)); while (start && strcmp(start->name, name)) start = start->next; - printf("node = %p\n", start); + d(printf("node = %p\n", start)); return start; } @@ -87,11 +89,11 @@ find_node_attr(xmlNodePtr start, char *name, char *attrname, char *attrvalue) xmlNodePtr node; char *s; - printf("looking for node named %s with attribute %s=%s\n", name, attrname, attrvalue); + d(printf("looking for node named %s with attribute %s=%s\n", name, attrname, attrvalue)); while ( start && (start = find_node(start, name)) ) { s = xmlGetProp(start, attrname); - printf(" comparing '%s' to '%s'\n", s, attrvalue); + d(printf(" comparing '%s' to '%s'\n", s, attrvalue)); if (s && !strcmp(s, attrvalue)) break; start = start->next; @@ -116,9 +118,9 @@ load_desc(xmlNodePtr node, int type, int vartype, char *varname) desc->type = type; desc->vartype = vartype; desc->varname = varname?g_strdup(varname):0; - printf(" **** node name = %s var name = %s var type = %s\n", node->name, varname, detokenise(vartype)); + d(printf(" **** node name = %s var name = %s var type = %s\n", node->name, varname, detokenise(vartype))); list = g_list_append(list, desc); - printf("appending '%s'\n", node->content); + d(printf("appending '%s'\n", node->content)); newtype = type; newvartype = -1; newvarname = NULL; @@ -129,7 +131,7 @@ load_desc(xmlNodePtr node, int type, int vartype, char *varname) } n = node->childs; while (n) { - printf("adding child '%s'\n", n->name); + d(printf("adding child '%s'\n", n->name)); list = g_list_concat(list, load_desc(n, newtype, newvartype, newvarname)); n = n->next; } @@ -157,7 +159,7 @@ filter_load_ruleset(xmlDocPtr doc) ruletype = tokenise(xmlGetProp(ruleset, "type")); - printf("ruleset, name = %s\n", ruleset->name); + d(printf("ruleset, name = %s\n", ruleset->name)); while (rule) { @@ -166,24 +168,24 @@ filter_load_ruleset(xmlDocPtr doc) r->type = ruletype; r->name = xmlGetProp(rule, "name"); - printf(" rule, name = %s\n", r->name); + d(printf(" rule, name = %s\n", r->name)); while (n) { type = tokenise(n->name); - printf(" n, name = %s\n", n->name); - printf(" ncontent = %s\n", n->content); - printf(" childs = %p\n", n->childs); + d(printf(" n, name = %s\n", n->name)); + d(printf(" ncontent = %s\n", n->content)); + d(printf(" childs = %p\n", n->childs)); if (n->childs) { - printf(" childs content = %s\n", n->childs->content); + d(printf(" childs content = %s\n", n->childs->content)); } switch(type) { case FILTER_XML_CODE: r->code = xmlNodeGetContent(n); break; case FILTER_XML_DESC: - printf(" ** loading description\n"); + d(printf(" ** loading description\n")); r->description = load_desc(n->childs, type, -1, NULL); - printf(" ** done loading description\n"); + d(printf(" ** done loading description\n")); break; default: printf("warning, unknown token encountered\n"); @@ -203,14 +205,14 @@ filter_load_ruleset(xmlDocPtr doc) int filter_find_rule(struct filter_rule *a, char *name) { - printf("finding, is %s = %s?\n", a->name, name); + d(printf("finding, is %s = %s?\n", a->name, name)); return strcmp(a->name, name); } int filter_find_arg(FilterArg *a, char *name) { - printf("finding, is %s = %s?\n", a->name, name); + d(printf("finding, is %s = %s?\n", a->name, name)); return strcmp(a->name, name); } @@ -221,19 +223,18 @@ load_optionvalue(struct filter_desc *desc, xmlNodePtr node) int token; int lasttoken = -2; FilterArg *arg = NULL; - char *name; - printf("creating arg entry for '%s'\n", desc->varname); + d(printf("creating arg entry for '%s'\n", desc->varname)); switch(desc->vartype) { case FILTER_XML_ADDRESS: - arg = filter_arg_address_new(name); + arg = filter_arg_address_new(desc->varname); break; case FILTER_XML_FOLDER: - arg = filter_arg_folder_new(name); + arg = filter_arg_folder_new(desc->varname); break; default: - printf("ok, maybe we're not\n"); + d(printf("ok, maybe we're not\n")); /* unknown arg type, drop it */ return NULL; } @@ -289,14 +290,14 @@ filter_load_optionset(xmlDocPtr doc, GList *rules) optionset = find_node(doc->root->childs, "optionset"); if (optionset == NULL) { printf("optionset not found\n"); - return; + return NULL; } option = find_node(optionset->childs, "option"); while (option) { o = option->childs; op = g_malloc0(sizeof(*op)); - printf("option = %s\n", o->name); - printf("option, type=%s\n", xmlGetProp(option, "type")); + d(printf("option = %s\n", o->name)); + d(printf("option, type=%s\n", xmlGetProp(option, "type"))); op->type = tokenise(xmlGetProp(option, "type")); while (o) { type = tokenise(o->name); @@ -305,7 +306,7 @@ filter_load_optionset(xmlDocPtr doc, GList *rules) lrule = g_list_find_custom(rules, xmlGetProp(o, "rule"), (GCompareFunc) filter_find_rule); if (lrule) { fr = lrule->data; - printf("found rule : %s\n", fr->name); + d(printf("found rule : %s\n", fr->name)); optionrule = g_malloc0(sizeof(*optionrule)); optionrule->rule = fr; op->options = g_list_append(op->options, optionrule); @@ -319,17 +320,20 @@ filter_load_optionset(xmlDocPtr doc, GList *rules) /* try and see if there is a setting for this value */ or = find_node_attr(o->childs, "optionvalue", "name", desc->varname); arg = load_optionvalue(desc, or); - if (arg) + if (arg) { optionrule->args = g_list_append(optionrule->args, arg); + d(printf("Adding arg %s\n", arg->name)); + } } ldesc = g_list_next(ldesc); } } else { + /* FIXME: memleak */ printf("Cannot find rule: %s\n", xmlGetProp(o, "rule")); } break; case FILTER_XML_DESC: - printf("loading option descriptiong\n"); + d(printf("loading option descriptiong\n")); op->description = load_desc(option->childs, type, -1, NULL); break; } @@ -414,8 +418,7 @@ filter_clone_optionrule_free(struct filter_optionrule *or) GList *argl; struct filter_optionrule *rule; - printf("---- free optionrule\n"); - return; + d(printf("---- free optionrule\n")); argl = or->args; while (argl) { |