Fix wrong free, and fix useless g_slist_concat
[claws.git] / src / matcher_parser_parse.y
1 %{
2 /*
3  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
4  * Copyright (c) 2001-2007 by Hiroyuki Yamamoto & The Claws Mail Team
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  * 
19  */
20
21 #include "defs.h"
22
23 #include <glib.h>
24 #include <glib/gi18n.h>
25
26 #include "utils.h"
27 #include "filtering.h"
28 #include "matcher.h"
29 #include "matcher_parser.h"
30 #include "matcher_parser_lex.h"
31 #include "colorlabel.h"
32 #include "folder_item_prefs.h"
33
34 static gint error = 0;
35 static gint bool_op = 0;
36 static gint match_type = 0;
37 static gchar *header = NULL;
38
39 static MatcherProp *prop;
40
41 static GSList *matchers_list = NULL;
42
43 static gboolean enabled = TRUE;
44 static gchar *name = NULL;
45 static gint account_id = 0;
46 static MatcherList *cond;
47 static GSList *action_list = NULL;
48 static FilteringAction *action = NULL;
49 static gboolean matcher_is_fast = TRUE;
50 static gboolean disable_warnings = FALSE;
51
52 static FilteringProp *filtering;
53
54 static GSList **prefs_filtering = NULL;
55 static int enable_compatibility = 0;
56
57 enum {
58         MATCHER_PARSE_FILE,
59         MATCHER_PARSE_NO_EOL,
60         MATCHER_PARSE_ENABLED,
61         MATCHER_PARSE_NAME,
62         MATCHER_PARSE_ACCOUNT,
63         MATCHER_PARSE_CONDITION,
64         MATCHER_PARSE_FILTERING_ACTION,
65 };
66
67 static int matcher_parse_op = MATCHER_PARSE_FILE;
68
69
70 /* ******************************************************************** */
71 /* redeclarations to avoid warnings */
72 void matcher_parserrestart(FILE *input_file);
73 void matcher_parser_init(void);
74 void matcher_parser_switch_to_buffer(void * new_buffer);
75 void matcher_parser_delete_buffer(void * b);
76 void matcher_parserpop_buffer_state(void);
77 int matcher_parserlex(void);
78
79 void matcher_parser_disable_warnings(const gboolean disable)
80 {
81         disable_warnings = disable;
82 }
83
84 void matcher_parser_start_parsing(FILE *f)
85 {
86         matcher_parserlineno = 1;
87         matcher_parserrestart(f);
88         account_id = 0;
89         matcher_parserparse();
90 }
91
92  
93 void * matcher_parser_scan_string(const char * str);
94  
95 FilteringProp *matcher_parser_get_filtering(gchar *str)
96 {
97         void *bufstate;
98         void *tmp_str = NULL;
99         
100         /* little hack to allow passing rules with no names */
101         if (!strncmp(str, "rulename ", 9))
102                 tmp_str = g_strdup(str);
103         else 
104                 tmp_str = g_strconcat("rulename \"\" ", str, NULL);
105
106         /* bad coding to enable the sub-grammar matching
107            in yacc */
108         matcher_parserlineno = 1;
109         matcher_parse_op = MATCHER_PARSE_NO_EOL;
110         matcher_parserrestart(NULL);
111         matcher_parserpop_buffer_state();
112         matcher_parser_init();
113         bufstate = matcher_parser_scan_string((const char *) tmp_str);
114         matcher_parser_switch_to_buffer(bufstate);
115         if (matcher_parserparse() != 0)
116                 filtering = NULL;
117         matcher_parse_op = MATCHER_PARSE_FILE;
118         matcher_parser_delete_buffer(bufstate);
119         g_free(tmp_str);
120         return filtering;
121 }
122
123 static gboolean check_quote_symetry(gchar *str)
124 {
125         const gchar *walk;
126         int ret = 0;
127         
128         if (str == NULL)
129                 return TRUE; /* heh, that's symetric */
130         if (*str == '\0')
131                 return TRUE;
132         for (walk = str; *walk; walk++) {
133                 if (*walk == '\"') {
134                         if (walk == str         /* first char */
135                         || *(walk - 1) != '\\') /* not escaped */
136                                 ret ++;
137                 }
138         }
139         return !(ret % 2);
140 }
141
142 MatcherList *matcher_parser_get_name(gchar *str)
143 {
144         void *bufstate;
145
146         if (!check_quote_symetry(str)) {
147                 cond = NULL;
148                 return cond;
149         }
150         
151         /* bad coding to enable the sub-grammar matching
152            in yacc */
153         matcher_parserlineno = 1;
154         matcher_parse_op = MATCHER_PARSE_NAME;
155         matcher_parserrestart(NULL);
156         matcher_parserpop_buffer_state();
157         matcher_parser_init();
158         bufstate = matcher_parser_scan_string(str);
159         matcher_parserparse();
160         matcher_parse_op = MATCHER_PARSE_FILE;
161         matcher_parser_delete_buffer(bufstate);
162         return cond;
163 }
164
165 MatcherList *matcher_parser_get_enabled(gchar *str)
166 {
167         void *bufstate;
168
169         if (!check_quote_symetry(str)) {
170                 cond = NULL;
171                 return cond;
172         }
173         
174         /* bad coding to enable the sub-grammar matching
175            in yacc */
176         matcher_parserlineno = 1;
177         matcher_parse_op = MATCHER_PARSE_ENABLED;
178         matcher_parserrestart(NULL);
179         matcher_parserpop_buffer_state();
180         matcher_parser_init();
181         bufstate = matcher_parser_scan_string(str);
182         matcher_parserparse();
183         matcher_parse_op = MATCHER_PARSE_FILE;
184         matcher_parser_delete_buffer(bufstate);
185         return cond;
186 }
187
188 MatcherList *matcher_parser_get_account(gchar *str)
189 {
190         void *bufstate;
191
192         if (!check_quote_symetry(str)) {
193                 cond = NULL;
194                 return cond;
195         }
196         
197         /* bad coding to enable the sub-grammar matching
198            in yacc */
199         matcher_parserlineno = 1;
200         matcher_parse_op = MATCHER_PARSE_ACCOUNT;
201         matcher_parserrestart(NULL);
202         matcher_parserpop_buffer_state();
203         matcher_parser_init();
204         bufstate = matcher_parser_scan_string(str);
205         matcher_parserparse();
206         matcher_parse_op = MATCHER_PARSE_FILE;
207         matcher_parser_delete_buffer(bufstate);
208         return cond;
209 }
210
211 MatcherList *matcher_parser_get_cond(gchar *str, gboolean *is_fast)
212 {
213         void *bufstate;
214
215         if (!check_quote_symetry(str)) {
216                 cond = NULL;
217                 return cond;
218         }
219         
220         matcher_is_fast = TRUE;
221         /* bad coding to enable the sub-grammar matching
222            in yacc */
223         matcher_parserlineno = 1;
224         matcher_parse_op = MATCHER_PARSE_CONDITION;
225         matcher_parserrestart(NULL);
226         matcher_parserpop_buffer_state();
227         matcher_parser_init();
228         bufstate = matcher_parser_scan_string(str);
229         matcher_parserparse();
230         matcher_parse_op = MATCHER_PARSE_FILE;
231         matcher_parser_delete_buffer(bufstate);
232         if (is_fast)
233                 *is_fast = matcher_is_fast;
234         return cond;
235 }
236
237 GSList *matcher_parser_get_action_list(gchar *str)
238 {
239         void *bufstate;
240
241         if (!check_quote_symetry(str)) {
242                 action_list = NULL;
243                 return action_list;
244         }
245         
246         /* bad coding to enable the sub-grammar matching
247            in yacc */
248         matcher_parserlineno = 1;
249         matcher_parse_op = MATCHER_PARSE_FILTERING_ACTION;
250         matcher_parserrestart(NULL);
251         matcher_parserpop_buffer_state();
252         matcher_parser_init();
253         bufstate = matcher_parser_scan_string(str);
254         matcher_parserparse();
255         matcher_parse_op = MATCHER_PARSE_FILE;
256         matcher_parser_delete_buffer(bufstate);
257         return action_list;
258 }
259
260 MatcherProp *matcher_parser_get_prop(gchar *str)
261 {
262         MatcherList *list;
263         MatcherProp *prop;
264
265         matcher_parserlineno = 1;
266         list = matcher_parser_get_cond(str, NULL);
267         if (list == NULL)
268                 return NULL;
269
270         if (list->matchers == NULL)
271                 return NULL;
272
273         if (list->matchers->next != NULL)
274                 return NULL;
275
276         prop = list->matchers->data;
277
278         g_slist_free(list->matchers);
279         g_free(list);
280
281         return prop;
282 }
283
284 void matcher_parsererror(char *str)
285 {
286         GSList *l;
287
288         if (matchers_list) {
289                 for (l = matchers_list; l != NULL; l = g_slist_next(l)) {
290                         matcherprop_free((MatcherProp *)
291                                          l->data);
292                         l->data = NULL;
293                 }
294                 g_slist_free(matchers_list);
295                 matchers_list = NULL;
296         }
297         cond = NULL;
298         if (!disable_warnings)
299                 g_warning("filtering parsing: %i: %s\n",
300                         matcher_parserlineno, str);
301         error = 1;
302 }
303
304 int matcher_parserwrap(void)
305 {
306         return 1;
307 }
308 %}
309
310 %union {
311         char *str;
312         int value;
313 }
314 %token MATCHER_ALL MATCHER_UNREAD  MATCHER_NOT_UNREAD 
315 %token MATCHER_NEW  MATCHER_NOT_NEW  MATCHER_MARKED
316 %token MATCHER_NOT_MARKED  MATCHER_DELETED  MATCHER_NOT_DELETED
317 %token MATCHER_REPLIED  MATCHER_NOT_REPLIED  MATCHER_FORWARDED
318 %token MATCHER_NOT_FORWARDED  MATCHER_SUBJECT  MATCHER_NOT_SUBJECT
319 %token MATCHER_FROM  MATCHER_NOT_FROM  MATCHER_TO  MATCHER_NOT_TO
320 %token MATCHER_CC  MATCHER_NOT_CC  MATCHER_TO_OR_CC  MATCHER_NOT_TO_AND_NOT_CC
321 %token MATCHER_AGE_GREATER  MATCHER_AGE_LOWER  MATCHER_NEWSGROUPS
322 %token MATCHER_AGE_GREATER_HOURS  MATCHER_AGE_LOWER_HOURS
323 %token MATCHER_NOT_NEWSGROUPS  MATCHER_INREPLYTO  MATCHER_NOT_INREPLYTO
324 %token MATCHER_REFERENCES  MATCHER_NOT_REFERENCES  MATCHER_SCORE_GREATER
325 %token MATCHER_SCORE_LOWER  MATCHER_HEADER  MATCHER_NOT_HEADER
326 %token MATCHER_HEADERS_PART  MATCHER_NOT_HEADERS_PART  MATCHER_MESSAGE
327 %token MATCHER_NOT_MESSAGE  MATCHER_BODY_PART  MATCHER_NOT_BODY_PART
328 %token MATCHER_TEST  MATCHER_NOT_TEST  MATCHER_MATCHCASE  MATCHER_MATCH
329 %token MATCHER_REGEXPCASE  MATCHER_REGEXP  MATCHER_SCORE  MATCHER_MOVE
330 %token MATCHER_FOUND_IN_ADDRESSBOOK MATCHER_NOT_FOUND_IN_ADDRESSBOOK MATCHER_IN
331 %token MATCHER_COPY  MATCHER_DELETE  MATCHER_MARK  MATCHER_UNMARK
332 %token MATCHER_LOCK MATCHER_UNLOCK
333 %token MATCHER_EXECUTE
334 %token MATCHER_MARK_AS_READ  MATCHER_MARK_AS_UNREAD  MATCHER_FORWARD
335 %token MATCHER_MARK_AS_SPAM MATCHER_MARK_AS_HAM
336 %token MATCHER_FORWARD_AS_ATTACHMENT  MATCHER_EOL
337 %token MATCHER_OR MATCHER_AND  
338 %token MATCHER_COLOR MATCHER_SCORE_EQUAL MATCHER_REDIRECT 
339 %token MATCHER_SIZE_GREATER MATCHER_SIZE_SMALLER MATCHER_SIZE_EQUAL
340 %token MATCHER_LOCKED MATCHER_NOT_LOCKED
341 %token MATCHER_PARTIAL MATCHER_NOT_PARTIAL
342 %token MATCHER_COLORLABEL MATCHER_NOT_COLORLABEL
343 %token MATCHER_IGNORE_THREAD MATCHER_NOT_IGNORE_THREAD
344 %token MATCHER_WATCH_THREAD MATCHER_NOT_WATCH_THREAD
345 %token MATCHER_CHANGE_SCORE MATCHER_SET_SCORE
346 %token MATCHER_ADD_TO_ADDRESSBOOK
347 %token MATCHER_STOP MATCHER_HIDE MATCHER_IGNORE MATCHER_WATCH
348 %token MATCHER_SPAM MATCHER_NOT_SPAM
349 %token MATCHER_HAS_ATTACHMENT MATCHER_HAS_NO_ATTACHMENT
350 %token MATCHER_SIGNED MATCHER_NOT_SIGNED
351 %token MATCHER_TAG MATCHER_NOT_TAG MATCHER_SET_TAG MATCHER_UNSET_TAG
352 %token MATCHER_TAGGED MATCHER_NOT_TAGGED MATCHER_CLEAR_TAGS
353
354 %start file
355
356 %token MATCHER_ENABLED MATCHER_DISABLED
357 %token MATCHER_RULENAME
358 %token MATCHER_ACCOUNT
359 %token <str> MATCHER_STRING
360 %token <str> MATCHER_SECTION
361 %token <str> MATCHER_INTEGER
362
363 %%
364
365 file:
366 {
367         if (matcher_parse_op == MATCHER_PARSE_FILE) {
368                 prefs_filtering = &pre_global_processing;
369         }
370 }
371 file_line_list;
372
373 file_line_list:
374 file_line
375 file_line_list
376 | file_line
377 ;
378
379 file_line:
380 section_notification
381
382 { action_list = NULL; }
383 instruction
384 | error MATCHER_EOL
385 {
386         yyerrok;
387 };
388
389 section_notification:
390 MATCHER_SECTION MATCHER_EOL
391 {
392         gchar *folder = $1;
393         FolderItem *item = NULL;
394
395         if (matcher_parse_op == MATCHER_PARSE_FILE) {
396                 enable_compatibility = 0;
397                 if (!strcmp(folder, "global")) {
398                         /* backward compatibility */
399                         enable_compatibility = 1;
400                 }
401                 else if (!strcmp(folder, "preglobal")) {
402                         prefs_filtering = &pre_global_processing;
403                 }
404                 else if (!strcmp(folder, "postglobal")) {
405                         prefs_filtering = &post_global_processing;
406                 }
407                 else if (!strcmp(folder, "filtering")) {
408                         prefs_filtering = &filtering_rules;
409                 }
410                 else {
411                         item = folder_find_item_from_identifier(folder);
412                         if (item != NULL) {
413                                 prefs_filtering = &item->prefs->processing;
414                         } else {
415                                 prefs_filtering = NULL;
416                         }
417                 }
418         }
419 }
420 ;
421
422 instruction:
423 enabled name account condition filtering MATCHER_EOL
424 | enabled name account condition filtering
425 | enabled name condition filtering MATCHER_EOL
426 | enabled name condition filtering
427 | name condition filtering MATCHER_EOL
428 | name condition filtering
429 {
430         if (matcher_parse_op == MATCHER_PARSE_NO_EOL)
431                 YYACCEPT;
432         else {
433                 matcher_parsererror("parse error [no eol]");
434                 YYERROR;
435         }
436 }
437 | enabled
438 {
439         if (matcher_parse_op == MATCHER_PARSE_ENABLED)
440                 YYACCEPT;
441         else {
442                 matcher_parsererror("parse error [enabled]");
443                 YYERROR;
444         }
445 }
446 | account
447 {
448         if (matcher_parse_op == MATCHER_PARSE_ACCOUNT)
449                 YYACCEPT;
450         else {
451                 matcher_parsererror("parse error [account]");
452                 YYERROR;
453         }
454 }
455 | name
456 {
457         if (matcher_parse_op == MATCHER_PARSE_NAME)
458                 YYACCEPT;
459         else {
460                 matcher_parsererror("parse error [name]");
461                 YYERROR;
462         }
463 }
464 | condition
465 {
466         if (matcher_parse_op == MATCHER_PARSE_CONDITION)
467                 YYACCEPT;
468         else {
469                 matcher_parsererror("parse error [condition]");
470                 YYERROR;
471         }
472 }
473 | filtering_action_list
474 {
475         if (matcher_parse_op == MATCHER_PARSE_FILTERING_ACTION)
476                 YYACCEPT;
477         else {
478                 matcher_parsererror("parse error [filtering action]");
479                 YYERROR;
480         }
481 }
482 | MATCHER_EOL
483 ;
484
485 enabled:
486 MATCHER_ENABLED
487 {
488         enabled = TRUE;
489 }
490 | MATCHER_DISABLED
491 {
492         enabled = FALSE;
493 }
494 ;
495
496 name:
497 MATCHER_RULENAME MATCHER_STRING
498 {
499         name = g_strdup($2);
500 }
501 ;
502
503 account:
504 MATCHER_ACCOUNT MATCHER_INTEGER
505 {
506         account_id = strtol($2, NULL, 10);
507 }
508 ;
509
510 filtering:
511 filtering_action_list
512 {
513         filtering = filteringprop_new(enabled, name, account_id, cond, action_list);
514         enabled = TRUE;
515         account_id = 0;
516         g_free(name);
517         name = NULL;
518         if (enable_compatibility) {
519                 prefs_filtering = &filtering_rules;
520                 if (action_list != NULL) {
521                         FilteringAction * first_action;
522                         
523                         first_action = action_list->data;
524                         
525                         if (first_action->type == MATCHACTION_CHANGE_SCORE)
526                                 prefs_filtering = &pre_global_processing;
527                 }
528         }
529         
530         cond = NULL;
531         action_list = NULL;
532         
533         if ((matcher_parse_op == MATCHER_PARSE_FILE) &&
534             (prefs_filtering != NULL)) {
535                 *prefs_filtering = g_slist_append(*prefs_filtering,
536                                                   filtering);
537                 filtering = NULL;
538         }
539 }
540 ;
541
542 filtering_action_list:
543 filtering_action_b filtering_action_list
544 | filtering_action_b
545 ;
546
547 filtering_action_b:
548 filtering_action
549 {
550         action_list = g_slist_append(action_list, action);
551         action = NULL;
552 }
553 ;
554
555 match_type:
556 MATCHER_MATCHCASE
557 {
558         match_type = MATCHTYPE_MATCHCASE;
559 }
560 | MATCHER_MATCH
561 {
562         match_type = MATCHTYPE_MATCH;
563 }
564 | MATCHER_REGEXPCASE
565 {
566         match_type = MATCHTYPE_REGEXPCASE;
567 }
568 | MATCHER_REGEXP
569 {
570         match_type = MATCHTYPE_REGEXP;
571 }
572 ;
573
574 condition:
575 condition_list
576 {
577         cond = matcherlist_new(matchers_list, (bool_op == MATCHERBOOL_AND));
578         matchers_list = NULL;
579 }
580 ;
581
582 condition_list:
583 condition_list bool_op one_condition
584 {
585         matchers_list = g_slist_append(matchers_list, prop);
586 }
587 | one_condition
588 {
589         matchers_list = NULL;
590         matchers_list = g_slist_append(matchers_list, prop);
591 }
592 ;
593
594 bool_op:
595 MATCHER_AND
596 {
597         bool_op = MATCHERBOOL_AND;
598 }
599 | MATCHER_OR
600 {
601         bool_op = MATCHERBOOL_OR;
602 }
603 ;
604
605 one_condition:
606 MATCHER_ALL
607 {
608         gint criteria = 0;
609
610         criteria = MATCHCRITERIA_ALL;
611         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
612 }
613 | MATCHER_UNREAD
614 {
615         gint criteria = 0;
616
617         criteria = MATCHCRITERIA_UNREAD;
618         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
619 }
620 | MATCHER_NOT_UNREAD 
621 {
622         gint criteria = 0;
623
624         criteria = MATCHCRITERIA_NOT_UNREAD;
625         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
626 }
627 | MATCHER_NEW
628 {
629         gint criteria = 0;
630
631         criteria = MATCHCRITERIA_NEW;
632         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
633 }
634 | MATCHER_NOT_NEW
635 {
636         gint criteria = 0;
637
638         criteria = MATCHCRITERIA_NOT_NEW;
639         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
640 }
641 | MATCHER_MARKED
642 {
643         gint criteria = 0;
644
645         criteria = MATCHCRITERIA_MARKED;
646         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
647 }
648 | MATCHER_NOT_MARKED
649 {
650         gint criteria = 0;
651
652         criteria = MATCHCRITERIA_NOT_MARKED;
653         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
654 }
655 | MATCHER_DELETED
656 {
657         gint criteria = 0;
658
659         criteria = MATCHCRITERIA_DELETED;
660         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
661 }
662 | MATCHER_NOT_DELETED
663 {
664         gint criteria = 0;
665
666         criteria = MATCHCRITERIA_NOT_DELETED;
667         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
668 }
669 | MATCHER_REPLIED
670 {
671         gint criteria = 0;
672
673         criteria = MATCHCRITERIA_REPLIED;
674         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
675 }
676 | MATCHER_NOT_REPLIED
677 {
678         gint criteria = 0;
679
680         criteria = MATCHCRITERIA_NOT_REPLIED;
681         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
682 }
683 | MATCHER_FORWARDED
684 {
685         gint criteria = 0;
686
687         criteria = MATCHCRITERIA_FORWARDED;
688         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
689 }
690 | MATCHER_NOT_FORWARDED
691 {
692         gint criteria = 0;
693
694         criteria = MATCHCRITERIA_NOT_FORWARDED;
695         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
696 }
697 | MATCHER_LOCKED
698 {
699         gint criteria = 0;
700
701         criteria = MATCHCRITERIA_LOCKED;
702         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
703 }
704 | MATCHER_NOT_LOCKED
705 {
706         gint criteria = 0;
707
708         criteria = MATCHCRITERIA_NOT_LOCKED;
709         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
710 }
711 | MATCHER_SPAM
712 {
713         gint criteria = 0;
714
715         criteria = MATCHCRITERIA_SPAM;
716         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
717 }
718 | MATCHER_NOT_SPAM 
719 {
720         gint criteria = 0;
721
722         criteria = MATCHCRITERIA_NOT_SPAM;
723         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
724 }
725 | MATCHER_HAS_ATTACHMENT
726 {
727         gint criteria = 0;
728
729         criteria = MATCHCRITERIA_HAS_ATTACHMENT;
730         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
731 }
732 | MATCHER_HAS_NO_ATTACHMENT
733 {
734         gint criteria = 0;
735
736         criteria = MATCHCRITERIA_HAS_NO_ATTACHMENT;
737         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
738 }
739 | MATCHER_SIGNED
740 {
741         gint criteria = 0;
742
743         criteria = MATCHCRITERIA_SIGNED;
744         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
745 }
746 | MATCHER_NOT_SIGNED
747 {
748         gint criteria = 0;
749
750         criteria = MATCHCRITERIA_NOT_SIGNED;
751         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
752 }
753 | MATCHER_PARTIAL
754 {
755         gint criteria = 0;
756
757         criteria = MATCHCRITERIA_PARTIAL;
758         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
759 }
760 | MATCHER_NOT_PARTIAL
761 {
762         gint criteria = 0;
763
764         criteria = MATCHCRITERIA_NOT_PARTIAL;
765         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
766 }
767 | MATCHER_COLORLABEL MATCHER_INTEGER
768 {
769         gint criteria = 0;
770         gint value = 0;
771
772         criteria = MATCHCRITERIA_COLORLABEL;
773         value = strtol($2, NULL, 10);
774         if (value < 0) value = 0;
775         else if (value > COLORLABELS) value = COLORLABELS;
776         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
777 }
778 | MATCHER_NOT_COLORLABEL MATCHER_INTEGER
779 {
780         gint criteria = 0;
781         gint value = 0;
782
783         criteria = MATCHCRITERIA_NOT_COLORLABEL;
784         value = strtol($2, NULL, 0);
785         if (value < 0) value = 0;
786         else if (value > COLORLABELS) value = COLORLABELS;
787         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
788 }
789 | MATCHER_IGNORE_THREAD
790 {
791         gint criteria = 0;
792
793         criteria = MATCHCRITERIA_IGNORE_THREAD;
794         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
795 }
796 | MATCHER_NOT_IGNORE_THREAD
797 {
798         gint criteria = 0;
799
800         criteria = MATCHCRITERIA_NOT_IGNORE_THREAD;
801         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
802 }
803 | MATCHER_WATCH_THREAD
804 {
805         gint criteria = 0;
806
807         criteria = MATCHCRITERIA_WATCH_THREAD;
808         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
809 }
810 | MATCHER_NOT_WATCH_THREAD
811 {
812         gint criteria = 0;
813
814         criteria = MATCHCRITERIA_NOT_WATCH_THREAD;
815         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
816 }
817 | MATCHER_SUBJECT match_type MATCHER_STRING
818 {
819         gint criteria = 0;
820         gchar *expr = NULL;
821
822         criteria = MATCHCRITERIA_SUBJECT;
823         expr = $3;
824         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
825 }
826 | MATCHER_NOT_SUBJECT match_type MATCHER_STRING
827 {
828         gint criteria = 0;
829         gchar *expr = NULL;
830
831         criteria = MATCHCRITERIA_NOT_SUBJECT;
832         expr = $3;
833         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
834 }
835 | MATCHER_FROM match_type MATCHER_STRING
836 {
837         gint criteria = 0;
838         gchar *expr = NULL;
839
840         criteria = MATCHCRITERIA_FROM;
841         expr = $3;
842         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
843 }
844 | MATCHER_NOT_FROM match_type MATCHER_STRING
845 {
846         gint criteria = 0;
847         gchar *expr = NULL;
848
849         criteria = MATCHCRITERIA_NOT_FROM;
850         expr = $3;
851         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
852 }
853 | MATCHER_TO match_type MATCHER_STRING
854 {
855         gint criteria = 0;
856         gchar *expr = NULL;
857
858         criteria = MATCHCRITERIA_TO;
859         expr = $3;
860         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
861 }
862 | MATCHER_NOT_TO match_type MATCHER_STRING
863 {
864         gint criteria = 0;
865         gchar *expr = NULL;
866
867         criteria = MATCHCRITERIA_NOT_TO;
868         expr = $3;
869         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
870 }
871 | MATCHER_CC match_type MATCHER_STRING
872 {
873         gint criteria = 0;
874         gchar *expr = NULL;
875
876         criteria = MATCHCRITERIA_CC;
877         expr = $3;
878         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
879 }
880 | MATCHER_NOT_CC match_type MATCHER_STRING
881 {
882         gint criteria = 0;
883         gchar *expr = NULL;
884
885         criteria = MATCHCRITERIA_NOT_CC;
886         expr = $3;
887         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
888 }
889 | MATCHER_TO_OR_CC match_type MATCHER_STRING
890 {
891         gint criteria = 0;
892         gchar *expr = NULL;
893
894         criteria = MATCHCRITERIA_TO_OR_CC;
895         expr = $3;
896         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
897 }
898 | MATCHER_NOT_TO_AND_NOT_CC match_type MATCHER_STRING
899 {
900         gint criteria = 0;
901         gchar *expr = NULL;
902
903         criteria = MATCHCRITERIA_NOT_TO_AND_NOT_CC;
904         expr = $3;
905         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
906 }
907 | MATCHER_TAG match_type MATCHER_STRING
908 {
909         gint criteria = 0;
910         gchar *expr = NULL;
911
912         criteria = MATCHCRITERIA_TAG;
913         expr = $3;
914         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
915 }
916 | MATCHER_NOT_TAG match_type MATCHER_STRING
917 {
918         gint criteria = 0;
919         gchar *expr = NULL;
920
921         criteria = MATCHCRITERIA_NOT_TAG;
922         expr = $3;
923         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
924 }
925 | MATCHER_TAGGED
926 {
927         gint criteria = 0;
928
929         criteria = MATCHCRITERIA_TAGGED;
930         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
931 }
932 | MATCHER_NOT_TAGGED
933 {
934         gint criteria = 0;
935
936         criteria = MATCHCRITERIA_NOT_TAGGED;
937         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
938 }
939 | MATCHER_AGE_GREATER MATCHER_INTEGER
940 {
941         gint criteria = 0;
942         gint value = 0;
943
944         criteria = MATCHCRITERIA_AGE_GREATER;
945         value = strtol($2, NULL, 0);
946         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
947 }
948 | MATCHER_AGE_LOWER MATCHER_INTEGER
949 {
950         gint criteria = 0;
951         gint value = 0;
952
953         criteria = MATCHCRITERIA_AGE_LOWER;
954         value = strtol($2, NULL, 0);
955         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
956 }
957 | MATCHER_AGE_GREATER_HOURS MATCHER_INTEGER
958 {
959         gint criteria = 0;
960         gint value = 0;
961
962         criteria = MATCHCRITERIA_AGE_GREATER_HOURS;
963         value = strtol($2, NULL, 0);
964         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
965 }
966 | MATCHER_AGE_LOWER_HOURS MATCHER_INTEGER
967 {
968         gint criteria = 0;
969         gint value = 0;
970
971         criteria = MATCHCRITERIA_AGE_LOWER_HOURS;
972         value = strtol($2, NULL, 0);
973         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
974 }
975 | MATCHER_NEWSGROUPS match_type MATCHER_STRING
976 {
977         gint criteria = 0;
978         gchar *expr = NULL;
979
980         criteria = MATCHCRITERIA_NEWSGROUPS;
981         expr = $3;
982         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
983 }
984 | MATCHER_NOT_NEWSGROUPS match_type MATCHER_STRING
985 {
986         gint criteria = 0;
987         gchar *expr = NULL;
988
989         criteria = MATCHCRITERIA_NOT_NEWSGROUPS;
990         expr = $3;
991         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
992 }
993 | MATCHER_INREPLYTO match_type MATCHER_STRING
994 {
995         gint criteria = 0;
996         gchar *expr = NULL;
997
998         criteria = MATCHCRITERIA_INREPLYTO;
999         expr = $3;
1000         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1001 }
1002 | MATCHER_NOT_INREPLYTO match_type MATCHER_STRING
1003 {
1004         gint criteria = 0;
1005         gchar *expr = NULL;
1006
1007         criteria = MATCHCRITERIA_NOT_INREPLYTO;
1008         expr = $3;
1009         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1010 }
1011 | MATCHER_REFERENCES match_type MATCHER_STRING
1012 {
1013         gint criteria = 0;
1014         gchar *expr = NULL;
1015
1016         criteria = MATCHCRITERIA_REFERENCES;
1017         expr = $3;
1018         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1019 }
1020 | MATCHER_NOT_REFERENCES match_type MATCHER_STRING
1021 {
1022         gint criteria = 0;
1023         gchar *expr = NULL;
1024
1025         criteria = MATCHCRITERIA_NOT_REFERENCES;
1026         expr = $3;
1027         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1028 }
1029 | MATCHER_SCORE_GREATER MATCHER_INTEGER
1030 {
1031         gint criteria = 0;
1032         gint value = 0;
1033
1034         criteria = MATCHCRITERIA_SCORE_GREATER;
1035         value = strtol($2, NULL, 0);
1036         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1037 }
1038 | MATCHER_SCORE_LOWER MATCHER_INTEGER
1039 {
1040         gint criteria = 0;
1041         gint value = 0;
1042
1043         criteria = MATCHCRITERIA_SCORE_LOWER;
1044         value = strtol($2, NULL, 0);
1045         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1046 }
1047 | MATCHER_SCORE_EQUAL MATCHER_INTEGER
1048 {
1049         gint criteria = 0;
1050         gint value = 0;
1051
1052         criteria = MATCHCRITERIA_SCORE_EQUAL;
1053         value = strtol($2, NULL, 0);
1054         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1055 }
1056 | MATCHER_SIZE_GREATER MATCHER_INTEGER 
1057 {
1058         gint criteria = 0;
1059         gint value    = 0;
1060         criteria = MATCHCRITERIA_SIZE_GREATER;
1061         value = strtol($2, NULL, 0);
1062         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1063 }
1064 | MATCHER_SIZE_SMALLER MATCHER_INTEGER
1065 {
1066         gint criteria = 0;
1067         gint value    = 0;
1068         criteria = MATCHCRITERIA_SIZE_SMALLER;
1069         value = strtol($2, NULL, 0);
1070         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1071 }
1072 | MATCHER_SIZE_EQUAL MATCHER_INTEGER
1073 {
1074         gint criteria = 0;
1075         gint value    = 0;
1076         criteria = MATCHCRITERIA_SIZE_EQUAL;
1077         value = strtol($2, NULL, 0);
1078         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1079 }
1080 | MATCHER_HEADER MATCHER_STRING
1081 {
1082         header = g_strdup($2);
1083 } match_type MATCHER_STRING
1084 {
1085         gint criteria = 0;
1086         gchar *expr = NULL;
1087         matcher_is_fast = FALSE;
1088         criteria = MATCHCRITERIA_HEADER;
1089         expr = $2;
1090         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1091         g_free(header);
1092 }
1093 | MATCHER_NOT_HEADER MATCHER_STRING
1094 {
1095         header = g_strdup($2);
1096 } match_type MATCHER_STRING
1097 {
1098         gint criteria = 0;
1099         gchar *expr = NULL;
1100         matcher_is_fast = FALSE;
1101         criteria = MATCHCRITERIA_NOT_HEADER;
1102         expr = $2;
1103         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1104         g_free(header);
1105 }
1106 | MATCHER_HEADERS_PART match_type MATCHER_STRING
1107 {
1108         gint criteria = 0;
1109         gchar *expr = NULL;
1110         matcher_is_fast = FALSE;
1111         criteria = MATCHCRITERIA_HEADERS_PART;
1112         expr = $3;
1113         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1114 }
1115 | MATCHER_NOT_HEADERS_PART match_type MATCHER_STRING
1116 {
1117         gint criteria = 0;
1118         gchar *expr = NULL;
1119         matcher_is_fast = FALSE;
1120         criteria = MATCHCRITERIA_NOT_HEADERS_PART;
1121         expr = $3;
1122         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1123 }
1124 | MATCHER_FOUND_IN_ADDRESSBOOK MATCHER_STRING
1125 {
1126         header = g_strdup($2);
1127 } MATCHER_IN MATCHER_STRING
1128 {
1129         gint criteria = 0;
1130         gchar *expr = NULL;
1131
1132         criteria = MATCHCRITERIA_FOUND_IN_ADDRESSBOOK;
1133         expr = $2;
1134         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1135         g_free(header);
1136 }
1137 | MATCHER_NOT_FOUND_IN_ADDRESSBOOK MATCHER_STRING
1138 {
1139         header = g_strdup($2);
1140 } MATCHER_IN MATCHER_STRING
1141 {
1142         gint criteria = 0;
1143         gchar *expr = NULL;
1144
1145         criteria = MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK;
1146         expr = $2;
1147         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1148         g_free(header);
1149 }
1150 | MATCHER_MESSAGE match_type MATCHER_STRING
1151 {
1152         gint criteria = 0;
1153         gchar *expr = NULL;
1154         matcher_is_fast = FALSE;
1155         criteria = MATCHCRITERIA_MESSAGE;
1156         expr = $3;
1157         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1158 }
1159 | MATCHER_NOT_MESSAGE match_type MATCHER_STRING
1160 {
1161         gint criteria = 0;
1162         gchar *expr = NULL;
1163         matcher_is_fast = FALSE;
1164         criteria = MATCHCRITERIA_NOT_MESSAGE;
1165         expr = $3;
1166         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1167 }
1168 | MATCHER_BODY_PART match_type MATCHER_STRING
1169 {
1170         gint criteria = 0;
1171         gchar *expr = NULL;
1172         matcher_is_fast = FALSE;
1173         criteria = MATCHCRITERIA_BODY_PART;
1174         expr = $3;
1175         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1176 }
1177 | MATCHER_NOT_BODY_PART match_type MATCHER_STRING
1178 {
1179         gint criteria = 0;
1180         gchar *expr = NULL;
1181         matcher_is_fast = FALSE;
1182         criteria = MATCHCRITERIA_NOT_BODY_PART;
1183         expr = $3;
1184         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1185 }
1186 | MATCHER_TEST MATCHER_STRING
1187 {
1188         gint criteria = 0;
1189         gchar *expr = NULL;
1190         matcher_is_fast = FALSE;
1191         criteria = MATCHCRITERIA_TEST;
1192         expr = $2;
1193         prop = matcherprop_new(criteria, NULL, MATCHTYPE_MATCH, expr, 0);
1194 }
1195 | MATCHER_NOT_TEST MATCHER_STRING
1196 {
1197         gint criteria = 0;
1198         gchar *expr = NULL;
1199         matcher_is_fast = FALSE;
1200         criteria = MATCHCRITERIA_NOT_TEST;
1201         expr = $2;
1202         prop = matcherprop_new(criteria, NULL, MATCHTYPE_MATCH, expr, 0);
1203 }
1204 ;
1205
1206 filtering_action:
1207 MATCHER_EXECUTE MATCHER_STRING
1208 {
1209         gchar *cmd = NULL;
1210         gint action_type = 0;
1211
1212         action_type = MATCHACTION_EXECUTE;
1213         cmd = $2;
1214         action = filteringaction_new(action_type, 0, cmd, 0, 0, NULL);
1215 }
1216 | MATCHER_MOVE MATCHER_STRING
1217 {
1218         gchar *destination = NULL;
1219         gint action_type = 0;
1220
1221         action_type = MATCHACTION_MOVE;
1222         destination = $2;
1223         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1224 }
1225 | MATCHER_SET_TAG MATCHER_STRING
1226 {
1227         gchar *destination = NULL;
1228         gint action_type = 0;
1229
1230         action_type = MATCHACTION_SET_TAG;
1231         destination = $2;
1232         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1233 }
1234 | MATCHER_UNSET_TAG MATCHER_STRING
1235 {
1236         gchar *destination = NULL;
1237         gint action_type = 0;
1238
1239         action_type = MATCHACTION_UNSET_TAG;
1240         destination = $2;
1241         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1242 }
1243 | MATCHER_CLEAR_TAGS
1244 {
1245         gint action_type = 0;
1246
1247         action_type = MATCHACTION_CLEAR_TAGS;
1248         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1249 }
1250 | MATCHER_COPY MATCHER_STRING
1251 {
1252         gchar *destination = NULL;
1253         gint action_type = 0;
1254
1255         action_type = MATCHACTION_COPY;
1256         destination = $2;
1257         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1258 }
1259 | MATCHER_DELETE
1260 {
1261         gint action_type = 0;
1262
1263         action_type = MATCHACTION_DELETE;
1264         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1265 }
1266 | MATCHER_MARK
1267 {
1268         gint action_type = 0;
1269
1270         action_type = MATCHACTION_MARK;
1271         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1272 }
1273 | MATCHER_UNMARK
1274 {
1275         gint action_type = 0;
1276
1277         action_type = MATCHACTION_UNMARK;
1278         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1279 }
1280 | MATCHER_LOCK
1281 {
1282         gint action_type = 0;
1283
1284         action_type = MATCHACTION_LOCK;
1285         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1286 }
1287 | MATCHER_UNLOCK
1288 {
1289         gint action_type = 0;
1290
1291         action_type = MATCHACTION_UNLOCK;
1292         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1293 }
1294 | MATCHER_MARK_AS_READ
1295 {
1296         gint action_type = 0;
1297
1298         action_type = MATCHACTION_MARK_AS_READ;
1299         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1300 }
1301 | MATCHER_MARK_AS_UNREAD
1302 {
1303         gint action_type = 0;
1304
1305         action_type = MATCHACTION_MARK_AS_UNREAD;
1306         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1307 }
1308 | MATCHER_MARK_AS_SPAM
1309 {
1310         gint action_type = 0;
1311
1312         action_type = MATCHACTION_MARK_AS_SPAM;
1313         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1314 }
1315 | MATCHER_MARK_AS_HAM
1316 {
1317         gint action_type = 0;
1318
1319         action_type = MATCHACTION_MARK_AS_HAM;
1320         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1321 }
1322 | MATCHER_FORWARD MATCHER_INTEGER MATCHER_STRING
1323 {
1324         gchar *destination = NULL;
1325         gint action_type = 0;
1326         gint account_id = 0;
1327
1328         action_type = MATCHACTION_FORWARD;
1329         account_id = strtol($2, NULL, 10);
1330         destination = $3;
1331         action = filteringaction_new(action_type,
1332             account_id, destination, 0, 0, NULL);
1333 }
1334 | MATCHER_FORWARD_AS_ATTACHMENT MATCHER_INTEGER MATCHER_STRING
1335 {
1336         gchar *destination = NULL;
1337         gint action_type = 0;
1338         gint account_id = 0;
1339
1340         action_type = MATCHACTION_FORWARD_AS_ATTACHMENT;
1341         account_id = strtol($2, NULL, 10);
1342         destination = $3;
1343         action = filteringaction_new(action_type,
1344             account_id, destination, 0, 0, NULL);
1345 }
1346 | MATCHER_REDIRECT MATCHER_INTEGER MATCHER_STRING
1347 {
1348         gchar *destination = NULL;
1349         gint action_type = 0;
1350         gint account_id = 0;
1351
1352         action_type = MATCHACTION_REDIRECT;
1353         account_id = strtol($2, NULL, 10);
1354         destination = $3;
1355         action = filteringaction_new(action_type,
1356             account_id, destination, 0, 0, NULL);
1357 }
1358 | MATCHER_COLOR MATCHER_INTEGER
1359 {
1360         gint action_type = 0;
1361         gint color = 0;
1362
1363         action_type = MATCHACTION_COLOR;
1364         color = strtol($2, NULL, 10);
1365         action = filteringaction_new(action_type, 0, NULL, color, 0, NULL);
1366 }
1367 | MATCHER_CHANGE_SCORE MATCHER_INTEGER
1368 {
1369         gint score = 0;
1370         
1371         score = strtol($2, NULL, 10);
1372         action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
1373                                      NULL, 0, score, NULL);
1374 }
1375 /* backward compatibility */
1376 | MATCHER_SCORE MATCHER_INTEGER
1377 {
1378         gint score = 0;
1379         
1380         score = strtol($2, NULL, 10);
1381         action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
1382                                      NULL, 0, score, NULL);
1383 }
1384 | MATCHER_SET_SCORE MATCHER_INTEGER
1385 {
1386         gint score = 0;
1387         
1388         score = strtol($2, NULL, 10);
1389         action = filteringaction_new(MATCHACTION_SET_SCORE, 0,
1390                                      NULL, 0, score, NULL);
1391 }
1392 | MATCHER_HIDE
1393 {
1394         action = filteringaction_new(MATCHACTION_HIDE, 0, NULL, 0, 0, NULL);
1395 }
1396 | MATCHER_IGNORE
1397 {
1398         action = filteringaction_new(MATCHACTION_IGNORE, 0, NULL, 0, 0, NULL);
1399 }
1400 | MATCHER_WATCH
1401 {
1402         action = filteringaction_new(MATCHACTION_WATCH, 0, NULL, 0, 0, NULL);
1403 }
1404 | MATCHER_ADD_TO_ADDRESSBOOK MATCHER_STRING
1405 {
1406         header = g_strdup($2);
1407 } MATCHER_STRING
1408 {
1409         gchar *addressbook = NULL;
1410         gint action_type = 0;
1411
1412         action_type = MATCHACTION_ADD_TO_ADDRESSBOOK;
1413         addressbook = $2;
1414         action = filteringaction_new(action_type, 0, addressbook, 0, 0, header);
1415         g_free(header);
1416 }
1417 | MATCHER_STOP
1418 {
1419         action = filteringaction_new(MATCHACTION_STOP, 0, NULL, 0, 0, NULL);
1420 }
1421 ;