aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--filter/ChangeLog11
-rw-r--r--filter/filter-driver.c297
-rw-r--r--filter/filter-xml.c63
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) {