RSSyl: use procheader_date_parse() instead of parseRFC822Date().
[claws.git] / src / matcher_parser_parse.y
1 %{
2 /*
3  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
4  * Copyright (c) 2001-2014 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_HEADERS_CONT  MATCHER_NOT_HEADERS_CONT
328 %token MATCHER_NOT_MESSAGE  MATCHER_BODY_PART  MATCHER_NOT_BODY_PART
329 %token MATCHER_TEST  MATCHER_NOT_TEST  MATCHER_MATCHCASE  MATCHER_MATCH
330 %token MATCHER_REGEXPCASE  MATCHER_REGEXP  MATCHER_SCORE  MATCHER_MOVE
331 %token MATCHER_FOUND_IN_ADDRESSBOOK MATCHER_NOT_FOUND_IN_ADDRESSBOOK MATCHER_IN
332 %token MATCHER_COPY  MATCHER_DELETE  MATCHER_MARK  MATCHER_UNMARK
333 %token MATCHER_LOCK MATCHER_UNLOCK
334 %token MATCHER_EXECUTE
335 %token MATCHER_MARK_AS_READ  MATCHER_MARK_AS_UNREAD  MATCHER_FORWARD
336 %token MATCHER_MARK_AS_SPAM MATCHER_MARK_AS_HAM
337 %token MATCHER_FORWARD_AS_ATTACHMENT  MATCHER_EOL
338 %token MATCHER_OR MATCHER_AND  
339 %token MATCHER_COLOR MATCHER_SCORE_EQUAL MATCHER_REDIRECT 
340 %token MATCHER_SIZE_GREATER MATCHER_SIZE_SMALLER MATCHER_SIZE_EQUAL
341 %token MATCHER_LOCKED MATCHER_NOT_LOCKED
342 %token MATCHER_PARTIAL MATCHER_NOT_PARTIAL
343 %token MATCHER_COLORLABEL MATCHER_NOT_COLORLABEL
344 %token MATCHER_IGNORE_THREAD MATCHER_NOT_IGNORE_THREAD
345 %token MATCHER_WATCH_THREAD MATCHER_NOT_WATCH_THREAD
346 %token MATCHER_CHANGE_SCORE MATCHER_SET_SCORE
347 %token MATCHER_ADD_TO_ADDRESSBOOK
348 %token MATCHER_STOP MATCHER_HIDE MATCHER_IGNORE MATCHER_WATCH
349 %token MATCHER_SPAM MATCHER_NOT_SPAM
350 %token MATCHER_HAS_ATTACHMENT MATCHER_HAS_NO_ATTACHMENT
351 %token MATCHER_SIGNED MATCHER_NOT_SIGNED
352 %token MATCHER_TAG MATCHER_NOT_TAG MATCHER_SET_TAG MATCHER_UNSET_TAG
353 %token MATCHER_TAGGED MATCHER_NOT_TAGGED MATCHER_CLEAR_TAGS
354
355 %start file
356
357 %token MATCHER_ENABLED MATCHER_DISABLED
358 %token MATCHER_RULENAME
359 %token MATCHER_ACCOUNT
360 %token <str> MATCHER_STRING
361 %token <str> MATCHER_SECTION
362 %token <str> MATCHER_INTEGER
363
364 %%
365
366 file:
367 {
368         if (matcher_parse_op == MATCHER_PARSE_FILE) {
369                 prefs_filtering = &pre_global_processing;
370         }
371 }
372 file_line_list;
373
374 file_line_list:
375 file_line
376 file_line_list
377 | file_line
378 ;
379
380 file_line:
381 section_notification
382
383 { action_list = NULL; }
384 instruction
385 | error MATCHER_EOL
386 {
387         yyerrok;
388 };
389
390 section_notification:
391 MATCHER_SECTION MATCHER_EOL
392 {
393         gchar *folder = $1;
394         FolderItem *item = NULL;
395
396         if (matcher_parse_op == MATCHER_PARSE_FILE) {
397                 enable_compatibility = 0;
398                 if (!strcmp(folder, "global")) {
399                         /* backward compatibility */
400                         enable_compatibility = 1;
401                 }
402                 else if (!strcmp(folder, "preglobal")) {
403                         prefs_filtering = &pre_global_processing;
404                 }
405                 else if (!strcmp(folder, "postglobal")) {
406                         prefs_filtering = &post_global_processing;
407                 }
408                 else if (!strcmp(folder, "filtering")) {
409                         prefs_filtering = &filtering_rules;
410                 }
411                 else {
412                         item = folder_find_item_from_identifier(folder);
413                         if (item != NULL) {
414                                 prefs_filtering = &item->prefs->processing;
415                         } else {
416                                 prefs_filtering = NULL;
417                         }
418                 }
419         }
420 }
421 ;
422
423 instruction:
424 enabled name account condition filtering MATCHER_EOL
425 | enabled name account condition filtering
426 | enabled name condition filtering MATCHER_EOL
427 | enabled name condition filtering
428 | name condition filtering MATCHER_EOL
429 | name condition filtering
430 {
431         if (matcher_parse_op == MATCHER_PARSE_NO_EOL)
432                 YYACCEPT;
433         else {
434                 matcher_parsererror("parse error [no eol]");
435                 YYERROR;
436         }
437 }
438 | enabled
439 {
440         if (matcher_parse_op == MATCHER_PARSE_ENABLED)
441                 YYACCEPT;
442         else {
443                 matcher_parsererror("parse error [enabled]");
444                 YYERROR;
445         }
446 }
447 | account
448 {
449         if (matcher_parse_op == MATCHER_PARSE_ACCOUNT)
450                 YYACCEPT;
451         else {
452                 matcher_parsererror("parse error [account]");
453                 YYERROR;
454         }
455 }
456 | name
457 {
458         if (matcher_parse_op == MATCHER_PARSE_NAME)
459                 YYACCEPT;
460         else {
461                 matcher_parsererror("parse error [name]");
462                 YYERROR;
463         }
464 }
465 | condition
466 {
467         if (matcher_parse_op == MATCHER_PARSE_CONDITION)
468                 YYACCEPT;
469         else {
470                 matcher_parsererror("parse error [condition]");
471                 YYERROR;
472         }
473 }
474 | filtering_action_list
475 {
476         if (matcher_parse_op == MATCHER_PARSE_FILTERING_ACTION)
477                 YYACCEPT;
478         else {
479                 matcher_parsererror("parse error [filtering action]");
480                 YYERROR;
481         }
482 }
483 | MATCHER_EOL
484 ;
485
486 enabled:
487 MATCHER_ENABLED
488 {
489         enabled = TRUE;
490 }
491 | MATCHER_DISABLED
492 {
493         enabled = FALSE;
494 }
495 ;
496
497 name:
498 MATCHER_RULENAME MATCHER_STRING
499 {
500         name = g_strdup($2);
501 }
502 ;
503
504 account:
505 MATCHER_ACCOUNT MATCHER_INTEGER
506 {
507         account_id = strtol($2, NULL, 10);
508 }
509 ;
510
511 filtering:
512 filtering_action_list
513 {
514         filtering = filteringprop_new(enabled, name, account_id, cond, action_list);
515         enabled = TRUE;
516         account_id = 0;
517         g_free(name);
518         name = NULL;
519         if (enable_compatibility) {
520                 prefs_filtering = &filtering_rules;
521                 if (action_list != NULL) {
522                         FilteringAction * first_action;
523                         
524                         first_action = action_list->data;
525                         
526                         if (first_action->type == MATCHACTION_CHANGE_SCORE)
527                                 prefs_filtering = &pre_global_processing;
528                 }
529         }
530         
531         cond = NULL;
532         action_list = NULL;
533         
534         if ((matcher_parse_op == MATCHER_PARSE_FILE) &&
535             (prefs_filtering != NULL)) {
536                 *prefs_filtering = g_slist_append(*prefs_filtering,
537                                                   filtering);
538                 filtering = NULL;
539         }
540 }
541 ;
542
543 filtering_action_list:
544 filtering_action_b filtering_action_list
545 | filtering_action_b
546 ;
547
548 filtering_action_b:
549 filtering_action
550 {
551         action_list = g_slist_append(action_list, action);
552         action = NULL;
553 }
554 ;
555
556 match_type:
557 MATCHER_MATCHCASE
558 {
559         match_type = MATCHTYPE_MATCHCASE;
560 }
561 | MATCHER_MATCH
562 {
563         match_type = MATCHTYPE_MATCH;
564 }
565 | MATCHER_REGEXPCASE
566 {
567         match_type = MATCHTYPE_REGEXPCASE;
568 }
569 | MATCHER_REGEXP
570 {
571         match_type = MATCHTYPE_REGEXP;
572 }
573 ;
574
575 condition:
576 condition_list
577 {
578         cond = matcherlist_new(matchers_list, (bool_op == MATCHERBOOL_AND));
579         matchers_list = NULL;
580 }
581 ;
582
583 condition_list:
584 condition_list bool_op one_condition
585 {
586         matchers_list = g_slist_append(matchers_list, prop);
587 }
588 | one_condition
589 {
590         matchers_list = NULL;
591         matchers_list = g_slist_append(matchers_list, prop);
592 }
593 ;
594
595 bool_op:
596 MATCHER_AND
597 {
598         bool_op = MATCHERBOOL_AND;
599 }
600 | MATCHER_OR
601 {
602         bool_op = MATCHERBOOL_OR;
603 }
604 ;
605
606 one_condition:
607 MATCHER_ALL
608 {
609         gint criteria = 0;
610
611         criteria = MATCHCRITERIA_ALL;
612         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
613 }
614 | MATCHER_UNREAD
615 {
616         gint criteria = 0;
617
618         criteria = MATCHCRITERIA_UNREAD;
619         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
620 }
621 | MATCHER_NOT_UNREAD 
622 {
623         gint criteria = 0;
624
625         criteria = MATCHCRITERIA_NOT_UNREAD;
626         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
627 }
628 | MATCHER_NEW
629 {
630         gint criteria = 0;
631
632         criteria = MATCHCRITERIA_NEW;
633         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
634 }
635 | MATCHER_NOT_NEW
636 {
637         gint criteria = 0;
638
639         criteria = MATCHCRITERIA_NOT_NEW;
640         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
641 }
642 | MATCHER_MARKED
643 {
644         gint criteria = 0;
645
646         criteria = MATCHCRITERIA_MARKED;
647         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
648 }
649 | MATCHER_NOT_MARKED
650 {
651         gint criteria = 0;
652
653         criteria = MATCHCRITERIA_NOT_MARKED;
654         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
655 }
656 | MATCHER_DELETED
657 {
658         gint criteria = 0;
659
660         criteria = MATCHCRITERIA_DELETED;
661         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
662 }
663 | MATCHER_NOT_DELETED
664 {
665         gint criteria = 0;
666
667         criteria = MATCHCRITERIA_NOT_DELETED;
668         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
669 }
670 | MATCHER_REPLIED
671 {
672         gint criteria = 0;
673
674         criteria = MATCHCRITERIA_REPLIED;
675         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
676 }
677 | MATCHER_NOT_REPLIED
678 {
679         gint criteria = 0;
680
681         criteria = MATCHCRITERIA_NOT_REPLIED;
682         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
683 }
684 | MATCHER_FORWARDED
685 {
686         gint criteria = 0;
687
688         criteria = MATCHCRITERIA_FORWARDED;
689         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
690 }
691 | MATCHER_NOT_FORWARDED
692 {
693         gint criteria = 0;
694
695         criteria = MATCHCRITERIA_NOT_FORWARDED;
696         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
697 }
698 | MATCHER_LOCKED
699 {
700         gint criteria = 0;
701
702         criteria = MATCHCRITERIA_LOCKED;
703         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
704 }
705 | MATCHER_NOT_LOCKED
706 {
707         gint criteria = 0;
708
709         criteria = MATCHCRITERIA_NOT_LOCKED;
710         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
711 }
712 | MATCHER_SPAM
713 {
714         gint criteria = 0;
715
716         criteria = MATCHCRITERIA_SPAM;
717         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
718 }
719 | MATCHER_NOT_SPAM 
720 {
721         gint criteria = 0;
722
723         criteria = MATCHCRITERIA_NOT_SPAM;
724         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
725 }
726 | MATCHER_HAS_ATTACHMENT
727 {
728         gint criteria = 0;
729
730         criteria = MATCHCRITERIA_HAS_ATTACHMENT;
731         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
732 }
733 | MATCHER_HAS_NO_ATTACHMENT
734 {
735         gint criteria = 0;
736
737         criteria = MATCHCRITERIA_HAS_NO_ATTACHMENT;
738         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
739 }
740 | MATCHER_SIGNED
741 {
742         gint criteria = 0;
743
744         criteria = MATCHCRITERIA_SIGNED;
745         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
746 }
747 | MATCHER_NOT_SIGNED
748 {
749         gint criteria = 0;
750
751         criteria = MATCHCRITERIA_NOT_SIGNED;
752         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
753 }
754 | MATCHER_PARTIAL
755 {
756         gint criteria = 0;
757
758         criteria = MATCHCRITERIA_PARTIAL;
759         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
760 }
761 | MATCHER_NOT_PARTIAL
762 {
763         gint criteria = 0;
764
765         criteria = MATCHCRITERIA_NOT_PARTIAL;
766         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
767 }
768 | MATCHER_COLORLABEL MATCHER_INTEGER
769 {
770         gint criteria = 0;
771         gint value = 0;
772
773         criteria = MATCHCRITERIA_COLORLABEL;
774         value = strtol($2, NULL, 10);
775         if (value < 0) value = 0;
776         else if (value > COLORLABELS) value = COLORLABELS;
777         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
778 }
779 | MATCHER_NOT_COLORLABEL MATCHER_INTEGER
780 {
781         gint criteria = 0;
782         gint value = 0;
783
784         criteria = MATCHCRITERIA_NOT_COLORLABEL;
785         value = strtol($2, NULL, 0);
786         if (value < 0) value = 0;
787         else if (value > COLORLABELS) value = COLORLABELS;
788         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
789 }
790 | MATCHER_IGNORE_THREAD
791 {
792         gint criteria = 0;
793
794         criteria = MATCHCRITERIA_IGNORE_THREAD;
795         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
796 }
797 | MATCHER_NOT_IGNORE_THREAD
798 {
799         gint criteria = 0;
800
801         criteria = MATCHCRITERIA_NOT_IGNORE_THREAD;
802         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
803 }
804 | MATCHER_WATCH_THREAD
805 {
806         gint criteria = 0;
807
808         criteria = MATCHCRITERIA_WATCH_THREAD;
809         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
810 }
811 | MATCHER_NOT_WATCH_THREAD
812 {
813         gint criteria = 0;
814
815         criteria = MATCHCRITERIA_NOT_WATCH_THREAD;
816         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
817 }
818 | MATCHER_SUBJECT match_type MATCHER_STRING
819 {
820         gint criteria = 0;
821         gchar *expr = NULL;
822
823         criteria = MATCHCRITERIA_SUBJECT;
824         expr = $3;
825         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
826 }
827 | MATCHER_NOT_SUBJECT match_type MATCHER_STRING
828 {
829         gint criteria = 0;
830         gchar *expr = NULL;
831
832         criteria = MATCHCRITERIA_NOT_SUBJECT;
833         expr = $3;
834         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
835 }
836 | MATCHER_FROM match_type MATCHER_STRING
837 {
838         gint criteria = 0;
839         gchar *expr = NULL;
840
841         criteria = MATCHCRITERIA_FROM;
842         expr = $3;
843         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
844 }
845 | MATCHER_NOT_FROM match_type MATCHER_STRING
846 {
847         gint criteria = 0;
848         gchar *expr = NULL;
849
850         criteria = MATCHCRITERIA_NOT_FROM;
851         expr = $3;
852         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
853 }
854 | MATCHER_TO match_type MATCHER_STRING
855 {
856         gint criteria = 0;
857         gchar *expr = NULL;
858
859         criteria = MATCHCRITERIA_TO;
860         expr = $3;
861         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
862 }
863 | MATCHER_NOT_TO match_type MATCHER_STRING
864 {
865         gint criteria = 0;
866         gchar *expr = NULL;
867
868         criteria = MATCHCRITERIA_NOT_TO;
869         expr = $3;
870         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
871 }
872 | MATCHER_CC match_type MATCHER_STRING
873 {
874         gint criteria = 0;
875         gchar *expr = NULL;
876
877         criteria = MATCHCRITERIA_CC;
878         expr = $3;
879         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
880 }
881 | MATCHER_NOT_CC match_type MATCHER_STRING
882 {
883         gint criteria = 0;
884         gchar *expr = NULL;
885
886         criteria = MATCHCRITERIA_NOT_CC;
887         expr = $3;
888         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
889 }
890 | MATCHER_TO_OR_CC match_type MATCHER_STRING
891 {
892         gint criteria = 0;
893         gchar *expr = NULL;
894
895         criteria = MATCHCRITERIA_TO_OR_CC;
896         expr = $3;
897         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
898 }
899 | MATCHER_NOT_TO_AND_NOT_CC match_type MATCHER_STRING
900 {
901         gint criteria = 0;
902         gchar *expr = NULL;
903
904         criteria = MATCHCRITERIA_NOT_TO_AND_NOT_CC;
905         expr = $3;
906         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
907 }
908 | MATCHER_TAG match_type MATCHER_STRING
909 {
910         gint criteria = 0;
911         gchar *expr = NULL;
912
913         criteria = MATCHCRITERIA_TAG;
914         expr = $3;
915         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
916 }
917 | MATCHER_NOT_TAG match_type MATCHER_STRING
918 {
919         gint criteria = 0;
920         gchar *expr = NULL;
921
922         criteria = MATCHCRITERIA_NOT_TAG;
923         expr = $3;
924         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
925 }
926 | MATCHER_TAGGED
927 {
928         gint criteria = 0;
929
930         criteria = MATCHCRITERIA_TAGGED;
931         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
932 }
933 | MATCHER_NOT_TAGGED
934 {
935         gint criteria = 0;
936
937         criteria = MATCHCRITERIA_NOT_TAGGED;
938         prop = matcherprop_new(criteria, NULL, 0, NULL, 0);
939 }
940 | MATCHER_AGE_GREATER MATCHER_INTEGER
941 {
942         gint criteria = 0;
943         gint value = 0;
944
945         criteria = MATCHCRITERIA_AGE_GREATER;
946         value = strtol($2, NULL, 0);
947         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
948 }
949 | MATCHER_AGE_LOWER MATCHER_INTEGER
950 {
951         gint criteria = 0;
952         gint value = 0;
953
954         criteria = MATCHCRITERIA_AGE_LOWER;
955         value = strtol($2, NULL, 0);
956         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
957 }
958 | MATCHER_AGE_GREATER_HOURS MATCHER_INTEGER
959 {
960         gint criteria = 0;
961         gint value = 0;
962
963         criteria = MATCHCRITERIA_AGE_GREATER_HOURS;
964         value = strtol($2, NULL, 0);
965         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
966 }
967 | MATCHER_AGE_LOWER_HOURS MATCHER_INTEGER
968 {
969         gint criteria = 0;
970         gint value = 0;
971
972         criteria = MATCHCRITERIA_AGE_LOWER_HOURS;
973         value = strtol($2, NULL, 0);
974         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
975 }
976 | MATCHER_NEWSGROUPS match_type MATCHER_STRING
977 {
978         gint criteria = 0;
979         gchar *expr = NULL;
980
981         criteria = MATCHCRITERIA_NEWSGROUPS;
982         expr = $3;
983         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
984 }
985 | MATCHER_NOT_NEWSGROUPS match_type MATCHER_STRING
986 {
987         gint criteria = 0;
988         gchar *expr = NULL;
989
990         criteria = MATCHCRITERIA_NOT_NEWSGROUPS;
991         expr = $3;
992         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
993 }
994 | MATCHER_INREPLYTO match_type MATCHER_STRING
995 {
996         gint criteria = 0;
997         gchar *expr = NULL;
998
999         criteria = MATCHCRITERIA_INREPLYTO;
1000         expr = $3;
1001         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1002 }
1003 | MATCHER_NOT_INREPLYTO match_type MATCHER_STRING
1004 {
1005         gint criteria = 0;
1006         gchar *expr = NULL;
1007
1008         criteria = MATCHCRITERIA_NOT_INREPLYTO;
1009         expr = $3;
1010         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1011 }
1012 | MATCHER_REFERENCES match_type MATCHER_STRING
1013 {
1014         gint criteria = 0;
1015         gchar *expr = NULL;
1016
1017         criteria = MATCHCRITERIA_REFERENCES;
1018         expr = $3;
1019         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1020 }
1021 | MATCHER_NOT_REFERENCES match_type MATCHER_STRING
1022 {
1023         gint criteria = 0;
1024         gchar *expr = NULL;
1025
1026         criteria = MATCHCRITERIA_NOT_REFERENCES;
1027         expr = $3;
1028         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1029 }
1030 | MATCHER_SCORE_GREATER MATCHER_INTEGER
1031 {
1032         gint criteria = 0;
1033         gint value = 0;
1034
1035         criteria = MATCHCRITERIA_SCORE_GREATER;
1036         value = strtol($2, NULL, 0);
1037         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1038 }
1039 | MATCHER_SCORE_LOWER MATCHER_INTEGER
1040 {
1041         gint criteria = 0;
1042         gint value = 0;
1043
1044         criteria = MATCHCRITERIA_SCORE_LOWER;
1045         value = strtol($2, NULL, 0);
1046         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1047 }
1048 | MATCHER_SCORE_EQUAL MATCHER_INTEGER
1049 {
1050         gint criteria = 0;
1051         gint value = 0;
1052
1053         criteria = MATCHCRITERIA_SCORE_EQUAL;
1054         value = strtol($2, NULL, 0);
1055         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1056 }
1057 | MATCHER_SIZE_GREATER MATCHER_INTEGER 
1058 {
1059         gint criteria = 0;
1060         gint value    = 0;
1061         criteria = MATCHCRITERIA_SIZE_GREATER;
1062         value = strtol($2, NULL, 0);
1063         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1064 }
1065 | MATCHER_SIZE_SMALLER MATCHER_INTEGER
1066 {
1067         gint criteria = 0;
1068         gint value    = 0;
1069         criteria = MATCHCRITERIA_SIZE_SMALLER;
1070         value = strtol($2, NULL, 0);
1071         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1072 }
1073 | MATCHER_SIZE_EQUAL MATCHER_INTEGER
1074 {
1075         gint criteria = 0;
1076         gint value    = 0;
1077         criteria = MATCHCRITERIA_SIZE_EQUAL;
1078         value = strtol($2, NULL, 0);
1079         prop = matcherprop_new(criteria, NULL, 0, NULL, value);
1080 }
1081 | MATCHER_HEADER MATCHER_STRING
1082 {
1083         header = g_strdup($2);
1084 } match_type MATCHER_STRING
1085 {
1086         gint criteria = 0;
1087         gchar *expr = NULL;
1088         matcher_is_fast = FALSE;
1089         criteria = MATCHCRITERIA_HEADER;
1090         expr = $2;
1091         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1092         g_free(header);
1093 }
1094 | MATCHER_NOT_HEADER MATCHER_STRING
1095 {
1096         header = g_strdup($2);
1097 } match_type MATCHER_STRING
1098 {
1099         gint criteria = 0;
1100         gchar *expr = NULL;
1101         matcher_is_fast = FALSE;
1102         criteria = MATCHCRITERIA_NOT_HEADER;
1103         expr = $2;
1104         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1105         g_free(header);
1106 }
1107 | MATCHER_HEADERS_PART match_type MATCHER_STRING
1108 {
1109         gint criteria = 0;
1110         gchar *expr = NULL;
1111         matcher_is_fast = FALSE;
1112         criteria = MATCHCRITERIA_HEADERS_PART;
1113         expr = $3;
1114         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1115 }
1116 | MATCHER_NOT_HEADERS_PART match_type MATCHER_STRING
1117 {
1118         gint criteria = 0;
1119         gchar *expr = NULL;
1120         matcher_is_fast = FALSE;
1121         criteria = MATCHCRITERIA_NOT_HEADERS_PART;
1122         expr = $3;
1123         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1124 }
1125 | MATCHER_HEADERS_CONT match_type MATCHER_STRING
1126 {
1127         gint criteria = 0;
1128         gchar *expr = NULL;
1129         matcher_is_fast = FALSE;
1130         criteria = MATCHCRITERIA_HEADERS_CONT;
1131         expr = $3;
1132         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1133 }
1134 | MATCHER_NOT_HEADERS_CONT match_type MATCHER_STRING
1135 {
1136         gint criteria = 0;
1137         gchar *expr = NULL;
1138         matcher_is_fast = FALSE;
1139         criteria = MATCHCRITERIA_NOT_HEADERS_CONT;
1140         expr = $3;
1141         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1142 }
1143 | MATCHER_FOUND_IN_ADDRESSBOOK MATCHER_STRING
1144 {
1145         header = g_strdup($2);
1146 } MATCHER_IN MATCHER_STRING
1147 {
1148         gint criteria = 0;
1149         gchar *expr = NULL;
1150
1151         criteria = MATCHCRITERIA_FOUND_IN_ADDRESSBOOK;
1152         expr = $2;
1153         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1154         g_free(header);
1155 }
1156 | MATCHER_NOT_FOUND_IN_ADDRESSBOOK MATCHER_STRING
1157 {
1158         header = g_strdup($2);
1159 } MATCHER_IN MATCHER_STRING
1160 {
1161         gint criteria = 0;
1162         gchar *expr = NULL;
1163
1164         criteria = MATCHCRITERIA_NOT_FOUND_IN_ADDRESSBOOK;
1165         expr = $2;
1166         prop = matcherprop_new(criteria, header, match_type, expr, 0);
1167         g_free(header);
1168 }
1169 | MATCHER_MESSAGE match_type MATCHER_STRING
1170 {
1171         gint criteria = 0;
1172         gchar *expr = NULL;
1173         matcher_is_fast = FALSE;
1174         criteria = MATCHCRITERIA_MESSAGE;
1175         expr = $3;
1176         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1177 }
1178 | MATCHER_NOT_MESSAGE match_type MATCHER_STRING
1179 {
1180         gint criteria = 0;
1181         gchar *expr = NULL;
1182         matcher_is_fast = FALSE;
1183         criteria = MATCHCRITERIA_NOT_MESSAGE;
1184         expr = $3;
1185         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1186 }
1187 | MATCHER_BODY_PART match_type MATCHER_STRING
1188 {
1189         gint criteria = 0;
1190         gchar *expr = NULL;
1191         matcher_is_fast = FALSE;
1192         criteria = MATCHCRITERIA_BODY_PART;
1193         expr = $3;
1194         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1195 }
1196 | MATCHER_NOT_BODY_PART match_type MATCHER_STRING
1197 {
1198         gint criteria = 0;
1199         gchar *expr = NULL;
1200         matcher_is_fast = FALSE;
1201         criteria = MATCHCRITERIA_NOT_BODY_PART;
1202         expr = $3;
1203         prop = matcherprop_new(criteria, NULL, match_type, expr, 0);
1204 }
1205 | MATCHER_TEST MATCHER_STRING
1206 {
1207         gint criteria = 0;
1208         gchar *expr = NULL;
1209         matcher_is_fast = FALSE;
1210         criteria = MATCHCRITERIA_TEST;
1211         expr = $2;
1212         prop = matcherprop_new(criteria, NULL, MATCHTYPE_MATCH, expr, 0);
1213 }
1214 | MATCHER_NOT_TEST MATCHER_STRING
1215 {
1216         gint criteria = 0;
1217         gchar *expr = NULL;
1218         matcher_is_fast = FALSE;
1219         criteria = MATCHCRITERIA_NOT_TEST;
1220         expr = $2;
1221         prop = matcherprop_new(criteria, NULL, MATCHTYPE_MATCH, expr, 0);
1222 }
1223 ;
1224
1225 filtering_action:
1226 MATCHER_EXECUTE MATCHER_STRING
1227 {
1228         gchar *cmd = NULL;
1229         gint action_type = 0;
1230
1231         action_type = MATCHACTION_EXECUTE;
1232         cmd = $2;
1233         action = filteringaction_new(action_type, 0, cmd, 0, 0, NULL);
1234 }
1235 | MATCHER_MOVE MATCHER_STRING
1236 {
1237         gchar *destination = NULL;
1238         gint action_type = 0;
1239
1240         action_type = MATCHACTION_MOVE;
1241         destination = $2;
1242         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1243 }
1244 | MATCHER_SET_TAG MATCHER_STRING
1245 {
1246         gchar *destination = NULL;
1247         gint action_type = 0;
1248
1249         action_type = MATCHACTION_SET_TAG;
1250         destination = $2;
1251         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1252 }
1253 | MATCHER_UNSET_TAG MATCHER_STRING
1254 {
1255         gchar *destination = NULL;
1256         gint action_type = 0;
1257
1258         action_type = MATCHACTION_UNSET_TAG;
1259         destination = $2;
1260         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1261 }
1262 | MATCHER_CLEAR_TAGS
1263 {
1264         gint action_type = 0;
1265
1266         action_type = MATCHACTION_CLEAR_TAGS;
1267         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1268 }
1269 | MATCHER_COPY MATCHER_STRING
1270 {
1271         gchar *destination = NULL;
1272         gint action_type = 0;
1273
1274         action_type = MATCHACTION_COPY;
1275         destination = $2;
1276         action = filteringaction_new(action_type, 0, destination, 0, 0, NULL);
1277 }
1278 | MATCHER_DELETE
1279 {
1280         gint action_type = 0;
1281
1282         action_type = MATCHACTION_DELETE;
1283         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1284 }
1285 | MATCHER_MARK
1286 {
1287         gint action_type = 0;
1288
1289         action_type = MATCHACTION_MARK;
1290         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1291 }
1292 | MATCHER_UNMARK
1293 {
1294         gint action_type = 0;
1295
1296         action_type = MATCHACTION_UNMARK;
1297         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1298 }
1299 | MATCHER_LOCK
1300 {
1301         gint action_type = 0;
1302
1303         action_type = MATCHACTION_LOCK;
1304         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1305 }
1306 | MATCHER_UNLOCK
1307 {
1308         gint action_type = 0;
1309
1310         action_type = MATCHACTION_UNLOCK;
1311         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1312 }
1313 | MATCHER_MARK_AS_READ
1314 {
1315         gint action_type = 0;
1316
1317         action_type = MATCHACTION_MARK_AS_READ;
1318         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1319 }
1320 | MATCHER_MARK_AS_UNREAD
1321 {
1322         gint action_type = 0;
1323
1324         action_type = MATCHACTION_MARK_AS_UNREAD;
1325         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1326 }
1327 | MATCHER_MARK_AS_SPAM
1328 {
1329         gint action_type = 0;
1330
1331         action_type = MATCHACTION_MARK_AS_SPAM;
1332         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1333 }
1334 | MATCHER_MARK_AS_HAM
1335 {
1336         gint action_type = 0;
1337
1338         action_type = MATCHACTION_MARK_AS_HAM;
1339         action = filteringaction_new(action_type, 0, NULL, 0, 0, NULL);
1340 }
1341 | MATCHER_FORWARD MATCHER_INTEGER MATCHER_STRING
1342 {
1343         gchar *destination = NULL;
1344         gint action_type = 0;
1345         gint account_id = 0;
1346
1347         action_type = MATCHACTION_FORWARD;
1348         account_id = strtol($2, NULL, 10);
1349         destination = $3;
1350         action = filteringaction_new(action_type,
1351             account_id, destination, 0, 0, NULL);
1352 }
1353 | MATCHER_FORWARD_AS_ATTACHMENT MATCHER_INTEGER MATCHER_STRING
1354 {
1355         gchar *destination = NULL;
1356         gint action_type = 0;
1357         gint account_id = 0;
1358
1359         action_type = MATCHACTION_FORWARD_AS_ATTACHMENT;
1360         account_id = strtol($2, NULL, 10);
1361         destination = $3;
1362         action = filteringaction_new(action_type,
1363             account_id, destination, 0, 0, NULL);
1364 }
1365 | MATCHER_REDIRECT MATCHER_INTEGER MATCHER_STRING
1366 {
1367         gchar *destination = NULL;
1368         gint action_type = 0;
1369         gint account_id = 0;
1370
1371         action_type = MATCHACTION_REDIRECT;
1372         account_id = strtol($2, NULL, 10);
1373         destination = $3;
1374         action = filteringaction_new(action_type,
1375             account_id, destination, 0, 0, NULL);
1376 }
1377 | MATCHER_COLOR MATCHER_INTEGER
1378 {
1379         gint action_type = 0;
1380         gint color = 0;
1381
1382         action_type = MATCHACTION_COLOR;
1383         color = strtol($2, NULL, 10);
1384         action = filteringaction_new(action_type, 0, NULL, color, 0, NULL);
1385 }
1386 | MATCHER_CHANGE_SCORE MATCHER_INTEGER
1387 {
1388         gint score = 0;
1389         
1390         score = strtol($2, NULL, 10);
1391         action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
1392                                      NULL, 0, score, NULL);
1393 }
1394 /* backward compatibility */
1395 | MATCHER_SCORE MATCHER_INTEGER
1396 {
1397         gint score = 0;
1398         
1399         score = strtol($2, NULL, 10);
1400         action = filteringaction_new(MATCHACTION_CHANGE_SCORE, 0,
1401                                      NULL, 0, score, NULL);
1402 }
1403 | MATCHER_SET_SCORE MATCHER_INTEGER
1404 {
1405         gint score = 0;
1406         
1407         score = strtol($2, NULL, 10);
1408         action = filteringaction_new(MATCHACTION_SET_SCORE, 0,
1409                                      NULL, 0, score, NULL);
1410 }
1411 | MATCHER_HIDE
1412 {
1413         action = filteringaction_new(MATCHACTION_HIDE, 0, NULL, 0, 0, NULL);
1414 }
1415 | MATCHER_IGNORE
1416 {
1417         action = filteringaction_new(MATCHACTION_IGNORE, 0, NULL, 0, 0, NULL);
1418 }
1419 | MATCHER_WATCH
1420 {
1421         action = filteringaction_new(MATCHACTION_WATCH, 0, NULL, 0, 0, NULL);
1422 }
1423 | MATCHER_ADD_TO_ADDRESSBOOK MATCHER_STRING
1424 {
1425         header = g_strdup($2);
1426 } MATCHER_STRING
1427 {
1428         gchar *addressbook = NULL;
1429         gint action_type = 0;
1430
1431         action_type = MATCHACTION_ADD_TO_ADDRESSBOOK;
1432         addressbook = $2;
1433         action = filteringaction_new(action_type, 0, addressbook, 0, 0, header);
1434         g_free(header);
1435 }
1436 | MATCHER_STOP
1437 {
1438         action = filteringaction_new(MATCHACTION_STOP, 0, NULL, 0, 0, NULL);
1439 }
1440 ;