Initial revision
svn path=/trunk/; revision=1786
This commit is contained in:
4
filter/ChangeLog
Normal file
4
filter/ChangeLog
Normal file
@ -0,0 +1,4 @@
|
||||
2000-02-14 NotZed <notzed@helixcode.com>
|
||||
|
||||
* Initial import.
|
||||
|
||||
11
filter/Makefile
Normal file
11
filter/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
OBJS = filter-arg-types.o filter-arg.o filter-xml.o filter-sexp.o filter-driver.o
|
||||
SRCS = filter-arg-types.c filter-arg.c filter-xml.c filter-sexp.c filter-driver.c
|
||||
|
||||
CFLAGS = `gnome-config --cflags xml gnome gtk gtkhtml gnomeui` -g -I../camel -I .. -I../libibex
|
||||
LDFLAGS = `gnome-config --libs xml gnome gtk gtkhtml gnomeui` -L ../camel/.libs -lcamel
|
||||
|
||||
all: filter-driver
|
||||
|
||||
filter-driver: $(OBJS)
|
||||
|
||||
393
filter/filter-arg-types.c
Normal file
393
filter/filter-arg-types.c
Normal file
@ -0,0 +1,393 @@
|
||||
/*
|
||||
* Copyright (C) 2000 Helix Code Inc.
|
||||
*
|
||||
* Authors: Michael Zucchi <notzed@helixcode.com>
|
||||
*
|
||||
* Implementations of the filter-arg types.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "filter-arg-types.h"
|
||||
|
||||
/* ********************************************************************** */
|
||||
/* Address */
|
||||
/* ********************************************************************** */
|
||||
|
||||
static void filter_arg_address_class_init (FilterArgAddressClass *class);
|
||||
static void filter_arg_address_init (FilterArgAddress *gspaper);
|
||||
|
||||
static FilterArg *parent_class;
|
||||
|
||||
guint
|
||||
filter_arg_address_get_type (void)
|
||||
{
|
||||
static guint type = 0;
|
||||
|
||||
if (!type) {
|
||||
GtkTypeInfo type_info = {
|
||||
"FilterArgAddress",
|
||||
sizeof (FilterArgAddress),
|
||||
sizeof (FilterArgAddressClass),
|
||||
(GtkClassInitFunc) filter_arg_address_class_init,
|
||||
(GtkObjectInitFunc) filter_arg_address_init,
|
||||
(GtkArgSetFunc) NULL,
|
||||
(GtkArgGetFunc) NULL
|
||||
};
|
||||
|
||||
type = gtk_type_unique (filter_arg_get_type (), &type_info);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
arg_address_write_html(FilterArg *argin, GtkHTML *html, GtkHTMLStreamHandle *stream)
|
||||
{
|
||||
FilterArgAddress *arg = (FilterArgAddress *)argin;
|
||||
/* empty */
|
||||
}
|
||||
|
||||
static void
|
||||
arg_address_write_text(FilterArg *argin, GString *string)
|
||||
{
|
||||
FilterArgAddress *arg = (FilterArgAddress *)argin;
|
||||
GList *l;
|
||||
struct filter_arg_address *a;
|
||||
|
||||
l = argin->values;
|
||||
if (l == NULL) {
|
||||
g_string_append(string, "email address");
|
||||
}
|
||||
while (l) {
|
||||
a = l->data;
|
||||
g_string_append(string, a->name);
|
||||
if (l->next) {
|
||||
g_string_append(string, ", ");
|
||||
}
|
||||
l = g_list_next(l);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
arg_address_edit_values(FilterArg *arg)
|
||||
{
|
||||
printf("edit it!\n");
|
||||
}
|
||||
|
||||
static xmlNodePtr
|
||||
arg_address_values_get_xml(FilterArg *argin)
|
||||
{
|
||||
xmlNodePtr value;
|
||||
FilterArgAddress *arg = (FilterArgAddress *)argin;
|
||||
GList *l;
|
||||
struct filter_arg_address *a;
|
||||
|
||||
/* hmm, perhaps this overhead should be in FilterArg, and this function just returns the base node?? */
|
||||
value = xmlNewNode(NULL, "optionvalue");
|
||||
xmlSetProp(value, "name", argin->name);
|
||||
|
||||
l = argin->values;
|
||||
while (l) {
|
||||
xmlNodePtr cur;
|
||||
|
||||
a = l->data;
|
||||
|
||||
cur = xmlNewChild(value, NULL, "address", NULL);
|
||||
if (a->name)
|
||||
xmlSetProp(cur, "name", a->name);
|
||||
if (a->email)
|
||||
xmlSetProp(cur, "email", a->email);
|
||||
l = g_list_next(l);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void
|
||||
arg_address_values_add_xml(FilterArg *arg, xmlNodePtr node)
|
||||
{
|
||||
xmlNodePtr n;
|
||||
|
||||
n = node->childs;
|
||||
while (n) {
|
||||
if (!strcmp(n->name, "address")) {
|
||||
filter_arg_address_add(arg, xmlGetProp(n, "name"), xmlGetProp(n, "email"));
|
||||
} else {
|
||||
g_warning("Loading address from xml, wrong node encountered: %s\n", n->name);
|
||||
}
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* the search string is just the raw email address */
|
||||
static char *
|
||||
arg_address_get_value_as_string(FilterArg *argin, void *data)
|
||||
{
|
||||
FilterArgAddress *arg = (FilterArgAddress *)argin;
|
||||
struct filter_arg_address *a = (struct filter_arg_address *)data;
|
||||
|
||||
if (a->email == NULL
|
||||
|| a->email[0] == '\0') {
|
||||
if (a->name == NULL
|
||||
|| a->name[0] == '\0')
|
||||
return "";
|
||||
return a->name;
|
||||
} else
|
||||
return a->email;
|
||||
}
|
||||
|
||||
static void
|
||||
arg_address_free_value(FilterArg *arg, struct filter_arg_address *a)
|
||||
{
|
||||
g_free(a->name);
|
||||
g_free(a->email);
|
||||
g_free(a);
|
||||
}
|
||||
|
||||
static void
|
||||
filter_arg_address_class_init (FilterArgAddressClass *class)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
object_class = (GtkObjectClass *) class;
|
||||
if (parent_class == NULL)
|
||||
parent_class = gtk_type_class (gtk_object_get_type ());
|
||||
|
||||
class->parent_class.write_html = arg_address_write_html;
|
||||
class->parent_class.write_text = arg_address_write_text;
|
||||
class->parent_class.edit_values = arg_address_edit_values;
|
||||
class->parent_class.free_value = arg_address_free_value;
|
||||
|
||||
class->parent_class.values_get_xml = arg_address_values_get_xml;
|
||||
class->parent_class.values_add_xml = arg_address_values_add_xml;
|
||||
|
||||
class->parent_class.get_value_as_string = arg_address_get_value_as_string;
|
||||
}
|
||||
|
||||
static void
|
||||
filter_arg_address_init (FilterArgAddress *arg)
|
||||
{
|
||||
arg->arg.values = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* filter_arg_address_new:
|
||||
*
|
||||
* Create a new FilterArgAddress widget.
|
||||
*
|
||||
* Return value: A new FilterArgAddress widget.
|
||||
**/
|
||||
FilterArg *
|
||||
filter_arg_address_new (char *name)
|
||||
{
|
||||
FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_address_get_type ()));
|
||||
a->name = g_strdup(name);
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
filter_arg_address_add(FilterArg *arg, char *name, char *email)
|
||||
{
|
||||
struct filter_arg_address *a;
|
||||
|
||||
a = g_malloc0(sizeof(*a));
|
||||
|
||||
a->name = g_strdup(name);
|
||||
a->email = g_strdup(email);
|
||||
|
||||
filter_arg_add(arg, a);
|
||||
}
|
||||
|
||||
void
|
||||
filter_arg_address_remove(FilterArg *arg, char *name, char *email)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* ********************************************************************** */
|
||||
/* Folder */
|
||||
/* ********************************************************************** */
|
||||
|
||||
|
||||
static void filter_arg_folder_class_init (FilterArgFolderClass *class);
|
||||
static void filter_arg_folder_init (FilterArgFolder *gspaper);
|
||||
|
||||
static FilterArg *parent_class;
|
||||
|
||||
guint
|
||||
filter_arg_folder_get_type (void)
|
||||
{
|
||||
static guint type = 0;
|
||||
|
||||
if (!type) {
|
||||
GtkTypeInfo type_info = {
|
||||
"FilterArgFolder",
|
||||
sizeof (FilterArgFolder),
|
||||
sizeof (FilterArgFolderClass),
|
||||
(GtkClassInitFunc) filter_arg_folder_class_init,
|
||||
(GtkObjectInitFunc) filter_arg_folder_init,
|
||||
(GtkArgSetFunc) NULL,
|
||||
(GtkArgGetFunc) NULL
|
||||
};
|
||||
|
||||
type = gtk_type_unique (filter_arg_get_type (), &type_info);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
arg_folder_write_html(FilterArg *argin, GtkHTML *html, GtkHTMLStreamHandle *stream)
|
||||
{
|
||||
FilterArgFolder *arg = (FilterArgFolder *)argin;
|
||||
/* empty */
|
||||
}
|
||||
|
||||
static void
|
||||
arg_folder_write_text(FilterArg *argin, GString *string)
|
||||
{
|
||||
FilterArgFolder *arg = (FilterArgFolder *)argin;
|
||||
GList *l;
|
||||
char *a;
|
||||
|
||||
l = argin->values;
|
||||
if (l == NULL) {
|
||||
g_string_append(string, "folder");
|
||||
}
|
||||
while (l) {
|
||||
a = l->data;
|
||||
g_string_append(string, a);
|
||||
if (l->next) {
|
||||
g_string_append(string, ", ");
|
||||
}
|
||||
l = g_list_next(l);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
arg_folder_edit_values(FilterArg *arg)
|
||||
{
|
||||
printf("edit it!\n");
|
||||
}
|
||||
|
||||
static xmlNodePtr
|
||||
arg_folder_values_get_xml(FilterArg *argin)
|
||||
{
|
||||
xmlNodePtr value;
|
||||
FilterArgFolder *arg = (FilterArgFolder *)argin;
|
||||
GList *l;
|
||||
char *a;
|
||||
|
||||
value = xmlNewNode(NULL, "optionvalue");
|
||||
xmlSetProp(value, "name", argin->name);
|
||||
|
||||
l = argin->values;
|
||||
while (l) {
|
||||
xmlNodePtr cur;
|
||||
|
||||
a = l->data;
|
||||
|
||||
cur = xmlNewChild(value, NULL, "folder", NULL);
|
||||
if (a)
|
||||
xmlSetProp(cur, "folder", a);
|
||||
l = g_list_next(l);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void
|
||||
arg_folder_values_add_xml(FilterArg *arg, xmlNodePtr node)
|
||||
{
|
||||
xmlNodePtr n;
|
||||
|
||||
n = node->childs;
|
||||
while (n) {
|
||||
if (!strcmp(n->name, "folder")) {
|
||||
filter_arg_folder_add(arg, xmlGetProp(n, "folder"));
|
||||
} else {
|
||||
g_warning("Loading folders from xml, wrong node encountered: %s\n", n->name);
|
||||
}
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
arg_folder_get_value_as_string(FilterArg *argin, void *data)
|
||||
{
|
||||
FilterArgFolder *arg = (FilterArgFolder *)argin;
|
||||
char *a = (char *)data;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static void
|
||||
arg_folder_free_value(FilterArg *arg, void *a)
|
||||
{
|
||||
g_free(a);
|
||||
}
|
||||
|
||||
static void
|
||||
filter_arg_folder_class_init (FilterArgFolderClass *class)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
object_class = (GtkObjectClass *) class;
|
||||
if (parent_class == NULL)
|
||||
parent_class = gtk_type_class (gtk_object_get_type ());
|
||||
|
||||
class->parent_class.write_html = arg_folder_write_html;
|
||||
class->parent_class.write_text = arg_folder_write_text;
|
||||
class->parent_class.edit_values = arg_folder_edit_values;
|
||||
class->parent_class.free_value = arg_folder_free_value;
|
||||
|
||||
class->parent_class.values_get_xml = arg_folder_values_get_xml;
|
||||
class->parent_class.values_add_xml = arg_folder_values_add_xml;
|
||||
}
|
||||
|
||||
static void
|
||||
filter_arg_folder_init (FilterArgFolder *arg)
|
||||
{
|
||||
arg->arg.values = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* filter_arg_folder_new:
|
||||
*
|
||||
* Create a new FilterArgFolder widget.
|
||||
*
|
||||
* Return value: A new FilterArgFolder widget.
|
||||
**/
|
||||
FilterArg *
|
||||
filter_arg_folder_new (char *name)
|
||||
{
|
||||
FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_folder_get_type ()));
|
||||
a->name = g_strdup(name);
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
filter_arg_folder_add(FilterArg *arg, char *name)
|
||||
{
|
||||
filter_arg_add(arg, g_strdup(name));
|
||||
}
|
||||
|
||||
void
|
||||
filter_arg_folder_remove(FilterArg *arg, char *name)
|
||||
{
|
||||
/* do it */
|
||||
}
|
||||
75
filter/filter-arg-types.h
Normal file
75
filter/filter-arg-types.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2000 Helix Code Inc.
|
||||
*
|
||||
* Authors: Michael Zucchi <notzed@helixcode.com>
|
||||
*
|
||||
* Implementations of the filter-args.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _FILTER_ARG_TYPES_H
|
||||
#define _FILTER_ARG_TYPES_H
|
||||
|
||||
#include "filter-arg.h"
|
||||
|
||||
/* An Address */
|
||||
#define FILTER_ARG_ADDRESS(obj) GTK_CHECK_CAST (obj, filter_arg_address_get_type (), FilterArgAddress)
|
||||
#define FILTER_ARG_ADDRESS_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_arg_address_get_type (), FilterArgAddressClass)
|
||||
#define IS_FILTER_ARG_ADDRESS(obj) GTK_CHECK_TYPE (obj, filter_arg_address_get_type ())
|
||||
|
||||
typedef struct _FilterArgAddress FilterArgAddress;
|
||||
typedef struct _FilterArgAddressClass FilterArgAddressClass;
|
||||
|
||||
struct _FilterArgAddress {
|
||||
FilterArg arg;
|
||||
};
|
||||
|
||||
struct _FilterArgAddressClass {
|
||||
FilterArgClass parent_class;
|
||||
};
|
||||
|
||||
struct filter_arg_address {
|
||||
char *name;
|
||||
char *email;
|
||||
};
|
||||
|
||||
guint filter_arg_address_get_type (void);
|
||||
FilterArg *filter_arg_address_new (char *name);
|
||||
void filter_arg_address_add(FilterArg *, char *name, char *email);
|
||||
void filter_arg_address_remove(FilterArg *, char *name, char *email);
|
||||
|
||||
/* A Folder */
|
||||
#define FILTER_ARG_FOLDER(obj) GTK_CHECK_CAST (obj, filter_arg_folder_get_type (), FilterArgFolder)
|
||||
#define FILTER_ARG_FOLDER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_arg_folder_get_type (), FilterArgFolderClass)
|
||||
#define IS_FILTER_ARG_FOLDER(obj) GTK_CHECK_TYPE (obj, filter_arg_folder_get_type ())
|
||||
|
||||
typedef struct _FilterArgFolder FilterArgFolder;
|
||||
typedef struct _FilterArgFolderClass FilterArgFolderClass;
|
||||
|
||||
struct _FilterArgFolder {
|
||||
FilterArg arg;
|
||||
};
|
||||
|
||||
struct _FilterArgFolderClass {
|
||||
FilterArgClass parent_class;
|
||||
};
|
||||
|
||||
guint filter_arg_folder_get_type (void);
|
||||
FilterArg *filter_arg_folder_new (char *name);
|
||||
void filter_arg_folder_add(FilterArg *, char *name);
|
||||
void filter_arg_folder_remove(FilterArg *, char *name);
|
||||
|
||||
#endif /* ! _FILTER_ARG_TYPES_H */
|
||||
217
filter/filter-arg.c
Normal file
217
filter/filter-arg.c
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (C) 2000 Helix Code Inc.
|
||||
*
|
||||
* Authors: Michael Zucchi <notzed@helixcode.com>
|
||||
*
|
||||
* Abstract filter argument class.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "filter-arg.h"
|
||||
|
||||
|
||||
static void filter_arg_class_init (FilterArgClass *class);
|
||||
static void filter_arg_init (FilterArg *gspaper);
|
||||
|
||||
static GtkObjectClass *parent_class;
|
||||
|
||||
enum {
|
||||
CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
guint
|
||||
filter_arg_get_type (void)
|
||||
{
|
||||
static guint type = 0;
|
||||
|
||||
if (!type) {
|
||||
GtkTypeInfo type_info = {
|
||||
"FilterArg",
|
||||
sizeof (FilterArg),
|
||||
sizeof (FilterArgClass),
|
||||
(GtkClassInitFunc) filter_arg_class_init,
|
||||
(GtkObjectInitFunc) filter_arg_init,
|
||||
(GtkArgSetFunc) NULL,
|
||||
(GtkArgGetFunc) NULL
|
||||
};
|
||||
|
||||
type = gtk_type_unique (gtk_object_get_type (), &type_info);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
write_html_nothing(FilterArg *arg, GtkHTML *html, GtkHTMLStreamHandle *stream)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
static void
|
||||
write_text_nothing(FilterArg *arg, GString *string)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
static void
|
||||
edit_values_nothing(FilterArg *arg)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
static void
|
||||
free_value_nothing(FilterArg *arg, void *v)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_pointers(gpointer a, gpointer b)
|
||||
{
|
||||
return a==b;
|
||||
}
|
||||
|
||||
static void
|
||||
filter_arg_class_init (FilterArgClass *class)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
object_class = (GtkObjectClass *) class;
|
||||
parent_class = gtk_type_class (gtk_object_get_type ());
|
||||
|
||||
class->write_html = write_html_nothing;
|
||||
class->write_text = write_text_nothing;
|
||||
class->edit_values = edit_values_nothing;
|
||||
class->free_value = free_value_nothing;
|
||||
|
||||
signals[CHANGED] =
|
||||
gtk_signal_new ("changed",
|
||||
GTK_RUN_LAST,
|
||||
object_class->type,
|
||||
GTK_SIGNAL_OFFSET (FilterArgClass, changed),
|
||||
gtk_marshal_NONE__NONE,
|
||||
GTK_TYPE_NONE, 0);
|
||||
gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL);
|
||||
}
|
||||
|
||||
static void
|
||||
filter_arg_init (FilterArg *arg)
|
||||
{
|
||||
arg->values = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* filter_arg_new:
|
||||
*
|
||||
* Create a new FilterArg widget.
|
||||
*
|
||||
* Return value: A new FilterArg widget.
|
||||
**/
|
||||
FilterArg *
|
||||
filter_arg_new (char *name)
|
||||
{
|
||||
FilterArg *a = FILTER_ARG ( gtk_type_new (filter_arg_get_type ()));
|
||||
if (name)
|
||||
a->name = g_strdup(name);
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
filter_arg_add(FilterArg *arg, void *v)
|
||||
{
|
||||
arg->values = g_list_append(arg->values, v);
|
||||
gtk_signal_emit(GTK_OBJECT(arg), signals[CHANGED]);
|
||||
}
|
||||
|
||||
void
|
||||
filter_arg_remove(FilterArg *arg, void *v)
|
||||
{
|
||||
arg->values = g_list_remove(arg->values, v);
|
||||
((FilterArgClass *)(arg->object.klass))->free_value(arg, v);
|
||||
gtk_signal_emit(GTK_OBJECT(arg), signals[CHANGED]);
|
||||
}
|
||||
|
||||
void
|
||||
filter_arg_write_html(FilterArg *arg, GtkHTML *html, GtkHTMLStreamHandle *stream)
|
||||
{
|
||||
((FilterArgClass *)(arg->object.klass))->write_html(arg, html, stream);
|
||||
}
|
||||
void
|
||||
filter_arg_write_text(FilterArg *arg, GString *string)
|
||||
{
|
||||
((FilterArgClass *)(arg->object.klass))->write_text(arg, string);
|
||||
}
|
||||
void
|
||||
filter_arg_edit_values(FilterArg *arg)
|
||||
{
|
||||
((FilterArgClass *)(arg->object.klass))->edit_values(arg);
|
||||
}
|
||||
|
||||
xmlNodePtr
|
||||
filter_arg_values_get_xml(FilterArg *arg)
|
||||
{
|
||||
return ((FilterArgClass *)(arg->object.klass))->values_get_xml(arg);
|
||||
}
|
||||
void
|
||||
filter_arg_values_add_xml(FilterArg *arg, xmlNodePtr node)
|
||||
{
|
||||
((FilterArgClass *)(arg->object.klass))->values_add_xml(arg, node);
|
||||
}
|
||||
|
||||
/* returns the number of args in the arg list */
|
||||
int
|
||||
filter_arg_get_count(FilterArg *arg)
|
||||
{
|
||||
int count=0;
|
||||
GList *l;
|
||||
|
||||
for (l = arg->values;l;l=g_list_next(l))
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
void *
|
||||
filter_arg_get_value(FilterArg *arg, int index)
|
||||
{
|
||||
int count=0;
|
||||
GList *l;
|
||||
|
||||
for (l = arg->values;l && count<index;l=g_list_next(l))
|
||||
count++;
|
||||
if (l)
|
||||
return l->data;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
filter_arg_get_value_as_string(FilterArg *arg, int index)
|
||||
{
|
||||
int count=0;
|
||||
GList *l;
|
||||
void *data;
|
||||
|
||||
data = filter_arg_get_value(arg, index);
|
||||
if (data) {
|
||||
return ((FilterArgClass *)(arg->object.klass))->get_value_as_string(arg, data);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
72
filter/filter-arg.h
Normal file
72
filter/filter-arg.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2000 Helix Code Inc.
|
||||
*
|
||||
* Authors: Michael Zucchi <notzed@helixcode.com>
|
||||
*
|
||||
* Abstract class to hold filter arguments.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public License
|
||||
* as published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _FILTER_ARG_H
|
||||
#define _FILTER_ARG_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtkhtml/gtkhtml.h>
|
||||
#include <gnome-xml/tree.h>
|
||||
|
||||
#define FILTER_ARG(obj) GTK_CHECK_CAST (obj, filter_arg_get_type (), FilterArg)
|
||||
#define FILTER_ARG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_arg_get_type (), FilterArgClass)
|
||||
#define IS_FILTER_ARG(obj) GTK_CHECK_TYPE (obj, filter_arg_get_type ())
|
||||
|
||||
typedef struct _FilterArg FilterArg;
|
||||
typedef struct _FilterArgClass FilterArgClass;
|
||||
|
||||
struct _FilterArg {
|
||||
GtkObject object;
|
||||
|
||||
char *name;
|
||||
GList *values;
|
||||
};
|
||||
|
||||
struct _FilterArgClass {
|
||||
GtkObjectClass parent_class;
|
||||
|
||||
/* virtual methods */
|
||||
void (*write_html)(FilterArg *arg, GtkHTML *html, GtkHTMLStreamHandle *stream);
|
||||
void (*write_text)(FilterArg *arg, GString *string);
|
||||
void (*free_value)(FilterArg *arg, void *v);
|
||||
void (*edit_values)(FilterArg *arg);
|
||||
|
||||
void (*values_add_xml)(FilterArg *arg, xmlNodePtr node);
|
||||
xmlNodePtr (*values_get_xml)(FilterArg *arg);
|
||||
|
||||
char * (*get_value_as_string)(FilterArg *arg, void *data);
|
||||
|
||||
/* signals */
|
||||
void (*changed)(FilterArg *arg);
|
||||
};
|
||||
|
||||
guint filter_arg_get_type (void);
|
||||
FilterArg *filter_arg_new (char *name);
|
||||
void filter_arg_value_add(FilterArg *a, void *v);
|
||||
|
||||
xmlNodePtr filter_arg_values_get_xml(FilterArg *arg);
|
||||
void filter_arg_values_add_xml(FilterArg *arg, xmlNodePtr node);
|
||||
int filter_arg_get_count(FilterArg *arg);
|
||||
void *filter_arg_get_value(FilterArg *arg, int index);
|
||||
char *filter_arg_get_value_as_string(FilterArg *arg, int index);
|
||||
|
||||
#endif /* ! _FILTER_ARG_H */
|
||||
176
filter/filter-driver.c
Normal file
176
filter/filter-driver.c
Normal file
@ -0,0 +1,176 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gnome.h>
|
||||
#include <gtkhtml/gtkhtml.h>
|
||||
|
||||
#include <gnome-xml/tree.h>
|
||||
#include <gnome-xml/parser.h>
|
||||
|
||||
#include "filter-arg-types.h"
|
||||
#include "filter-xml.h"
|
||||
#include "filter-sexp.h"
|
||||
|
||||
extern int filter_find_arg(FilterArg *a, char *name);
|
||||
|
||||
/*
|
||||
splices ${cc} lines into a single string
|
||||
*/
|
||||
int
|
||||
expand_variables(GString *out, char *source, GList *args, int index)
|
||||
{
|
||||
GList *argl;
|
||||
FilterArg *arg;
|
||||
char *name= alloca(32);
|
||||
char *start, *end, *newstart, *tmp;
|
||||
int namelen=32;
|
||||
int len=0;
|
||||
int ok = 0;
|
||||
|
||||
start = source;
|
||||
while ( (newstart = strstr(start, "${"))
|
||||
&& (end = strstr(newstart+2, "}")) ) {
|
||||
len = end-newstart-2;
|
||||
if (len+1>namelen) {
|
||||
namelen = (len+1)*2;
|
||||
name = alloca(namelen);
|
||||
}
|
||||
memcpy(name, newstart+2, len);
|
||||
name[len] = 0;
|
||||
argl = g_list_find_custom(args, name, filter_find_arg);
|
||||
if (argl) {
|
||||
arg = argl->data;
|
||||
tmp = g_strdup_printf("%.*s%s", newstart-start, start, filter_arg_get_value_as_string(arg, index));
|
||||
printf("appending: %s\n", tmp);
|
||||
g_string_append(out, tmp);
|
||||
g_free(tmp);
|
||||
} else {
|
||||
ok = 1;
|
||||
tmp = g_strdup_printf("%.*s", end-start+1, start);
|
||||
printf("appending: %s\n", tmp);
|
||||
g_string_append(out, tmp);
|
||||
g_free(tmp);
|
||||
}
|
||||
start = end+1;
|
||||
}
|
||||
g_string_append(out, start);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
build an expression for the filter
|
||||
*/
|
||||
static void
|
||||
expand_filter_option(GString *s, struct filter_option *op)
|
||||
{
|
||||
GList *optionl;
|
||||
FilterArg *arg;
|
||||
|
||||
g_string_append(s, "(and ");
|
||||
optionl = op->options;
|
||||
while (optionl) {
|
||||
struct filter_optionrule *or = optionl->data;
|
||||
if (or->rule->type == FILTER_XML_MATCH) {
|
||||
GList *argl;
|
||||
int max=1, count;
|
||||
int i;
|
||||
|
||||
/* find out how many values we have in each arg (rule
|
||||
is repeated that many times for each arg) */
|
||||
argl = or->args;
|
||||
while (argl) {
|
||||
arg = argl->data;
|
||||
count = filter_arg_get_count(arg);
|
||||
if (count>=max && max>1) {
|
||||
g_warning("Rule '%s' has too many multi-valued values, ignored", or->rule->name);
|
||||
goto next_rule;
|
||||
}
|
||||
if (count>max) {
|
||||
max = count;
|
||||
}
|
||||
argl = g_list_next(argl);
|
||||
}
|
||||
g_string_append(s, "(or ");
|
||||
for (i=0;i<max;i++) {
|
||||
expand_variables(s, or->rule->code, or->args, i);
|
||||
}
|
||||
g_string_append(s, ") ");
|
||||
}
|
||||
next_rule:
|
||||
optionl = g_list_next(optionl);
|
||||
}
|
||||
#if 0
|
||||
optionl = op->options;
|
||||
while (optionl) {
|
||||
struct filter_optionrule *or = optionl->data;
|
||||
if (or->rule->type == FILTER_XML_EXCEPT) {
|
||||
g_string_append(s, " (except \"");
|
||||
g_string_append(s, or->rule->name);
|
||||
g_string_append(s, "\" ");
|
||||
g_string_append(s, or->rule->code);
|
||||
g_string_append(s, " ) ");
|
||||
}
|
||||
optionl = g_list_next(optionl);
|
||||
}
|
||||
#endif
|
||||
g_string_append(s, ")");
|
||||
#if 0
|
||||
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, " ");
|
||||
}
|
||||
optionl = g_list_next(optionl);
|
||||
}
|
||||
g_string_append(s, ")))");
|
||||
#endif
|
||||
printf("combined rule '%s'\n", s->str);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FilterSEXP *f;
|
||||
FilterSEXPResult *r;
|
||||
GList *rules, *options;
|
||||
xmlDocPtr doc, out, optionset, filteroptions;
|
||||
GString *s;
|
||||
|
||||
gnome_init("Test", "0.0", argc, argv);
|
||||
|
||||
doc = xmlParseFile("filterdescription.xml");
|
||||
rules = load_ruleset(doc);
|
||||
options = load_optionset(doc, rules);
|
||||
out = xmlParseFile("saveoptions.xml");
|
||||
options = load_optionset(out, rules);
|
||||
|
||||
s = g_string_new("");
|
||||
expand_filter_option(s, options->data);
|
||||
g_string_append(s, "");
|
||||
|
||||
printf("total rule = '%s'\n", s->str);
|
||||
|
||||
f = filter_sexp_new();
|
||||
filter_sexp_add_variable(f, 0, "sender", NULL);
|
||||
filter_sexp_add_variable(f, 0, "receipient", NULL);
|
||||
filter_sexp_add_variable(f, 0, "folder", NULL);
|
||||
|
||||
/* simple functions */
|
||||
filter_sexp_add_function(f, 0, "header-get", NULL, NULL);
|
||||
filter_sexp_add_function(f, 0, "header-contains", NULL, NULL);
|
||||
filter_sexp_add_function(f, 0, "copy-to", NULL, NULL);
|
||||
|
||||
filter_sexp_add_ifunction(f, 0, "set", NULL, NULL);
|
||||
|
||||
/* control functions */
|
||||
filter_sexp_add_ifunction(f, 0, "match-all", NULL, NULL);
|
||||
filter_sexp_add_ifunction(f, 0, "match", NULL, NULL);
|
||||
filter_sexp_add_ifunction(f, 0, "action", NULL, NULL);
|
||||
filter_sexp_add_ifunction(f, 0, "except", NULL, NULL);
|
||||
|
||||
filter_sexp_input_text(f, s->str, strlen(s->str));
|
||||
filter_sexp_parse(f);
|
||||
|
||||
}
|
||||
1073
filter/filter-sexp.c
Normal file
1073
filter/filter-sexp.c
Normal file
File diff suppressed because it is too large
Load Diff
117
filter/filter-sexp.h
Normal file
117
filter/filter-sexp.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
generic s-exp evaluator class
|
||||
*/
|
||||
#ifndef _FILTER_SEXP_H
|
||||
#define _FILTER_SEXP_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtkhtml/gtkhtml.h>
|
||||
#include <gnome-xml/tree.h>
|
||||
|
||||
#define FILTER_SEXP(obj) GTK_CHECK_CAST (obj, filter_sexp_get_type (), FilterSEXP)
|
||||
#define FILTER_SEXP_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, filter_sexp_get_type (), FilterSEXPClass)
|
||||
#define FILTER_IS_SEXP(obj) GTK_CHECK_TYPE (obj, filter_sexp_get_type ())
|
||||
|
||||
typedef struct _FilterSEXP FilterSEXP;
|
||||
typedef struct _FilterSEXPClass FilterSEXPClass;
|
||||
|
||||
typedef struct _FilterSEXPSymbol FilterSEXPSymbol;
|
||||
typedef struct _FilterSEXPResult FilterSEXPResult;
|
||||
typedef struct _FilterSEXPTerm FilterSEXPTerm;
|
||||
|
||||
typedef struct _FilterSEXPResult *(FilterSEXPFunc)(struct _FilterSEXP *sexp,
|
||||
int argc,
|
||||
struct _FilterSEXPResult **argv,
|
||||
void *data);
|
||||
|
||||
typedef struct _FilterSEXPResult *(FilterSEXPIFunc)(struct _FilterSEXP *sexp,
|
||||
int argc,
|
||||
struct _FilterSEXPTerm **argv,
|
||||
void *data);
|
||||
enum _FilterSEXPResultType {
|
||||
FSEXP_RES_ARRAY_PTR=0, /* type is a ptrarray, what it points to is implementation dependant */
|
||||
FSEXP_RES_INT, /* type is a number */
|
||||
FSEXP_RES_STRING, /* type is a pointer to a single string */
|
||||
FSEXP_RES_BOOL, /* boolean type */
|
||||
FSEXP_RES_UNDEFINED /* unknown type */
|
||||
};
|
||||
|
||||
struct _FilterSEXPResult {
|
||||
enum _FilterSEXPResultType type;
|
||||
union {
|
||||
GPtrArray *ptrarray;
|
||||
int number;
|
||||
char *string;
|
||||
int bool;
|
||||
} value;
|
||||
};
|
||||
|
||||
enum _FilterSEXPTermType {
|
||||
FSEXP_TERM_INT = 0, /* integer literal */
|
||||
FSEXP_TERM_BOOL, /* boolean literal */
|
||||
FSEXP_TERM_STRING, /* string literal */
|
||||
FSEXP_TERM_FUNC, /* normal function, arguments are evaluated before calling */
|
||||
FSEXP_TERM_IFUNC, /* immediate function, raw terms are arguments */
|
||||
FSEXP_TERM_VAR, /* variable reference */
|
||||
};
|
||||
|
||||
struct _FilterSEXPSymbol {
|
||||
int type; /* FSEXP_TERM_FUNC or FSEXP_TERM_VAR */
|
||||
char *name;
|
||||
void *data;
|
||||
union {
|
||||
FilterSEXPFunc *func;
|
||||
FilterSEXPIFunc *ifunc;
|
||||
} f;
|
||||
};
|
||||
|
||||
struct _FilterSEXPTerm {
|
||||
enum _FilterSEXPTermType type;
|
||||
union {
|
||||
char *string;
|
||||
int number;
|
||||
int bool;
|
||||
struct {
|
||||
struct _FilterSEXPSymbol *sym;
|
||||
struct _FilterSEXPTerm **terms;
|
||||
int termcount;
|
||||
} func;
|
||||
struct _FilterSEXPSymbol *var;
|
||||
} value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct _FilterSEXP {
|
||||
GtkObject object;
|
||||
|
||||
GScanner *scanner; /* for parsing text version */
|
||||
FilterSEXPTerm *tree; /* root of expression tree */
|
||||
};
|
||||
|
||||
struct _FilterSEXPClass {
|
||||
GtkObjectClass parent_class;
|
||||
|
||||
};
|
||||
|
||||
guint filter_sexp_get_type (void);
|
||||
FilterSEXP *filter_sexp_new (void);
|
||||
void filter_sexp_add_function (FilterSEXP *f, int scope, char *name, FilterSEXPFunc *func, void *data);
|
||||
void filter_sexp_add_ifunction (FilterSEXP *f, int scope, char *name, FilterSEXPIFunc *func, void *data);
|
||||
void filter_sexp_add_variable (FilterSEXP *f, int scope, char *name, FilterSEXPTerm *value);
|
||||
void filter_sexp_remove_symbol (FilterSEXP *f, int scope, char *name);
|
||||
int filter_sexp_set_scope (FilterSEXP *f, int scope);
|
||||
|
||||
void filter_sexp_input_text (FilterSEXP *f, char *text, int len);
|
||||
void filter_sexp_input_file (FilterSEXP *f, int fd);
|
||||
|
||||
|
||||
void filter_sexp_parse (FilterSEXP *f);
|
||||
FilterSEXPResult *filter_sexp_eval (FilterSEXP *f);
|
||||
|
||||
FilterSEXPResult *filter_sexp_term_eval (struct _FilterSEXP *f, struct _FilterSEXPTerm *t);
|
||||
FilterSEXPResult *filter_sexp_result_new (int type);
|
||||
void filter_sexp_result_free (struct _FilterSEXPResult *t);
|
||||
|
||||
#endif /* _FILTER_SEXP_H */
|
||||
658
filter/filter-xml.c
Normal file
658
filter/filter-xml.c
Normal file
@ -0,0 +1,658 @@
|
||||
/* -*- Mode: C; c-file-style: "linux"; indent-tabs-mode: t; c-basic-offset: 8; -*- */
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gnome.h>
|
||||
#include <gtkhtml/gtkhtml.h>
|
||||
|
||||
#include <gnome-xml/tree.h>
|
||||
#include <gnome-xml/parser.h>
|
||||
|
||||
#include "filter-arg-types.h"
|
||||
#include "filter-xml.h"
|
||||
|
||||
struct token_tab {
|
||||
char *name;
|
||||
enum filter_xml_token token;
|
||||
};
|
||||
|
||||
struct token_tab token_table[] = {
|
||||
{ "action", FILTER_XML_ACTION },
|
||||
{ "address", FILTER_XML_ADDRESS },
|
||||
{ "code", FILTER_XML_CODE },
|
||||
{ "description", FILTER_XML_DESC },
|
||||
{ "except", FILTER_XML_EXCEPT },
|
||||
{ "folder", FILTER_XML_FOLDER },
|
||||
{ "match", FILTER_XML_MATCH },
|
||||
{ "name", FILTER_XML_NAME },
|
||||
{ "option", FILTER_XML_OPTION },
|
||||
{ "optionrule", FILTER_XML_OPTIONRULE },
|
||||
{ "optionset", FILTER_XML_OPTIONSET },
|
||||
{ "optionvalue", FILTER_XML_OPTIONVALUE },
|
||||
{ "receive", FILTER_XML_RECEIVE },
|
||||
{ "rule", FILTER_XML_RULE },
|
||||
{ "ruleset", FILTER_XML_RULESET },
|
||||
{ "send", FILTER_XML_SEND },
|
||||
{ "source", FILTER_XML_SOURCE },
|
||||
{ "text", FILTER_XML_TEXT },
|
||||
};
|
||||
|
||||
/* convert a name to a token value */
|
||||
static int
|
||||
tokenise(const char *name)
|
||||
{
|
||||
int i;
|
||||
int len = sizeof(token_table)/sizeof(token_table[0]);
|
||||
|
||||
if (name) {
|
||||
for (i=0;i<len;i++) {
|
||||
if (strcmp(name, token_table[i].name) == 0)
|
||||
return token_table[i].token;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *
|
||||
detokenise(int token)
|
||||
{
|
||||
int i;
|
||||
int len = sizeof(token_table)/sizeof(token_table[0]);
|
||||
|
||||
if (token>=0) {
|
||||
for (i=0;i<len;i++) {
|
||||
if (token_table[i].token == token)
|
||||
return token_table[i].name;
|
||||
}
|
||||
}
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
|
||||
xmlNodePtr find_node(xmlNodePtr start, char *name)
|
||||
{
|
||||
printf("trying to find node '%s'\n", name);
|
||||
while (start && strcmp(start->name, name))
|
||||
start = start->next;
|
||||
printf("node = %p\n", start);
|
||||
return start;
|
||||
}
|
||||
|
||||
xmlNodePtr 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);
|
||||
|
||||
while ( start && (start = find_node(start, name)) ) {
|
||||
s = xmlGetProp(start, attrname);
|
||||
printf(" comparing '%s' to '%s'\n", s, attrvalue);
|
||||
if (s && !strcmp(s, attrvalue))
|
||||
break;
|
||||
start = start->next;
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
static int
|
||||
find_arg(FilterArg *a, char *name)
|
||||
{
|
||||
printf("finding, is %s = %s?\n", a->name, name);
|
||||
return strcmp(a->name, name);
|
||||
}
|
||||
|
||||
static int
|
||||
find_rule(struct filter_rule *a, char *name)
|
||||
{
|
||||
printf("finding, is %s = %s?\n", a->name, name);
|
||||
return strcmp(a->name, name);
|
||||
}
|
||||
|
||||
static int display_order[] = { FILTER_XML_MATCH, FILTER_XML_ACTION, FILTER_XML_EXCEPT };
|
||||
|
||||
static struct filter_option *
|
||||
option_clone(struct filter_option *source)
|
||||
{
|
||||
struct filter_option *dest = g_malloc0(sizeof(*dest));
|
||||
GList *loptions;
|
||||
struct filter_optionrule *old, *new;
|
||||
|
||||
dest->type = source->type;
|
||||
dest->description = source->description;
|
||||
loptions = dest->options;
|
||||
while (loptions) {
|
||||
old = loptions->data;
|
||||
new = g_malloc0(sizeof(*new));
|
||||
new->rule = old->rule;
|
||||
/* FIXME: need to copy any args as well!!! */
|
||||
dest->options = g_list_append(dest->options, new);
|
||||
loptions = g_list_next(loptions);
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct description_decode_lambda {
|
||||
GString *str;
|
||||
GList *args;
|
||||
GtkHTML *html;
|
||||
GtkHTMLStreamHandle *stream;
|
||||
};
|
||||
|
||||
static char *
|
||||
arg_text(FilterArg *arg)
|
||||
{
|
||||
char *out = NULL;
|
||||
GList *value, *next;
|
||||
GString *str;
|
||||
|
||||
value = arg->values;
|
||||
|
||||
if (value == NULL)
|
||||
return NULL;
|
||||
|
||||
str = g_string_new("");
|
||||
filter_arg_write_text(arg, str);
|
||||
out = str->str;
|
||||
g_string_free(str, FALSE);
|
||||
return out;
|
||||
}
|
||||
|
||||
static void
|
||||
description_decode_text(struct filter_desc *d, struct description_decode_lambda *l)
|
||||
{
|
||||
GList *list;
|
||||
char *txt;
|
||||
|
||||
switch (d->type) {
|
||||
case FILTER_XML_TEXT:
|
||||
case FILTER_XML_DESC:
|
||||
dotext:
|
||||
printf("appending '%s'\n", d->data);
|
||||
printf("vartype = %s\n", detokenise(d->vartype));
|
||||
printf("varname = %s\n", d->varname);
|
||||
if (d->vartype !=-1 && d->varname
|
||||
&& (list = g_list_find_custom(l->args, d->varname, (GCompareFunc) find_arg))
|
||||
&& (txt = arg_text(list->data))) {
|
||||
} else {
|
||||
txt = d->data;
|
||||
}
|
||||
g_string_append(l->str, txt);
|
||||
break;
|
||||
default:
|
||||
printf("WARN: unknown desc text type '%s' = %s\n", detokenise(d->type), d->data);
|
||||
goto dotext;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
description_text(GList *description, GList *args)
|
||||
{
|
||||
char *txt;
|
||||
struct description_decode_lambda l;
|
||||
|
||||
printf("\ndecoding ...\n");
|
||||
|
||||
l.str = g_string_new("");
|
||||
l.args = args;
|
||||
g_list_foreach(description, (GFunc) description_decode_text, &l);
|
||||
|
||||
printf("string is '%s'\n", l.str->str);
|
||||
|
||||
txt = l.str->str;
|
||||
g_string_free(l.str, FALSE);
|
||||
|
||||
return txt;
|
||||
}
|
||||
|
||||
static void
|
||||
html_write(GtkHTML *html, GtkHTMLStreamHandle *stream, char *s)
|
||||
{
|
||||
printf("appending html '%s'\n", s);
|
||||
gtk_html_write(html, stream, s, strlen(s));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
description_decode_html(struct filter_desc *d, struct description_decode_lambda *l)
|
||||
{
|
||||
GList *list;
|
||||
char *txt, *end;
|
||||
int free;
|
||||
|
||||
switch (d->type) {
|
||||
case FILTER_XML_TEXT:
|
||||
case FILTER_XML_DESC:
|
||||
dotext:
|
||||
printf("appending '%s'\n", d->data);
|
||||
printf("vartype = %s\n", detokenise(d->vartype));
|
||||
printf("varname = %s\n", d->varname);
|
||||
free = FALSE;
|
||||
if (d->vartype !=-1 && d->varname) {
|
||||
char *link;
|
||||
list = g_list_find_custom(l->args, d->varname, (GCompareFunc) find_arg);
|
||||
end = "</a>";
|
||||
if (list) {
|
||||
txt = arg_text(list->data);
|
||||
if (txt == NULL)
|
||||
txt = d->data;
|
||||
else
|
||||
free = TRUE;
|
||||
link = g_strdup_printf("<a href=\"arg:%p %p\">", d, list->data);
|
||||
} else {
|
||||
printf("cannot find arg '%s'\n", d->varname);
|
||||
link = g_strdup_printf("<a href=\"arg:%p %p\">", d, NULL);
|
||||
txt = d->data;
|
||||
}
|
||||
html_write(l->html, l->stream, link);
|
||||
g_free(link);
|
||||
} else {
|
||||
txt = d->data;
|
||||
end = NULL;
|
||||
}
|
||||
html_write(l->html, l->stream, txt);
|
||||
if (end) {
|
||||
html_write(l->html, l->stream, end);
|
||||
}
|
||||
if (free)
|
||||
g_free(txt);
|
||||
break;
|
||||
default:
|
||||
printf("WARN: unknown desc text type '%s' = %s\n", detokenise(d->type), d->data);
|
||||
goto dotext;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
description_html_write(GList *description, GList *args, GtkHTML *html, GtkHTMLStreamHandle *stream)
|
||||
{
|
||||
char *txt;
|
||||
struct description_decode_lambda l;
|
||||
|
||||
printf("\ndecoding ...\n");
|
||||
|
||||
l.str = NULL;
|
||||
l.args = args;
|
||||
l.html = html;
|
||||
l.stream = stream;
|
||||
g_list_foreach(description, (GFunc) description_decode_html, &l);
|
||||
}
|
||||
|
||||
|
||||
static GList *
|
||||
load_desc(xmlNodePtr node, int type, int vartype, char *varname)
|
||||
{
|
||||
struct filter_desc *desc;
|
||||
xmlNodePtr n;
|
||||
int newtype;
|
||||
int newvartype;
|
||||
char *newvarname;
|
||||
GList *list = NULL;
|
||||
|
||||
while (node) {
|
||||
if (node->content) {
|
||||
desc = g_malloc0(sizeof(*desc));
|
||||
desc->data = node->content;
|
||||
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));
|
||||
list = g_list_append(list, desc);
|
||||
printf("appending '%s'\n", node->content);
|
||||
newtype = type;
|
||||
newvartype = -1;
|
||||
newvarname = NULL;
|
||||
} else {
|
||||
newtype = tokenise(node->name);
|
||||
newvartype = tokenise(xmlGetProp(node, "type"));
|
||||
newvarname = xmlGetProp(node, "name");
|
||||
}
|
||||
n = node->childs;
|
||||
while (n) {
|
||||
printf("adding child '%s'\n", n->name);
|
||||
list = g_list_concat(list, load_desc(n, newtype, newvartype, newvarname));
|
||||
n = n->next;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
GList *
|
||||
load_ruleset(xmlDocPtr doc)
|
||||
{
|
||||
xmlNodePtr ruleset, rule, n;
|
||||
struct filter_rule *r;
|
||||
int type;
|
||||
int ruletype;
|
||||
GList *rules = NULL;
|
||||
|
||||
g_return_val_if_fail(doc!=NULL, NULL);
|
||||
|
||||
ruleset = find_node(doc->root->childs, "ruleset");
|
||||
|
||||
while (ruleset) {
|
||||
|
||||
rule = ruleset->childs;
|
||||
|
||||
ruletype = tokenise(xmlGetProp(ruleset, "type"));
|
||||
|
||||
printf("ruleset, name = %s\n", ruleset->name);
|
||||
|
||||
while (rule) {
|
||||
|
||||
n = rule->childs;
|
||||
r = g_malloc0(sizeof(*r));
|
||||
r->type = ruletype;
|
||||
r->name = xmlGetProp(rule, "name");
|
||||
|
||||
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);
|
||||
if (n->childs) {
|
||||
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");
|
||||
r->description = load_desc(n->childs, type, -1, NULL);
|
||||
printf(" ** done loading description\n");
|
||||
description_text(r->description, 0);
|
||||
printf(" ** done dumping description\n");
|
||||
break;
|
||||
default:
|
||||
printf("warning, unknown token encountered\n");
|
||||
break;
|
||||
}
|
||||
n = n->next;
|
||||
}
|
||||
if (r)
|
||||
rules = g_list_append(rules, r);
|
||||
rule = rule->next;
|
||||
}
|
||||
ruleset = find_node(ruleset->next, "ruleset");
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
|
||||
int
|
||||
filter_find_rule(struct filter_rule *a, char *name)
|
||||
{
|
||||
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);
|
||||
return strcmp(a->name, name);
|
||||
}
|
||||
|
||||
static FilterArg *
|
||||
load_optionvalue(struct filter_desc *desc, xmlNodePtr node)
|
||||
{
|
||||
xmlNodePtr n;
|
||||
int token;
|
||||
int lasttoken = -2;
|
||||
FilterArg *arg = NULL;
|
||||
char *name;
|
||||
|
||||
printf("creating arg entry for '%s'\n", desc->varname);
|
||||
|
||||
switch(desc->vartype) {
|
||||
case FILTER_XML_ADDRESS:
|
||||
arg = filter_arg_address_new(name);
|
||||
break;
|
||||
case FILTER_XML_FOLDER:
|
||||
arg = filter_arg_folder_new(name);
|
||||
break;
|
||||
default:
|
||||
printf("ok, maybe we're not\n");
|
||||
/* unknown arg type, drop it */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (node == NULL)
|
||||
return arg;
|
||||
|
||||
filter_arg_values_add_xml(arg, node);
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* loads a blank (empty args) optionrule from a rule */
|
||||
static struct filter_optionrule *
|
||||
optionrule_new(struct filter_rule *rule)
|
||||
{
|
||||
GList *ldesc;
|
||||
struct filter_desc *desc;
|
||||
struct filter_optionrule *optionrule;
|
||||
|
||||
optionrule = g_malloc0(sizeof(*optionrule));
|
||||
optionrule->rule = rule;
|
||||
|
||||
ldesc = rule->description;
|
||||
while (ldesc) {
|
||||
desc = ldesc->data;
|
||||
if (desc->varname && desc->vartype!=-1) {
|
||||
FilterArg *arg;
|
||||
arg = load_optionvalue(desc, NULL);
|
||||
if (arg)
|
||||
optionrule->args = g_list_append(optionrule->args, arg);
|
||||
}
|
||||
ldesc = g_list_next(ldesc);
|
||||
}
|
||||
return optionrule;
|
||||
}
|
||||
|
||||
GList *
|
||||
load_optionset(xmlDocPtr doc, GList *rules)
|
||||
{
|
||||
xmlNodePtr optionset, option, o, or;
|
||||
struct filter_option *op;
|
||||
struct filter_optionrule *optionrule;
|
||||
struct filter_rule *fr;
|
||||
struct filter_desc *desc;
|
||||
int type, token;
|
||||
GList *l = NULL;
|
||||
GList *lrule;
|
||||
GList *ldesc;
|
||||
|
||||
g_return_val_if_fail(doc!=NULL, NULL);
|
||||
|
||||
optionset = find_node(doc->root->childs, "optionset");
|
||||
if (optionset == NULL) {
|
||||
printf("optionset not found\n");
|
||||
return;
|
||||
}
|
||||
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"));
|
||||
op->type = tokenise(xmlGetProp(option, "type"));
|
||||
while (o) {
|
||||
type = tokenise(o->name);
|
||||
switch (type) {
|
||||
case FILTER_XML_OPTIONRULE:
|
||||
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);
|
||||
optionrule = g_malloc0(sizeof(*optionrule));
|
||||
optionrule->rule = fr;
|
||||
op->options = g_list_append(op->options, optionrule);
|
||||
|
||||
/* scan through all variables required, setup blank variables if they do not exist */
|
||||
ldesc = fr->description;
|
||||
while (ldesc) {
|
||||
desc = ldesc->data;
|
||||
if (desc->varname && desc->vartype!=-1) {
|
||||
FilterArg *arg;
|
||||
/* 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)
|
||||
optionrule->args = g_list_append(optionrule->args, arg);
|
||||
}
|
||||
ldesc = g_list_next(ldesc);
|
||||
}
|
||||
} else {
|
||||
printf("Cannot find rule: %s\n", xmlGetProp(o, "rule"));
|
||||
}
|
||||
break;
|
||||
case FILTER_XML_DESC:
|
||||
printf("loading option descriptiong\n");
|
||||
op->description = load_desc(option->childs, type, -1, NULL);
|
||||
break;
|
||||
}
|
||||
o = o->next;
|
||||
}
|
||||
l = g_list_append(l, op);
|
||||
option = find_node(option->next, "option");
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
static xmlNodePtr
|
||||
save_optionset(xmlDocPtr doc, GList *optionl)
|
||||
{
|
||||
xmlNodePtr root, cur, option, optionrule, optionvalue;
|
||||
GList *optionrulel, *argl;
|
||||
struct filter_optionrule *or;
|
||||
|
||||
root = xmlNewDocNode(doc, NULL, "optionset", NULL);
|
||||
|
||||
/* for all options */
|
||||
while (optionl) {
|
||||
struct filter_option *op = optionl->data;
|
||||
|
||||
option = xmlNewDocNode(doc, NULL, "option", NULL);
|
||||
xmlSetProp(option, "type", detokenise(op->type));
|
||||
|
||||
optionrulel = op->options;
|
||||
while (optionrulel) {
|
||||
or = optionrulel->data;
|
||||
|
||||
optionrule = xmlNewDocNode(doc, NULL, "optionrule", NULL);
|
||||
xmlSetProp(optionrule, "type", detokenise(or->rule->type));
|
||||
xmlSetProp(optionrule, "rule", or->rule->name);
|
||||
|
||||
argl = or->args;
|
||||
while (argl) {
|
||||
FilterArg *arg = argl->data;
|
||||
|
||||
optionvalue = filter_arg_values_get_xml(arg);
|
||||
if (optionvalue)
|
||||
xmlAddChild(optionrule, optionvalue);
|
||||
|
||||
argl = g_list_next(argl);
|
||||
}
|
||||
|
||||
xmlAddChild(option, optionrule);
|
||||
|
||||
optionrulel = g_list_next(optionrulel);
|
||||
}
|
||||
|
||||
xmlAddChild(root, option);
|
||||
optionl = g_list_next(optionl);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
build an expression for the filter
|
||||
*/
|
||||
static void
|
||||
filterme(struct filter_option *op)
|
||||
{
|
||||
GList *optionl;
|
||||
GString *s;
|
||||
|
||||
s = g_string_new("(if (and ");
|
||||
optionl = op->options;
|
||||
while (optionl) {
|
||||
struct filter_optionrule *or = optionl->data;
|
||||
if (or->rule->type == FILTER_XML_MATCH) {
|
||||
g_string_append(s, "(match \"");
|
||||
g_string_append(s, or->rule->name);
|
||||
g_string_append(s, "\" ");
|
||||
g_string_append(s, or->rule->code);
|
||||
g_string_append(s, ") ");
|
||||
}
|
||||
optionl = g_list_next(optionl);
|
||||
}
|
||||
optionl = op->options;
|
||||
while (optionl) {
|
||||
struct filter_optionrule *or = optionl->data;
|
||||
if (or->rule->type == FILTER_XML_EXCEPT) {
|
||||
g_string_append(s, " (except \"");
|
||||
g_string_append(s, or->rule->name);
|
||||
g_string_append(s, "\" ");
|
||||
g_string_append(s, or->rule->code);
|
||||
g_string_append(s, " ) ");
|
||||
}
|
||||
optionl = g_list_next(optionl);
|
||||
}
|
||||
g_string_append(s, ") (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, " ");
|
||||
}
|
||||
optionl = g_list_next(optionl);
|
||||
}
|
||||
g_string_append(s, "))");
|
||||
printf("combined rule '%s'\n", s->str);
|
||||
}
|
||||
|
||||
#ifdef TESTER
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GList *rules, *options;
|
||||
xmlDocPtr doc, out, optionset, filteroptions;
|
||||
|
||||
gnome_init("Test", "0.0", argc, argv);
|
||||
|
||||
doc = xmlParseFile("filterdescription.xml");
|
||||
|
||||
rules = load_ruleset(doc);
|
||||
options = load_optionset(doc, rules);
|
||||
|
||||
out = xmlParseFile("saveoptions.xml");
|
||||
options = load_optionset(doc, rules);
|
||||
|
||||
while (options) {
|
||||
printf("applying a rule ...\n");
|
||||
filterme(options->data);
|
||||
options = g_list_next(options);
|
||||
}
|
||||
|
||||
#if 0
|
||||
out = xmlNewDoc("1.0");
|
||||
optionset = save_optionset(out, options);
|
||||
filteroptions = xmlNewDocNode(out, NULL, "filteroptions", NULL);
|
||||
xmlAddChild(filteroptions, optionset);
|
||||
xmlDocSetRootElement(out, filteroptions);
|
||||
xmlSaveFile("saveoptions.xml", out);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
51
filter/filter-xml.h
Normal file
51
filter/filter-xml.h
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
#ifndef _FILTER_XML_H
|
||||
#define _FILTER_XML_H
|
||||
|
||||
enum filter_xml_token {
|
||||
FILTER_XML_TEXT=0,
|
||||
FILTER_XML_RULE,
|
||||
FILTER_XML_CODE,
|
||||
FILTER_XML_DESC,
|
||||
FILTER_XML_RULESET,
|
||||
FILTER_XML_OPTION,
|
||||
FILTER_XML_OPTIONRULE,
|
||||
FILTER_XML_OPTIONSET,
|
||||
FILTER_XML_OPTIONVALUE,
|
||||
FILTER_XML_SOURCE,
|
||||
FILTER_XML_SEND,
|
||||
FILTER_XML_RECEIVE,
|
||||
FILTER_XML_ADDRESS,
|
||||
FILTER_XML_FOLDER,
|
||||
FILTER_XML_NAME,
|
||||
FILTER_XML_MATCH,
|
||||
FILTER_XML_ACTION,
|
||||
FILTER_XML_EXCEPT
|
||||
};
|
||||
|
||||
struct filter_desc {
|
||||
int type;
|
||||
char *data;
|
||||
char *varname; /* for named types */
|
||||
int vartype;
|
||||
};
|
||||
|
||||
struct filter_rule {
|
||||
int type;
|
||||
char *name;
|
||||
char *code;
|
||||
GList *description;
|
||||
};
|
||||
|
||||
struct filter_optionrule {
|
||||
struct filter_rule *rule;
|
||||
GList *args; /* FilterArg objects */
|
||||
};
|
||||
|
||||
struct filter_option {
|
||||
int type; /* 'send' 'receive'? */
|
||||
GList *description; /* filter_desc */
|
||||
GList *options; /* option_rule */
|
||||
};
|
||||
|
||||
#endif /* ! _FILTER_XML_H */
|
||||
Reference in New Issue
Block a user