aboutsummaryrefslogtreecommitdiffstats
path: root/filter/filter-driver.c
diff options
context:
space:
mode:
authorNotZed <NotZed@HelixCode.com>2000-03-05 11:36:37 +0800
committerMichael Zucci <zucchi@src.gnome.org>2000-03-05 11:36:37 +0800
commit2485f10196f6611d28d428ff0f1b9a5ac9fe755e (patch)
treed232ef17603fc2fc2e3b05772efc72dce7bad4d0 /filter/filter-driver.c
parent48e373b1565b810bcf76642d9fc6c96f3a26a0b0 (diff)
downloadgsoc2013-evolution-2485f10196f6611d28d428ff0f1b9a5ac9fe755e.tar
gsoc2013-evolution-2485f10196f6611d28d428ff0f1b9a5ac9fe755e.tar.gz
gsoc2013-evolution-2485f10196f6611d28d428ff0f1b9a5ac9fe755e.tar.bz2
gsoc2013-evolution-2485f10196f6611d28d428ff0f1b9a5ac9fe755e.tar.lz
gsoc2013-evolution-2485f10196f6611d28d428ff0f1b9a5ac9fe755e.tar.xz
gsoc2013-evolution-2485f10196f6611d28d428ff0f1b9a5ac9fe755e.tar.zst
gsoc2013-evolution-2485f10196f6611d28d428ff0f1b9a5ac9fe755e.zip
Actually implement filtering, at least, from Inbox. Copy messages to
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. svn path=/trunk/; revision=2054
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;
}