2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
17 * Not Zed <notzed@lostzed.mmc.com.au>
18 * Jeffrey Stedfast <fejj@ximian.com>
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
27 #include <sys/types.h>
34 #include <glib/gstdio.h>
38 #include <glib/gi18n.h>
40 #include <libedataserver/e-xml-utils.h>
42 #include "e-util/e-error.h"
43 #include "e-util/e-xml-utils.h"
45 #include "filter-code.h"
46 #include "filter-colour.h"
47 #include "filter-datespec.h"
48 #include "filter-file.h"
49 #include "filter-input.h"
50 #include "filter-int.h"
51 #include "filter-marshal.h"
52 #include "filter-option.h"
53 #include "filter-rule.h"
54 #include "rule-context.h"
58 static int load(RuleContext
*rc
, const char *system
, const char *user
);
59 static int save(RuleContext
*rc
, const char *user
);
60 static int revert(RuleContext
*rc
, const char *user
);
61 static GList
*rename_uri(RuleContext
*rc
, const char *olduri
, const char *newuri
, GCompareFunc cmp
);
62 static GList
*delete_uri(RuleContext
*rc
, const char *uri
, GCompareFunc cmp
);
63 static FilterElement
*new_element(RuleContext
*rc
, const char *name
);
65 static void rule_context_class_init(RuleContextClass
*klass
);
66 static void rule_context_init(RuleContext
*rc
);
67 static void rule_context_finalise(GObject
*obj
);
69 #define _PRIVATE(x)(((RuleContext *)(x))->priv)
71 struct _RuleContextPrivate
{
75 static GObjectClass
*parent_class
= NULL
;
84 static guint signals
[LAST_SIGNAL
] = { 0 };
88 rule_context_get_type(void)
90 static GType type
= 0;
93 static const GTypeInfo info
= {
94 sizeof(RuleContextClass
),
95 NULL
, /* base_class_init */
96 NULL
, /* base_class_finalize */
97 (GClassInitFunc
) rule_context_class_init
,
98 NULL
, /* class_finalize */
99 NULL
, /* class_data */
102 (GInstanceInitFunc
) rule_context_init
,
105 type
= g_type_register_static(G_TYPE_OBJECT
, "RuleContext", &info
, 0);
112 rule_context_class_init(RuleContextClass
*klass
)
114 GObjectClass
*object_class
= G_OBJECT_CLASS(klass
);
116 parent_class
= g_type_class_ref(G_TYPE_OBJECT
);
118 object_class
->finalize
= rule_context_finalise
;
120 /* override methods */
123 klass
->revert
= revert
;
124 klass
->rename_uri
= rename_uri
;
125 klass
->delete_uri
= delete_uri
;
126 klass
->new_element
= new_element
;
129 signals
[RULE_ADDED
] =
130 g_signal_new("rule_added",
133 G_STRUCT_OFFSET(RuleContextClass
, rule_added
),
136 g_cclosure_marshal_VOID__POINTER
,
137 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
139 signals
[RULE_REMOVED
] =
140 g_signal_new("rule_removed",
143 G_STRUCT_OFFSET(RuleContextClass
, rule_removed
),
146 g_cclosure_marshal_VOID__POINTER
,
147 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
150 g_signal_new("changed",
153 G_STRUCT_OFFSET(RuleContextClass
, changed
),
156 g_cclosure_marshal_VOID__VOID
,
161 rule_context_init(RuleContext
*rc
)
163 rc
->priv
= g_malloc0(sizeof(*rc
->priv
));
165 rc
->part_set_map
= g_hash_table_new(g_str_hash
, g_str_equal
);
166 rc
->rule_set_map
= g_hash_table_new(g_str_hash
, g_str_equal
);
168 rc
->flags
= RULE_CONTEXT_GROUPING
;
172 free_part_set(struct _part_set_map
*map
, void *data
)
179 free_rule_set(struct _rule_set_map
*map
, void *data
)
186 rule_context_finalise(GObject
*obj
)
188 RuleContext
*rc
=(RuleContext
*) obj
;
190 g_list_foreach(rc
->rule_set_list
, (GFunc
)free_rule_set
, NULL
);
191 g_list_free(rc
->rule_set_list
);
192 g_hash_table_destroy(rc
->rule_set_map
);
194 g_list_foreach(rc
->part_set_list
, (GFunc
)free_part_set
, NULL
);
195 g_list_free(rc
->part_set_list
);
196 g_hash_table_destroy(rc
->part_set_map
);
200 g_list_foreach(rc
->parts
, (GFunc
)g_object_unref
, NULL
);
201 g_list_free(rc
->parts
);
202 g_list_foreach(rc
->rules
, (GFunc
)g_object_unref
, NULL
);
203 g_list_free(rc
->rules
);
207 G_OBJECT_CLASS(parent_class
)->finalize(obj
);
213 * Create a new RuleContext object.
215 * Return value: A new #RuleContext object.
218 rule_context_new(void)
220 return(RuleContext
*) g_object_new(RULE_TYPE_CONTEXT
, NULL
, NULL
);
224 rule_context_add_part_set(RuleContext
*rc
, const char *setname
, GType part_type
, RCPartFunc append
, RCNextPartFunc next
)
226 struct _part_set_map
*map
;
228 g_return_if_fail (g_hash_table_lookup(rc
->part_set_map
, setname
) == NULL
);
230 map
= g_malloc0(sizeof(*map
));
231 map
->type
= part_type
;
232 map
->append
= append
;
234 map
->name
= g_strdup(setname
);
235 g_hash_table_insert(rc
->part_set_map
, map
->name
, map
);
236 rc
->part_set_list
= g_list_append(rc
->part_set_list
, map
);
237 d(printf("adding part set '%s'\n", setname
));
241 rule_context_add_rule_set(RuleContext
*rc
, const char *setname
, GType rule_type
, RCRuleFunc append
, RCNextRuleFunc next
)
243 struct _rule_set_map
*map
;
245 g_return_if_fail (g_hash_table_lookup(rc
->rule_set_map
, setname
) == NULL
);
247 map
= g_malloc0(sizeof(*map
));
248 map
->type
= rule_type
;
249 map
->append
= append
;
251 map
->name
= g_strdup(setname
);
252 g_hash_table_insert(rc
->rule_set_map
, map
->name
, map
);
253 rc
->rule_set_list
= g_list_append(rc
->rule_set_list
, map
);
254 d(printf("adding rule set '%s'\n", setname
));
258 * rule_context_set_error:
262 * Set the text error for the context, or NULL to clear it.
265 rule_context_set_error(RuleContext
*rc
, char *error
)
267 g_return_if_fail (rc
);
279 * Load a rule context from a system and user description file.
284 rule_context_load(RuleContext
*rc
, const char *system
, const char *user
)
288 g_return_val_if_fail (rc
, -1);
290 d(printf("rule_context: loading %s %s\n", system
, user
));
293 res
= RULE_CONTEXT_GET_CLASS(rc
)->load(rc
, system
, user
);
300 load(RuleContext
*rc
, const char *system
, const char *user
)
302 xmlNodePtr set
, rule
, root
;
303 xmlDocPtr systemdoc
, userdoc
;
304 struct _part_set_map
*part_map
;
305 struct _rule_set_map
*rule_map
;
307 rule_context_set_error(rc
, NULL
);
309 d(printf("loading rules %s %s\n", system
, user
));
311 systemdoc
= e_xml_parse_file (system
);
312 if (systemdoc
== NULL
) {
313 rule_context_set_error(rc
, g_strdup_printf("Unable to load system rules '%s': %s",
314 system
, g_strerror(errno
)));
318 root
= xmlDocGetRootElement(systemdoc
);
319 if (root
== NULL
|| strcmp((char *)root
->name
, "filterdescription")) {
320 rule_context_set_error(rc
, g_strdup_printf("Unable to load system rules '%s': Invalid format", system
));
321 xmlFreeDoc(systemdoc
);
324 /* doesn't matter if this doens't exist */
326 if (g_file_test(user
, G_FILE_TEST_IS_REGULAR
))
327 userdoc
= e_xml_parse_file (user
);
329 /* now parse structure */
331 set
= root
->children
;
333 d(printf("set name = %s\n", set
->name
));
334 part_map
= g_hash_table_lookup(rc
->part_set_map
, set
->name
);
336 d(printf("loading parts ...\n"));
337 rule
= set
->children
;
339 if (!strcmp((char *)rule
->name
, "part")) {
340 FilterPart
*part
= FILTER_PART(g_object_new(part_map
->type
, NULL
, NULL
));
342 if (filter_part_xml_create(part
, rule
, rc
) == 0) {
343 part_map
->append(rc
, part
);
345 g_object_unref(part
);
346 g_warning("Cannot load filter part");
351 } else if ((rule_map
= g_hash_table_lookup(rc
->rule_set_map
, set
->name
))) {
352 d(printf("loading system rules ...\n"));
353 rule
= set
->children
;
355 d(printf("checking node: %s\n", rule
->name
));
356 if (!strcmp((char *)rule
->name
, "rule")) {
357 FilterRule
*part
= FILTER_RULE(g_object_new(rule_map
->type
, NULL
, NULL
));
359 if (filter_rule_xml_decode(part
, rule
, rc
) == 0) {
361 rule_map
->append(rc
, part
);
363 g_object_unref(part
);
364 g_warning("Cannot load filter part");
373 /* now load actual rules */
375 root
= xmlDocGetRootElement(userdoc
);
376 set
= root
?root
->children
:NULL
;
378 d(printf("set name = %s\n", set
->name
));
379 rule_map
= g_hash_table_lookup(rc
->rule_set_map
, set
->name
);
381 d(printf("loading rules ...\n"));
382 rule
= set
->children
;
384 d(printf("checking node: %s\n", rule
->name
));
385 if (!strcmp((char *)rule
->name
, "rule")) {
386 FilterRule
*part
= FILTER_RULE(g_object_new(rule_map
->type
, NULL
, NULL
));
388 if (filter_rule_xml_decode(part
, rule
, rc
) == 0) {
389 rule_map
->append(rc
, part
);
391 g_object_unref(part
);
392 g_warning("Cannot load filter part");
403 xmlFreeDoc(systemdoc
);
413 * Save a rule context to disk.
418 rule_context_save(RuleContext
*rc
, const char *user
)
420 g_return_val_if_fail (rc
, -1);
421 g_return_val_if_fail (user
, -1);
423 return RULE_CONTEXT_GET_CLASS(rc
)->save(rc
, user
);
427 save(RuleContext
*rc
, const char *user
)
430 xmlNodePtr root
, rules
, work
;
433 struct _rule_set_map
*map
;
436 doc
= xmlNewDoc((const unsigned char *)"1.0");
437 /* FIXME: set character encoding to UTF-8? */
438 root
= xmlNewDocNode(doc
, NULL
, (const unsigned char *)"filteroptions", NULL
);
439 xmlDocSetRootElement(doc
, root
);
440 l
= rc
->rule_set_list
;
443 rules
= xmlNewDocNode(doc
, NULL
, (unsigned char *)map
->name
, NULL
);
444 xmlAddChild(root
, rules
);
446 while ((rule
= map
->next(rc
, rule
, NULL
))) {
448 d(printf("processing rule %s\n", rule
->name
));
449 work
= filter_rule_xml_encode(rule
);
450 xmlAddChild(rules
, work
);
456 ret
= e_xml_save_file(user
, doc
);
464 * rule_context_revert:
468 * Reverts a rule context from a user description file. Assumes the
469 * system description file is unchanged from when it was loaded.
474 rule_context_revert(RuleContext
*rc
, const char *user
)
476 g_return_val_if_fail (rc
, 0);
478 d(printf("rule_context: restoring %s\n", user
));
480 return RULE_CONTEXT_GET_CLASS(rc
)->revert(rc
, user
);
483 struct _revert_data
{
489 revert_rule_remove(void *key
, FilterRule
*frule
, RuleContext
*rc
)
491 rule_context_remove_rule(rc
, frule
);
492 g_object_unref(frule
);
496 revert_source_remove(void *key
, struct _revert_data
*rest_data
, RuleContext
*rc
)
498 g_hash_table_foreach(rest_data
->rules
, (GHFunc
)revert_rule_remove
, rc
);
499 g_hash_table_destroy(rest_data
->rules
);
504 source_hashf(const char *a
)
507 return g_str_hash(a
);
512 source_eqf(const char *a
, const char *b
)
514 return((a
&& b
&& strcmp(a
, b
) == 0))
515 || (a
== NULL
&& b
== NULL
);
519 revert(RuleContext
*rc
, const char *user
)
521 xmlNodePtr set
, rule
;
522 /*struct _part_set_map *part_map;*/
523 struct _rule_set_map
*rule_map
;
524 struct _revert_data
*rest_data
;
525 GHashTable
*source_hash
;
529 rule_context_set_error(rc
, NULL
);
531 d(printf("restoring rules %s\n", user
));
533 userdoc
= e_xml_parse_file (user
);
535 /* clear out anythign we have? */
538 source_hash
= g_hash_table_new((GHashFunc
)source_hashf
, (GCompareFunc
)source_eqf
);
540 /* setup stuff we have now */
541 /* Note that we assume there is only 1 set of rules in a given rule context,
542 although other parts of the code dont assume this */
544 while ((frule
= rule_context_next_rule(rc
, frule
, NULL
))) {
545 rest_data
= g_hash_table_lookup(source_hash
, frule
->source
);
546 if (rest_data
== NULL
) {
547 rest_data
= g_malloc0(sizeof(*rest_data
));
548 rest_data
->rules
= g_hash_table_new(g_str_hash
, g_str_equal
);
549 g_hash_table_insert(source_hash
, frule
->source
, rest_data
);
551 g_hash_table_insert(rest_data
->rules
, frule
->name
, frule
);
554 /* make what we have, match what we load */
555 set
= xmlDocGetRootElement(userdoc
);
556 set
= set
?set
->children
:NULL
;
558 d(printf("set name = %s\n", set
->name
));
559 rule_map
= g_hash_table_lookup(rc
->rule_set_map
, set
->name
);
561 d(printf("loading rules ...\n"));
562 rule
= set
->children
;
564 d(printf("checking node: %s\n", rule
->name
));
565 if (!strcmp((char *)rule
->name
, "rule")) {
566 FilterRule
*part
= FILTER_RULE(g_object_new(rule_map
->type
, NULL
, NULL
));
568 if (filter_rule_xml_decode(part
, rule
, rc
) == 0) {
569 /* use the revert data to keep track of the right rank of this rule part */
570 rest_data
= g_hash_table_lookup(source_hash
, part
->source
);
571 if (rest_data
== NULL
) {
572 rest_data
= g_malloc0(sizeof(*rest_data
));
573 rest_data
->rules
= g_hash_table_new(g_str_hash
, g_str_equal
);
574 g_hash_table_insert(source_hash
, part
->source
, rest_data
);
576 frule
= g_hash_table_lookup(rest_data
->rules
, part
->name
);
578 if (rc
->priv
->frozen
== 0 && !filter_rule_eq(frule
, part
))
579 filter_rule_copy(frule
, part
);
581 g_object_unref(part
);
582 rule_context_rank_rule(rc
, frule
, frule
->source
, rest_data
->rank
);
583 g_hash_table_remove(rest_data
->rules
, frule
->name
);
585 rule_context_add_rule(rc
, part
);
586 rule_context_rank_rule(rc
, part
, part
->source
, rest_data
->rank
);
590 g_object_unref(part
);
591 g_warning("Cannot load filter part");
602 /* remove any we still have that weren't in the file */
603 g_hash_table_foreach(source_hash
, (GHFunc
)revert_source_remove
, rc
);
604 g_hash_table_destroy(source_hash
);
610 rule_context_find_part(RuleContext
*rc
, const char *name
)
612 g_return_val_if_fail (rc
, NULL
);
613 g_return_val_if_fail (name
, NULL
);
615 d(printf("find part : "));
616 return filter_part_find_list(rc
->parts
, name
);
620 rule_context_create_part(RuleContext
*rc
, const char *name
)
624 g_return_val_if_fail (rc
, NULL
);
625 g_return_val_if_fail (name
, NULL
);
627 if ((part
= rule_context_find_part(rc
, name
)))
628 return filter_part_clone(part
);
634 rule_context_next_part(RuleContext
*rc
, FilterPart
*last
)
636 g_return_val_if_fail (rc
, NULL
);
638 return filter_part_next_list(rc
->parts
, last
);
642 rule_context_next_rule(RuleContext
*rc
, FilterRule
*last
, const char *source
)
644 g_return_val_if_fail (rc
, NULL
);
646 return filter_rule_next_list(rc
->rules
, last
, source
);
650 rule_context_find_rule(RuleContext
*rc
, const char *name
, const char *source
)
652 g_return_val_if_fail (name
, NULL
);
653 g_return_val_if_fail (rc
, NULL
);
655 return filter_rule_find_list(rc
->rules
, name
, source
);
659 rule_context_add_part(RuleContext
*rc
, FilterPart
*part
)
661 g_return_if_fail (rc
);
662 g_return_if_fail (part
);
664 rc
->parts
= g_list_append(rc
->parts
, part
);
668 rule_context_add_rule(RuleContext
*rc
, FilterRule
*new)
670 g_return_if_fail (rc
);
671 g_return_if_fail (new);
673 d(printf("add rule '%s'\n", new->name
));
675 rc
->rules
= g_list_append(rc
->rules
, new);
677 if (rc
->priv
->frozen
== 0) {
678 g_signal_emit(rc
, signals
[RULE_ADDED
], 0, new);
679 g_signal_emit(rc
, signals
[CHANGED
], 0);
684 new_rule_response(GtkWidget
*dialog
, int button
, RuleContext
*context
)
686 if (button
== GTK_RESPONSE_OK
) {
687 FilterRule
*rule
= g_object_get_data((GObject
*) dialog
, "rule");
688 char *user
= g_object_get_data((GObject
*) dialog
, "path");
690 if (!filter_rule_validate(rule
)) {
691 /* no need to popup a dialog because the validate code does that. */
695 if (rule_context_find_rule (context
, rule
->name
, rule
->source
)) {
696 e_error_run((GtkWindow
*)dialog
, "filter:bad-name-notunique", rule
->name
, NULL
);
702 rule_context_add_rule(context
, rule
);
704 rule_context_save(context
, user
);
707 gtk_widget_destroy(dialog
);
710 /* add a rule, with a gui, asking for confirmation first ... optionally save to path */
712 rule_context_add_rule_gui(RuleContext
*rc
, FilterRule
*rule
, const char *title
, const char *path
)
717 d(printf("add rule gui '%s'\n", rule
->name
));
719 g_return_if_fail (rc
);
720 g_return_if_fail (rule
);
722 widget
= filter_rule_get_widget(rule
, rc
);
723 gtk_widget_show(widget
);
725 dialog
=(GtkDialog
*) gtk_dialog_new();
726 gtk_dialog_add_buttons(dialog
,
727 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
728 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
730 gtk_dialog_set_has_separator (dialog
, FALSE
);
732 gtk_window_set_title((GtkWindow
*) dialog
, title
);
733 gtk_window_set_default_size((GtkWindow
*) dialog
, 600, 400);
734 gtk_window_set_resizable((GtkWindow
*) dialog
, TRUE
);
736 gtk_box_pack_start((GtkBox
*) dialog
->vbox
, widget
, TRUE
, TRUE
, 0);
738 g_object_set_data_full((GObject
*) dialog
, "rule", rule
, g_object_unref
);
740 g_object_set_data_full((GObject
*) dialog
, "path", g_strdup(path
), g_free
);
742 g_signal_connect(dialog
, "response", G_CALLBACK(new_rule_response
), rc
);
746 g_object_set_data_full((GObject
*) dialog
, "context", rc
, g_object_unref
);
748 gtk_widget_show((GtkWidget
*) dialog
);
752 rule_context_remove_rule(RuleContext
*rc
, FilterRule
*rule
)
754 g_return_if_fail (rc
);
755 g_return_if_fail (rule
);
757 d(printf("remove rule '%s'\n", rule
->name
));
759 rc
->rules
= g_list_remove(rc
->rules
, rule
);
761 if (rc
->priv
->frozen
== 0) {
762 g_signal_emit(rc
, signals
[RULE_REMOVED
], 0, rule
);
763 g_signal_emit(rc
, signals
[CHANGED
], 0);
768 rule_context_rank_rule(RuleContext
*rc
, FilterRule
*rule
, const char *source
, int rank
)
771 int i
= 0, index
= 0;
773 g_return_if_fail (rc
);
774 g_return_if_fail (rule
);
776 if (rule_context_get_rank_rule (rc
, rule
, source
) == rank
)
779 rc
->rules
= g_list_remove(rc
->rules
, rule
);
782 FilterRule
*r
= node
->data
;
785 rc
->rules
= g_list_insert(rc
->rules
, rule
, index
);
786 if (rc
->priv
->frozen
== 0)
787 g_signal_emit(rc
, signals
[CHANGED
], 0);
793 if (source
== NULL
|| (r
->source
&& strcmp(r
->source
, source
) == 0))
799 rc
->rules
= g_list_append(rc
->rules
, rule
);
800 if (rc
->priv
->frozen
== 0)
801 g_signal_emit(rc
, signals
[CHANGED
], 0);
805 rule_context_get_rank_rule(RuleContext
*rc
, FilterRule
*rule
, const char *source
)
810 g_return_val_if_fail (rc
, -1);
811 g_return_val_if_fail (rule
, -1);
813 d(printf("getting rank of rule '%s'\n", rule
->name
));
817 FilterRule
*r
= node
->data
;
819 d(printf(" checking against rule '%s' rank '%d'\n", r
->name
, i
));
824 if (source
== NULL
|| (r
->source
&& strcmp(r
->source
, source
) == 0))
834 rule_context_find_rank_rule(RuleContext
*rc
, int rank
, const char *source
)
839 g_return_val_if_fail (rc
, NULL
);
841 d(printf("getting rule at rank %d source '%s'\n", rank
, source
?source
:"<any>"));
845 FilterRule
*r
= node
->data
;
847 d(printf(" checking against rule '%s' rank '%d'\n", r
->name
, i
));
849 if (source
== NULL
|| (r
->source
&& strcmp(r
->source
, source
) == 0)) {
862 delete_uri(RuleContext
*rc
, const char *uri
, GCompareFunc cmp
)
868 rule_context_delete_uri(RuleContext
*rc
, const char *uri
, GCompareFunc cmp
)
870 return RULE_CONTEXT_GET_CLASS(rc
)->delete_uri(rc
, uri
, cmp
);
874 rename_uri(RuleContext
*rc
, const char *olduri
, const char *newuri
, GCompareFunc cmp
)
880 rule_context_rename_uri(RuleContext
*rc
, const char *olduri
, const char *newuri
, GCompareFunc cmp
)
882 return RULE_CONTEXT_GET_CLASS(rc
)->rename_uri(rc
, olduri
, newuri
, cmp
);
886 rule_context_free_uri_list(RuleContext
*rc
, GList
*uris
)
890 /* TODO: should be virtual */
900 static FilterElement
*
901 new_element(RuleContext
*rc
, const char *type
)
903 if (!strcmp (type
, "string")) {
904 return (FilterElement
*) filter_input_new ();
905 } else if (!strcmp (type
, "address")) {
906 /* FIXME: temporary ... need real address type */
907 return (FilterElement
*) filter_input_new_type_name (type
);
908 } else if (!strcmp (type
, "code")) {
909 return (FilterElement
*) filter_code_new (FALSE
);
910 } else if (!strcmp (type
, "rawcode")) {
911 return (FilterElement
*) filter_code_new (TRUE
);
912 } else if (!strcmp (type
, "colour")) {
913 return (FilterElement
*) filter_colour_new ();
914 } else if (!strcmp (type
, "optionlist")) {
915 return (FilterElement
*) filter_option_new ();
916 } else if (!strcmp (type
, "datespec")) {
917 return (FilterElement
*) filter_datespec_new ();
918 } else if (!strcmp (type
, "command")) {
919 return (FilterElement
*) filter_file_new_type_name (type
);
920 } else if (!strcmp (type
, "file")) {
921 return (FilterElement
*) filter_file_new_type_name (type
);
922 } else if (!strcmp (type
, "integer")) {
923 return (FilterElement
*) filter_int_new ();
924 } else if (!strcmp (type
, "regex")) {
925 return (FilterElement
*) filter_input_new_type_name (type
);
926 }else if (!strcmp(type
, "completedpercent")) {
927 return (FilterElement
*) filter_int_new_type("completedpercent", 0,100);
930 g_warning("Unknown filter type '%s'", type
);
936 * rule_context_new_element:
940 * create a new filter element based on name.
945 rule_context_new_element(RuleContext
*rc
, const char *name
)
950 return RULE_CONTEXT_GET_CLASS(rc
)->new_element(rc
, name
);