5 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
6 * Copyright (c) 2001-2002 by Hiroyuki Yamamoto & The Sylpheed Claws Team.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include "filtering.h"
32 #include "matcher_parser.h"
33 #include "matcher_parser_lex.h"
36 #define MAX_COLORLABELS (MSG_CLABEL_7 - MSG_CLABEL_NONE)
38 static gint error = 0;
39 static gint bool_op = 0;
40 static gint match_type = 0;
41 static gchar *header = NULL;
43 static MatcherProp *prop;
45 static GSList *matchers_list = NULL;
47 static MatcherList *cond;
48 static gint score = 0;
49 static FilteringAction *action = NULL;
51 static FilteringProp *filtering;
52 static ScoringProp *scoring = NULL;
54 static GSList **prefs_scoring = NULL;
55 static GSList **prefs_filtering = NULL;
57 static int matcher_parser_dialog = 0;
59 /* ******************************************************************** */
61 void matcher_parser_start_parsing(FILE *f)
63 matcher_parserrestart(f);
64 matcher_parserparse();
67 FilteringProp *matcher_parser_get_filtering(gchar *str)
71 /* bad coding to enable the sub-grammar matching
73 matcher_parserlineno = 1;
74 matcher_parser_dialog = 1;
75 matcher_parserrestart(NULL);
76 matcher_parser_init();
77 bufstate = matcher_parser_scan_string(str);
78 matcher_parser_switch_to_buffer(bufstate);
79 if (matcher_parserparse() != 0)
81 matcher_parser_dialog = 0;
82 matcher_parser_delete_buffer(bufstate);
86 ScoringProp *matcher_parser_get_scoring(gchar *str)
90 /* bad coding to enable the sub-grammar matching
92 matcher_parserlineno = 1;
93 matcher_parser_dialog = 1;
94 matcher_parserrestart(NULL);
95 matcher_parser_init();
96 bufstate = matcher_parser_scan_string(str);
97 matcher_parser_switch_to_buffer(bufstate);
98 if (matcher_parserparse() != 0)
100 matcher_parser_dialog = 0;
101 matcher_parser_delete_buffer(bufstate);
105 static gboolean check_quote_symetry(gchar *str)
111 return TRUE; /* heh, that's symetric */
114 for (walk = str; *walk; walk++) {
116 if (walk == str /* first char */
117 || *(walk - 1) != '\\') /* not escaped */
124 MatcherList *matcher_parser_get_cond(gchar *str)
128 if (!check_quote_symetry(str)) {
133 /* bad coding to enable the sub-grammar matching
135 matcher_parserlineno = 1;
136 matcher_parser_dialog = 1;
137 matcher_parserrestart(NULL);
138 matcher_parser_init();
139 bufstate = matcher_parser_scan_string(str);
140 matcher_parserparse();
141 matcher_parser_dialog = 0;
142 matcher_parser_delete_buffer(bufstate);
146 MatcherProp *matcher_parser_get_prop(gchar *str)
151 matcher_parserlineno = 1;
152 list = matcher_parser_get_cond(str);
156 if (list->matchers == NULL)
159 if (list->matchers->next != NULL)
162 prop = list->matchers->data;
164 g_slist_free(list->matchers);
170 void matcher_parsererror(char *str)
175 for (l = matchers_list; l != NULL; l = g_slist_next(l)) {
176 matcherprop_free((MatcherProp *)
180 g_slist_free(matchers_list);
181 matchers_list = NULL;
184 g_warning("scoring / filtering parsing: %i: %s\n",
185 matcher_parserlineno, str);
189 int matcher_parserwrap(void)
200 %token MATCHER_ALL MATCHER_UNREAD MATCHER_NOT_UNREAD
201 %token MATCHER_NEW MATCHER_NOT_NEW MATCHER_MARKED
202 %token MATCHER_NOT_MARKED MATCHER_DELETED MATCHER_NOT_DELETED
203 %token MATCHER_REPLIED MATCHER_NOT_REPLIED MATCHER_FORWARDED
204 %token MATCHER_NOT_FORWARDED MATCHER_SUBJECT MATCHER_NOT_SUBJECT
205 %token MATCHER_FROM MATCHER_NOT_FROM MATCHER_TO MATCHER_NOT_TO
206 %token MATCHER_CC MATCHER_NOT_CC MATCHER_TO_OR_CC MATCHER_NOT_TO_AND_NOT_CC
207 %token MATCHER_AGE_GREATER MATCHER_AGE_LOWER MATCHER_NEWSGROUPS
208 %token MATCHER_NOT_NEWSGROUPS MATCHER_INREPLYTO MATCHER_NOT_INREPLYTO
209 %token MATCHER_REFERENCES MATCHER_NOT_REFERENCES MATCHER_SCORE_GREATER
210 %token MATCHER_SCORE_LOWER MATCHER_HEADER MATCHER_NOT_HEADER
211 %token MATCHER_HEADERS_PART MATCHER_NOT_HEADERS_PART MATCHER_MESSAGE
212 %token MATCHER_NOT_MESSAGE MATCHER_BODY_PART MATCHER_NOT_BODY_PART
213 %token MATCHER_EXECUTE MATCHER_NOT_EXECUTE MATCHER_MATCHCASE MATCHER_MATCH
214 %token MATCHER_REGEXPCASE MATCHER_REGEXP MATCHER_SCORE MATCHER_MOVE
215 %token MATCHER_COPY MATCHER_DELETE MATCHER_MARK MATCHER_UNMARK
216 %token MATCHER_MARK_AS_READ MATCHER_MARK_AS_UNREAD MATCHER_FORWARD
217 %token MATCHER_FORWARD_AS_ATTACHMENT MATCHER_EOL MATCHER_STRING
218 %token MATCHER_OR MATCHER_AND
219 %token MATCHER_COLOR MATCHER_SCORE_EQUAL MATCHER_REDIRECT MATCHER_DELETE_ON_SERVER
220 %token MATCHER_SIZE_GREATER MATCHER_SIZE_SMALLER MATCHER_SIZE_EQUAL
221 %token MATCHER_LOCKED MATCHER_NOT_LOCKED
222 %token MATCHER_COLORLABEL MATCHER_NOT_COLORLABEL
226 %token <str> MATCHER_STRING
227 %token <str> MATCHER_SECTION
228 %token <str> MATCHER_INTEGER
234 if (!matcher_parser_dialog) {
235 prefs_scoring = &global_scoring;
236 prefs_filtering = &global_processing;
255 section_notification:
256 MATCHER_SECTION MATCHER_EOL
259 FolderItem *item = NULL;
261 if (!matcher_parser_dialog) {
262 item = folder_find_item_from_identifier(folder);
264 prefs_scoring = &global_scoring;
265 prefs_filtering = &global_processing;
268 prefs_scoring = &item->prefs->scoring;
269 prefs_filtering = &item->prefs->processing;
276 condition end_instr_opt
281 filtering_or_scoring end_action
284 if (matcher_parser_dialog)
287 matcher_parsererror("parse error");
297 if (matcher_parser_dialog)
300 matcher_parsererror("parse error");
306 filtering_or_scoring:
309 filtering = filteringprop_new(cond, action);
312 if (!matcher_parser_dialog) {
313 *prefs_filtering = g_slist_append(*prefs_filtering,
320 scoring = scoringprop_new(cond, score);
323 if (!matcher_parser_dialog) {
324 *prefs_scoring = g_slist_append(*prefs_scoring, scoring);
333 match_type = MATCHTYPE_MATCHCASE;
337 match_type = MATCHTYPE_MATCH;
341 match_type = MATCHTYPE_REGEXPCASE;
345 match_type = MATCHTYPE_REGEXP;
352 cond = matcherlist_new(matchers_list, (bool_op == MATCHERBOOL_AND));
353 matchers_list = NULL;
358 condition_list bool_op one_condition
360 matchers_list = g_slist_append(matchers_list, prop);
364 matchers_list = NULL;
365 matchers_list = g_slist_append(matchers_list, prop);
372 bool_op = MATCHERBOOL_AND;
376 bool_op = MATCHERBOOL_OR;
385 criteria = MATCHCRITERIA_ALL;
386 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
392 criteria = MATCHCRITERIA_UNREAD;
393 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
399 criteria = MATCHCRITERIA_NOT_UNREAD;
400 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
406 criteria = MATCHCRITERIA_NEW;
407 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
413 criteria = MATCHCRITERIA_NOT_NEW;
414 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
420 criteria = MATCHCRITERIA_MARKED;
421 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
427 criteria = MATCHCRITERIA_NOT_MARKED;
428 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
434 criteria = MATCHCRITERIA_DELETED;
435 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
437 | MATCHER_NOT_DELETED
441 criteria = MATCHCRITERIA_NOT_DELETED;
442 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
448 criteria = MATCHCRITERIA_REPLIED;
449 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
451 | MATCHER_NOT_REPLIED
455 criteria = MATCHCRITERIA_NOT_REPLIED;
456 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
462 criteria = MATCHCRITERIA_FORWARDED;
463 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
465 | MATCHER_NOT_FORWARDED
469 criteria = MATCHCRITERIA_NOT_FORWARDED;
470 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
476 criteria = MATCHCRITERIA_LOCKED;
477 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
483 criteria = MATCHCRITERIA_NOT_LOCKED;
484 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
486 | MATCHER_COLORLABEL MATCHER_INTEGER
491 criteria = MATCHCRITERIA_COLORLABEL;
493 if (value < 1) value = 1;
494 else if (value > MAX_COLORLABELS) value = MAX_COLORLABELS;
495 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
497 | MATCHER_NOT_COLORLABEL MATCHER_INTEGER
502 criteria = MATCHCRITERIA_NOT_COLORLABEL;
504 if (value < 1) value = 1;
505 else if (value > MAX_COLORLABELS) value = MAX_COLORLABELS;
506 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
508 | MATCHER_SUBJECT match_type MATCHER_STRING
513 criteria = MATCHCRITERIA_SUBJECT;
515 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
517 | MATCHER_NOT_SUBJECT match_type MATCHER_STRING
522 criteria = MATCHCRITERIA_NOT_SUBJECT;
524 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
526 | MATCHER_FROM match_type MATCHER_STRING
531 criteria = MATCHCRITERIA_FROM;
533 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
535 | MATCHER_NOT_FROM match_type MATCHER_STRING
540 criteria = MATCHCRITERIA_NOT_FROM;
542 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
544 | MATCHER_TO match_type MATCHER_STRING
549 criteria = MATCHCRITERIA_TO;
551 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
553 | MATCHER_NOT_TO match_type MATCHER_STRING
558 criteria = MATCHCRITERIA_NOT_TO;
560 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
562 | MATCHER_CC match_type MATCHER_STRING
567 criteria = MATCHCRITERIA_CC;
569 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
571 | MATCHER_NOT_CC match_type MATCHER_STRING
576 criteria = MATCHCRITERIA_NOT_CC;
578 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
580 | MATCHER_TO_OR_CC match_type MATCHER_STRING
585 criteria = MATCHCRITERIA_TO_OR_CC;
587 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
589 | MATCHER_NOT_TO_AND_NOT_CC match_type MATCHER_STRING
594 criteria = MATCHCRITERIA_NOT_TO_AND_NOT_CC;
596 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
598 | MATCHER_AGE_GREATER MATCHER_INTEGER
603 criteria = MATCHCRITERIA_AGE_GREATER;
605 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
607 | MATCHER_AGE_LOWER MATCHER_INTEGER
612 criteria = MATCHCRITERIA_AGE_LOWER;
614 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
616 | MATCHER_NEWSGROUPS match_type MATCHER_STRING
621 criteria = MATCHCRITERIA_NEWSGROUPS;
623 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
625 | MATCHER_NOT_NEWSGROUPS match_type MATCHER_STRING
630 criteria = MATCHCRITERIA_NOT_NEWSGROUPS;
632 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
634 | MATCHER_INREPLYTO match_type MATCHER_STRING
639 criteria = MATCHCRITERIA_INREPLYTO;
641 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
643 | MATCHER_NOT_INREPLYTO match_type MATCHER_STRING
648 criteria = MATCHCRITERIA_NOT_INREPLYTO;
650 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
652 | MATCHER_REFERENCES match_type MATCHER_STRING
657 criteria = MATCHCRITERIA_REFERENCES;
659 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
661 | MATCHER_NOT_REFERENCES match_type MATCHER_STRING
666 criteria = MATCHCRITERIA_NOT_REFERENCES;
668 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
670 | MATCHER_SCORE_GREATER MATCHER_INTEGER
675 criteria = MATCHCRITERIA_SCORE_GREATER;
677 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
679 | MATCHER_SCORE_LOWER MATCHER_INTEGER
684 criteria = MATCHCRITERIA_SCORE_LOWER;
686 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
688 | MATCHER_SCORE_EQUAL MATCHER_INTEGER
693 criteria = MATCHCRITERIA_SCORE_EQUAL;
695 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
697 | MATCHER_SIZE_GREATER MATCHER_INTEGER
701 criteria = MATCHCRITERIA_SIZE_GREATER;
703 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
705 | MATCHER_SIZE_SMALLER MATCHER_INTEGER
709 criteria = MATCHCRITERIA_SIZE_SMALLER;
711 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
713 | MATCHER_SIZE_EQUAL MATCHER_INTEGER
717 criteria = MATCHCRITERIA_SIZE_EQUAL;
719 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
721 | MATCHER_HEADER MATCHER_STRING
723 header = g_strdup($2);
724 } match_type MATCHER_STRING
729 criteria = MATCHCRITERIA_HEADER;
731 prop = matcherprop_unquote_new(criteria, header, match_type, expr, 0);
734 | MATCHER_NOT_HEADER MATCHER_STRING
736 header = g_strdup($2);
737 } match_type MATCHER_STRING
742 criteria = MATCHCRITERIA_NOT_HEADER;
744 prop = matcherprop_unquote_new(criteria, header, match_type, expr, 0);
747 | MATCHER_HEADERS_PART match_type MATCHER_STRING
752 criteria = MATCHCRITERIA_HEADERS_PART;
754 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
756 | MATCHER_NOT_HEADERS_PART match_type MATCHER_STRING
761 criteria = MATCHCRITERIA_NOT_HEADERS_PART;
763 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
765 | MATCHER_MESSAGE match_type MATCHER_STRING
770 criteria = MATCHCRITERIA_MESSAGE;
772 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
774 | MATCHER_NOT_MESSAGE match_type MATCHER_STRING
779 criteria = MATCHCRITERIA_NOT_MESSAGE;
781 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
783 | MATCHER_BODY_PART match_type MATCHER_STRING
788 criteria = MATCHCRITERIA_BODY_PART;
790 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
792 | MATCHER_NOT_BODY_PART match_type MATCHER_STRING
797 criteria = MATCHCRITERIA_NOT_BODY_PART;
799 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
801 | MATCHER_EXECUTE MATCHER_STRING
806 criteria = MATCHCRITERIA_EXECUTE;
808 prop = matcherprop_unquote_new(criteria, NULL, 0, expr, 0);
810 | MATCHER_NOT_EXECUTE MATCHER_STRING
815 criteria = MATCHCRITERIA_NOT_EXECUTE;
817 prop = matcherprop_unquote_new(criteria, NULL, 0, expr, 0);
822 MATCHER_EXECUTE MATCHER_STRING
825 gint action_type = 0;
827 action_type = MATCHACTION_EXECUTE;
829 action = filteringaction_new(action_type, 0, cmd, 0);
831 | MATCHER_MOVE MATCHER_STRING
833 gchar *destination = NULL;
834 gint action_type = 0;
836 action_type = MATCHACTION_MOVE;
838 action = filteringaction_new(action_type, 0, destination, 0);
840 | MATCHER_COPY MATCHER_STRING
842 gchar *destination = NULL;
843 gint action_type = 0;
845 action_type = MATCHACTION_COPY;
847 action = filteringaction_new(action_type, 0, destination, 0);
851 gint action_type = 0;
853 action_type = MATCHACTION_DELETE;
854 action = filteringaction_new(action_type, 0, NULL, 0);
858 gint action_type = 0;
860 action_type = MATCHACTION_MARK;
861 action = filteringaction_new(action_type, 0, NULL, 0);
865 gint action_type = 0;
867 action_type = MATCHACTION_UNMARK;
868 action = filteringaction_new(action_type, 0, NULL, 0);
870 | MATCHER_MARK_AS_READ
872 gint action_type = 0;
874 action_type = MATCHACTION_MARK_AS_READ;
875 action = filteringaction_new(action_type, 0, NULL, 0);
877 | MATCHER_MARK_AS_UNREAD
879 gint action_type = 0;
881 action_type = MATCHACTION_MARK_AS_UNREAD;
882 action = filteringaction_new(action_type, 0, NULL, 0);
884 | MATCHER_FORWARD MATCHER_INTEGER MATCHER_STRING
886 gchar *destination = NULL;
887 gint action_type = 0;
890 action_type = MATCHACTION_FORWARD;
891 account_id = atoi($2);
893 action = filteringaction_new(action_type, account_id, destination, 0);
895 | MATCHER_FORWARD_AS_ATTACHMENT MATCHER_INTEGER MATCHER_STRING
897 gchar *destination = NULL;
898 gint action_type = 0;
901 action_type = MATCHACTION_FORWARD_AS_ATTACHMENT;
902 account_id = atoi($2);
904 action = filteringaction_new(action_type, account_id, destination, 0);
906 | MATCHER_REDIRECT MATCHER_INTEGER MATCHER_STRING
908 gchar *destination = NULL;
909 gint action_type = 0;
912 action_type = MATCHACTION_REDIRECT;
913 account_id = atoi($2);
915 action = filteringaction_new(action_type, account_id, destination, 0);
917 | MATCHER_COLOR MATCHER_INTEGER
919 gint action_type = 0;
922 action_type = MATCHACTION_COLOR;
924 action = filteringaction_new(action_type, 0, NULL, color);
926 | MATCHER_DELETE_ON_SERVER
928 gint action_type = 0;
929 action_type = MATCHACTION_DELETE_ON_SERVER;
930 action = filteringaction_new(action_type, 0, NULL, 0);
935 MATCHER_SCORE MATCHER_INTEGER