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