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
223 %token MATCHER_IGNORE_THREAD MATCHER_NOT_IGNORE_THREAD
227 %token <str> MATCHER_STRING
228 %token <str> MATCHER_SECTION
229 %token <str> MATCHER_INTEGER
235 if (!matcher_parser_dialog) {
236 prefs_scoring = &global_scoring;
237 prefs_filtering = &global_processing;
256 section_notification:
257 MATCHER_SECTION MATCHER_EOL
260 FolderItem *item = NULL;
262 if (!matcher_parser_dialog) {
263 item = folder_find_item_from_identifier(folder);
265 prefs_scoring = &global_scoring;
266 prefs_filtering = &global_processing;
269 prefs_scoring = &item->prefs->scoring;
270 prefs_filtering = &item->prefs->processing;
277 condition end_instr_opt
282 filtering_or_scoring end_action
285 if (matcher_parser_dialog)
288 matcher_parsererror("parse error");
298 if (matcher_parser_dialog)
301 matcher_parsererror("parse error");
307 filtering_or_scoring:
310 filtering = filteringprop_new(cond, action);
313 if (!matcher_parser_dialog) {
314 *prefs_filtering = g_slist_append(*prefs_filtering,
321 scoring = scoringprop_new(cond, score);
324 if (!matcher_parser_dialog) {
325 *prefs_scoring = g_slist_append(*prefs_scoring, scoring);
334 match_type = MATCHTYPE_MATCHCASE;
338 match_type = MATCHTYPE_MATCH;
342 match_type = MATCHTYPE_REGEXPCASE;
346 match_type = MATCHTYPE_REGEXP;
353 cond = matcherlist_new(matchers_list, (bool_op == MATCHERBOOL_AND));
354 matchers_list = NULL;
359 condition_list bool_op one_condition
361 matchers_list = g_slist_append(matchers_list, prop);
365 matchers_list = NULL;
366 matchers_list = g_slist_append(matchers_list, prop);
373 bool_op = MATCHERBOOL_AND;
377 bool_op = MATCHERBOOL_OR;
386 criteria = MATCHCRITERIA_ALL;
387 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
393 criteria = MATCHCRITERIA_UNREAD;
394 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
400 criteria = MATCHCRITERIA_NOT_UNREAD;
401 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
407 criteria = MATCHCRITERIA_NEW;
408 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
414 criteria = MATCHCRITERIA_NOT_NEW;
415 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
421 criteria = MATCHCRITERIA_MARKED;
422 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
428 criteria = MATCHCRITERIA_NOT_MARKED;
429 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
435 criteria = MATCHCRITERIA_DELETED;
436 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
438 | MATCHER_NOT_DELETED
442 criteria = MATCHCRITERIA_NOT_DELETED;
443 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
449 criteria = MATCHCRITERIA_REPLIED;
450 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
452 | MATCHER_NOT_REPLIED
456 criteria = MATCHCRITERIA_NOT_REPLIED;
457 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
463 criteria = MATCHCRITERIA_FORWARDED;
464 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
466 | MATCHER_NOT_FORWARDED
470 criteria = MATCHCRITERIA_NOT_FORWARDED;
471 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
477 criteria = MATCHCRITERIA_LOCKED;
478 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
484 criteria = MATCHCRITERIA_NOT_LOCKED;
485 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
487 | MATCHER_COLORLABEL MATCHER_INTEGER
492 criteria = MATCHCRITERIA_COLORLABEL;
494 if (value < 1) value = 1;
495 else if (value > MAX_COLORLABELS) value = MAX_COLORLABELS;
496 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
498 | MATCHER_NOT_COLORLABEL MATCHER_INTEGER
503 criteria = MATCHCRITERIA_NOT_COLORLABEL;
505 if (value < 1) value = 1;
506 else if (value > MAX_COLORLABELS) value = MAX_COLORLABELS;
507 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
509 | MATCHER_IGNORE_THREAD
513 criteria = MATCHCRITERIA_IGNORE_THREAD;
514 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
516 | MATCHER_NOT_IGNORE_THREAD
520 criteria = MATCHCRITERIA_NOT_IGNORE_THREAD;
521 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, 0);
523 | MATCHER_SUBJECT match_type MATCHER_STRING
528 criteria = MATCHCRITERIA_SUBJECT;
530 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
532 | MATCHER_NOT_SUBJECT match_type MATCHER_STRING
537 criteria = MATCHCRITERIA_NOT_SUBJECT;
539 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
541 | MATCHER_FROM match_type MATCHER_STRING
546 criteria = MATCHCRITERIA_FROM;
548 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
550 | MATCHER_NOT_FROM match_type MATCHER_STRING
555 criteria = MATCHCRITERIA_NOT_FROM;
557 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
559 | MATCHER_TO match_type MATCHER_STRING
564 criteria = MATCHCRITERIA_TO;
566 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
568 | MATCHER_NOT_TO match_type MATCHER_STRING
573 criteria = MATCHCRITERIA_NOT_TO;
575 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
577 | MATCHER_CC match_type MATCHER_STRING
582 criteria = MATCHCRITERIA_CC;
584 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
586 | MATCHER_NOT_CC match_type MATCHER_STRING
591 criteria = MATCHCRITERIA_NOT_CC;
593 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
595 | MATCHER_TO_OR_CC match_type MATCHER_STRING
600 criteria = MATCHCRITERIA_TO_OR_CC;
602 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
604 | MATCHER_NOT_TO_AND_NOT_CC match_type MATCHER_STRING
609 criteria = MATCHCRITERIA_NOT_TO_AND_NOT_CC;
611 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
613 | MATCHER_AGE_GREATER MATCHER_INTEGER
618 criteria = MATCHCRITERIA_AGE_GREATER;
620 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
622 | MATCHER_AGE_LOWER MATCHER_INTEGER
627 criteria = MATCHCRITERIA_AGE_LOWER;
629 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
631 | MATCHER_NEWSGROUPS match_type MATCHER_STRING
636 criteria = MATCHCRITERIA_NEWSGROUPS;
638 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
640 | MATCHER_NOT_NEWSGROUPS match_type MATCHER_STRING
645 criteria = MATCHCRITERIA_NOT_NEWSGROUPS;
647 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
649 | MATCHER_INREPLYTO match_type MATCHER_STRING
654 criteria = MATCHCRITERIA_INREPLYTO;
656 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
658 | MATCHER_NOT_INREPLYTO match_type MATCHER_STRING
663 criteria = MATCHCRITERIA_NOT_INREPLYTO;
665 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
667 | MATCHER_REFERENCES match_type MATCHER_STRING
672 criteria = MATCHCRITERIA_REFERENCES;
674 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
676 | MATCHER_NOT_REFERENCES match_type MATCHER_STRING
681 criteria = MATCHCRITERIA_NOT_REFERENCES;
683 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
685 | MATCHER_SCORE_GREATER MATCHER_INTEGER
690 criteria = MATCHCRITERIA_SCORE_GREATER;
692 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
694 | MATCHER_SCORE_LOWER MATCHER_INTEGER
699 criteria = MATCHCRITERIA_SCORE_LOWER;
701 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
703 | MATCHER_SCORE_EQUAL MATCHER_INTEGER
708 criteria = MATCHCRITERIA_SCORE_EQUAL;
710 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
712 | MATCHER_SIZE_GREATER MATCHER_INTEGER
716 criteria = MATCHCRITERIA_SIZE_GREATER;
718 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
720 | MATCHER_SIZE_SMALLER MATCHER_INTEGER
724 criteria = MATCHCRITERIA_SIZE_SMALLER;
726 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
728 | MATCHER_SIZE_EQUAL MATCHER_INTEGER
732 criteria = MATCHCRITERIA_SIZE_EQUAL;
734 prop = matcherprop_unquote_new(criteria, NULL, 0, NULL, value);
736 | MATCHER_HEADER MATCHER_STRING
738 header = g_strdup($2);
739 } match_type MATCHER_STRING
744 criteria = MATCHCRITERIA_HEADER;
746 prop = matcherprop_unquote_new(criteria, header, match_type, expr, 0);
749 | MATCHER_NOT_HEADER MATCHER_STRING
751 header = g_strdup($2);
752 } match_type MATCHER_STRING
757 criteria = MATCHCRITERIA_NOT_HEADER;
759 prop = matcherprop_unquote_new(criteria, header, match_type, expr, 0);
762 | MATCHER_HEADERS_PART match_type MATCHER_STRING
767 criteria = MATCHCRITERIA_HEADERS_PART;
769 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
771 | MATCHER_NOT_HEADERS_PART match_type MATCHER_STRING
776 criteria = MATCHCRITERIA_NOT_HEADERS_PART;
778 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
780 | MATCHER_MESSAGE match_type MATCHER_STRING
785 criteria = MATCHCRITERIA_MESSAGE;
787 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
789 | MATCHER_NOT_MESSAGE match_type MATCHER_STRING
794 criteria = MATCHCRITERIA_NOT_MESSAGE;
796 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
798 | MATCHER_BODY_PART match_type MATCHER_STRING
803 criteria = MATCHCRITERIA_BODY_PART;
805 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
807 | MATCHER_NOT_BODY_PART match_type MATCHER_STRING
812 criteria = MATCHCRITERIA_NOT_BODY_PART;
814 prop = matcherprop_unquote_new(criteria, NULL, match_type, expr, 0);
816 | MATCHER_EXECUTE MATCHER_STRING
821 criteria = MATCHCRITERIA_EXECUTE;
823 prop = matcherprop_unquote_new(criteria, NULL, 0, expr, 0);
825 | MATCHER_NOT_EXECUTE MATCHER_STRING
830 criteria = MATCHCRITERIA_NOT_EXECUTE;
832 prop = matcherprop_unquote_new(criteria, NULL, 0, expr, 0);
837 MATCHER_EXECUTE MATCHER_STRING
840 gint action_type = 0;
842 action_type = MATCHACTION_EXECUTE;
844 action = filteringaction_new(action_type, 0, cmd, 0);
846 | MATCHER_MOVE MATCHER_STRING
848 gchar *destination = NULL;
849 gint action_type = 0;
851 action_type = MATCHACTION_MOVE;
853 action = filteringaction_new(action_type, 0, destination, 0);
855 | MATCHER_COPY MATCHER_STRING
857 gchar *destination = NULL;
858 gint action_type = 0;
860 action_type = MATCHACTION_COPY;
862 action = filteringaction_new(action_type, 0, destination, 0);
866 gint action_type = 0;
868 action_type = MATCHACTION_DELETE;
869 action = filteringaction_new(action_type, 0, NULL, 0);
873 gint action_type = 0;
875 action_type = MATCHACTION_MARK;
876 action = filteringaction_new(action_type, 0, NULL, 0);
880 gint action_type = 0;
882 action_type = MATCHACTION_UNMARK;
883 action = filteringaction_new(action_type, 0, NULL, 0);
885 | MATCHER_MARK_AS_READ
887 gint action_type = 0;
889 action_type = MATCHACTION_MARK_AS_READ;
890 action = filteringaction_new(action_type, 0, NULL, 0);
892 | MATCHER_MARK_AS_UNREAD
894 gint action_type = 0;
896 action_type = MATCHACTION_MARK_AS_UNREAD;
897 action = filteringaction_new(action_type, 0, NULL, 0);
899 | MATCHER_FORWARD MATCHER_INTEGER MATCHER_STRING
901 gchar *destination = NULL;
902 gint action_type = 0;
905 action_type = MATCHACTION_FORWARD;
906 account_id = atoi($2);
908 action = filteringaction_new(action_type, account_id, destination, 0);
910 | MATCHER_FORWARD_AS_ATTACHMENT MATCHER_INTEGER MATCHER_STRING
912 gchar *destination = NULL;
913 gint action_type = 0;
916 action_type = MATCHACTION_FORWARD_AS_ATTACHMENT;
917 account_id = atoi($2);
919 action = filteringaction_new(action_type, account_id, destination, 0);
921 | MATCHER_REDIRECT MATCHER_INTEGER MATCHER_STRING
923 gchar *destination = NULL;
924 gint action_type = 0;
927 action_type = MATCHACTION_REDIRECT;
928 account_id = atoi($2);
930 action = filteringaction_new(action_type, account_id, destination, 0);
932 | MATCHER_COLOR MATCHER_INTEGER
934 gint action_type = 0;
937 action_type = MATCHACTION_COLOR;
939 action = filteringaction_new(action_type, 0, NULL, color);
941 | MATCHER_DELETE_ON_SERVER
943 gint action_type = 0;
944 action_type = MATCHACTION_DELETE_ON_SERVER;
945 action = filteringaction_new(action_type, 0, NULL, 0);
950 MATCHER_SCORE MATCHER_INTEGER