7 #include "procheader.h"
16 typedef struct _MatchParser MatchParser;
18 static MatchParser matchparser_tab[] = {
20 {MATCHING_ALL, "all"},
21 {MATCHING_UNREAD, "unread"},
22 {MATCHING_NOT_UNREAD, "~unread"},
23 {MATCHING_NEW, "new"},
24 {MATCHING_NOT_NEW, "~new"},
25 {MATCHING_MARKED, "marked"},
26 {MATCHING_NOT_MARKED, "~marked"},
27 {MATCHING_DELETED, "deleted"},
28 {MATCHING_NOT_DELETED, "~deleted"},
29 {MATCHING_REPLIED, "replied"},
30 {MATCHING_NOT_REPLIED, "~replied"},
31 {MATCHING_FORWARDED, "forwarded"},
32 {MATCHING_NOT_FORWARDED, "~forwarded"},
35 {MATCHING_SUBJECT, "subject"},
36 {MATCHING_NOT_SUBJECT, "~subject"},
37 {MATCHING_FROM, "from"},
38 {MATCHING_NOT_FROM, "~from"},
40 {MATCHING_NOT_TO, "~to"},
42 {MATCHING_NOT_CC, "~cc"},
43 {MATCHING_TO_OR_CC, "to_or_cc"},
44 {MATCHING_NOT_TO_AND_NOT_CC, "~to_or_cc"},
45 {MATCHING_AGE_GREATER, "age_greater"},
46 {MATCHING_AGE_LOWER, "age_lower"},
47 {MATCHING_NEWSGROUPS, "newsgroups"},
48 {MATCHING_NOT_NEWSGROUPS, "~newsgroups"},
49 {MATCHING_INREPLYTO, "inreplyto"},
50 {MATCHING_NOT_INREPLYTO, "~inreplyto"},
51 {MATCHING_REFERENCES, "references"},
52 {MATCHING_NOT_REFERENCES, "~references"},
53 {MATCHING_SCORE_GREATER, "score_greater"},
54 {MATCHING_SCORE_LOWER, "score_lower"},
56 /* content have to be read */
57 {MATCHING_HEADER, "header"},
58 {MATCHING_NOT_HEADER, "~header"},
59 {MATCHING_HEADERS_PART, "headers_part"},
60 {MATCHING_NOT_HEADERS_PART, "~headers_part"},
61 {MATCHING_MESSAGE, "message"},
62 {MATCHING_NOT_MESSAGE, "~message"},
63 {MATCHING_BODY_PART, "body_part"},
64 {MATCHING_NOT_BODY_PART, "~body_part"},
65 {MATCHING_EXECUTE, "execute"},
66 {MATCHING_NOT_EXECUTE, "~execute"},
69 {MATCHING_MATCHCASE, "matchcase"},
70 {MATCHING_MATCH, "match"},
71 {MATCHING_REGEXPCASE, "regexpcase"},
72 {MATCHING_REGEXP, "regexp"},
75 {MATCHING_SCORE, "score"},
78 {MATCHING_ACTION_MOVE, "move"},
79 {MATCHING_ACTION_COPY, "copy"},
80 {MATCHING_ACTION_DELETE, "delete"},
81 {MATCHING_ACTION_MARK, "mark"},
82 {MATCHING_ACTION_UNMARK, "unmark"},
83 {MATCHING_ACTION_MARK_AS_READ, "mark_as_read"},
84 {MATCHING_ACTION_MARK_AS_UNREAD, "mark_as_unread"},
85 {MATCHING_ACTION_FORWARD, "forward"},
86 {MATCHING_ACTION_FORWARD_AS_ATTACHMENT, "forward_as_attachment"},
87 /* {MATCHING_EXECUTE, "execute"}, */
90 gchar * get_matchparser_tab_str(gint id)
94 for(i = 0 ; i < (int) (sizeof(matchparser_tab) / sizeof(MatchParser)) ;
96 if (matchparser_tab[i].id == id)
97 return matchparser_tab[i].str;
107 header "x-mailing" match "toto"
108 subject match "regexp" & to regexp "regexp"
109 subject match "regexp" | to regexpcase "regexp" | age_sup 5
112 static gboolean matcher_is_blank(gchar ch);
114 /* ******************* parser *********************** */
116 static gboolean matcher_is_blank(gchar ch)
118 return (ch == ' ') || (ch == '\t');
121 /* parse for one condition */
123 MatcherProp * matcherprop_parse(gchar ** str)
131 gchar * header = NULL;
134 key = matcher_parse_keyword(&tmp);
141 case MATCHING_AGE_LOWER:
142 case MATCHING_AGE_GREATER:
143 case MATCHING_SCORE_LOWER:
144 case MATCHING_SCORE_GREATER:
145 value = matcher_parse_number(&tmp);
152 prop = matcherprop_new(key, NULL, 0, NULL, value);
157 case MATCHING_UNREAD:
158 case MATCHING_NOT_UNREAD:
160 case MATCHING_NOT_NEW:
161 case MATCHING_MARKED:
162 case MATCHING_NOT_MARKED:
163 case MATCHING_DELETED:
164 case MATCHING_NOT_DELETED:
165 case MATCHING_REPLIED:
166 case MATCHING_NOT_REPLIED:
167 case MATCHING_FORWARDED:
168 case MATCHING_NOT_FORWARDED:
169 prop = matcherprop_new(key, NULL, 0, NULL, 0);
174 case MATCHING_SUBJECT:
175 case MATCHING_NOT_SUBJECT:
177 case MATCHING_NOT_FROM:
179 case MATCHING_NOT_TO:
181 case MATCHING_NOT_CC:
182 case MATCHING_TO_OR_CC:
183 case MATCHING_NOT_TO_AND_NOT_CC:
184 case MATCHING_NEWSGROUPS:
185 case MATCHING_NOT_NEWSGROUPS:
186 case MATCHING_INREPLYTO:
187 case MATCHING_NOT_REFERENCES:
188 case MATCHING_REFERENCES:
189 case MATCHING_NOT_INREPLYTO:
190 case MATCHING_MESSAGE:
191 case MATCHING_NOT_MESSAGE:
192 case MATCHING_EXECUTE:
193 case MATCHING_NOT_EXECUTE:
194 case MATCHING_HEADERS_PART:
195 case MATCHING_NOT_HEADERS_PART:
196 case MATCHING_BODY_PART:
197 case MATCHING_NOT_BODY_PART:
198 case MATCHING_HEADER:
199 case MATCHING_NOT_HEADER:
200 if ((key == MATCHING_HEADER) || (key == MATCHING_NOT_HEADER)) {
201 header = matcher_parse_str(&tmp);
208 match = matcher_parse_keyword(&tmp);
217 case MATCHING_REGEXP:
218 case MATCHING_REGEXPCASE:
219 expr = matcher_parse_regexp(&tmp);
227 prop = matcherprop_new(key, header, match, expr, 0);
232 case MATCHING_MATCHCASE:
233 expr = matcher_parse_str(&tmp);
241 prop = matcherprop_new(key, header, match, expr, 0);
257 gint matcher_parse_keyword(gchar ** str)
265 dup = alloca(strlen(* str) + 1);
269 while (matcher_is_blank(*p))
274 while (!matcher_is_blank(*p) && (*p != '\0'))
278 for(i = 0 ; i < (int) (sizeof(matchparser_tab) / sizeof(MatchParser)) ;
280 if ((strlen(matchparser_tab[i].str) == p - start) &&
281 (strncasecmp(matchparser_tab[i].str, start,
296 return matchparser_tab[match].id;
299 gint matcher_parse_number(gchar ** str)
305 dup = alloca(strlen(* str) + 1);
309 while (matcher_is_blank(*p))
314 if (!isdigit(*p) && *p != '-' && *p != '+') {
318 if (*p == '-' || *p == '+')
329 gboolean matcher_parse_boolean_op(gchar ** str)
335 while (matcher_is_blank(*p))
339 *str += p - * str + 1;
342 else if (*p == '&') {
343 *str += p - * str + 1;
352 gchar * matcher_parse_regexp(gchar ** str)
358 dup = alloca(strlen(* str) + 1);
362 while (matcher_is_blank(*p))
380 return g_strdup(start);
383 gchar * matcher_parse_str(gchar ** str)
390 dup = alloca(strlen(* str) + 1);
394 while (matcher_is_blank(*p))
417 *str += dest - dup + 2;
418 return g_strdup(start);
421 /* **************** data structure allocation **************** */
424 MatcherProp * matcherprop_new(gint criteria, gchar * header,
425 gint matchtype, gchar * expr,
430 prop = g_new0(MatcherProp, 1);
431 prop->criteria = criteria;
433 prop->header = g_strdup(header);
437 prop->expr = g_strdup(expr);
440 prop->matchtype = matchtype;
448 void matcherprop_free(MatcherProp * prop)
451 if (prop->preg != NULL) {
459 /* ************** match ******************************/
462 /* match the given string */
464 static gboolean matcherprop_string_match(MatcherProp * prop, gchar * str)
472 switch(prop->matchtype) {
473 case MATCHING_REGEXPCASE:
474 case MATCHING_REGEXP:
475 if (!prop->preg && (prop->error == 0)) {
476 prop->preg = g_new0(regex_t, 1);
477 if (regcomp(prop->preg, prop->expr,
478 REG_NOSUB | REG_EXTENDED
479 | ((prop->matchtype == MATCHING_REGEXPCASE)
480 ? REG_ICASE : 0)) != 0) {
485 if (prop->preg == NULL)
488 if (regexec(prop->preg, str, 0, NULL, 0) == 0)
494 return (strstr(str, prop->expr) != NULL);
496 case MATCHING_MATCHCASE:
497 str2 = alloca(strlen(prop->expr) + 1);
498 strcpy(str2, prop->expr);
500 str1 = alloca(strlen(str) + 1);
503 return (strstr(str1, str2) != NULL);
510 gboolean matcherprop_match_execute(MatcherProp * prop, MsgInfo * info)
515 file = procmsg_get_message_file(info);
519 cmd = matching_build_command(prop->expr, info);
523 return (system(cmd) == 0);
526 /* match a message and his headers, hlist can be NULL if you don't
527 want to use headers */
529 gboolean matcherprop_match(MatcherProp * prop, MsgInfo * info)
533 switch(prop->criteria) {
536 case MATCHING_UNREAD:
537 return MSG_IS_UNREAD(info->flags);
538 case MATCHING_NOT_UNREAD:
539 return !MSG_IS_UNREAD(info->flags);
541 return MSG_IS_NEW(info->flags);
542 case MATCHING_NOT_NEW:
543 return !MSG_IS_NEW(info->flags);
544 case MATCHING_MARKED:
545 return MSG_IS_MARKED(info->flags);
546 case MATCHING_NOT_MARKED:
547 return !MSG_IS_MARKED(info->flags);
548 case MATCHING_DELETED:
549 return MSG_IS_DELETED(info->flags);
550 case MATCHING_NOT_DELETED:
551 return !MSG_IS_DELETED(info->flags);
552 case MATCHING_REPLIED:
553 return MSG_IS_REPLIED(info->flags);
554 case MATCHING_NOT_REPLIED:
555 return !MSG_IS_REPLIED(info->flags);
556 case MATCHING_FORWARDED:
557 return MSG_IS_FORWARDED(info->flags);
558 case MATCHING_NOT_FORWARDED:
559 return !MSG_IS_FORWARDED(info->flags);
560 case MATCHING_SUBJECT:
561 return matcherprop_string_match(prop, info->subject);
562 case MATCHING_NOT_SUBJECT:
563 return !matcherprop_string_match(prop, info->subject);
565 return matcherprop_string_match(prop, info->from);
566 case MATCHING_NOT_FROM:
567 return !matcherprop_string_match(prop, info->from);
569 return matcherprop_string_match(prop, info->to);
570 case MATCHING_NOT_TO:
571 return !matcherprop_string_match(prop, info->to);
573 return matcherprop_string_match(prop, info->cc);
574 case MATCHING_NOT_CC:
575 return !matcherprop_string_match(prop, info->cc);
576 case MATCHING_TO_OR_CC:
577 return matcherprop_string_match(prop, info->to)
578 || matcherprop_string_match(prop, info->cc);
579 case MATCHING_NOT_TO_AND_NOT_CC:
580 return !(matcherprop_string_match(prop, info->to)
581 || matcherprop_string_match(prop, info->cc));
582 case MATCHING_AGE_GREATER:
584 return ((t - info->date_t) / (60 * 60 * 24)) >= prop->value;
585 case MATCHING_AGE_LOWER:
587 return ((t - info->date_t) / (60 * 60 * 24)) <= prop->value;
588 case MATCHING_SCORE_GREATER:
589 return info->score >= prop->value;
590 case MATCHING_SCORE_LOWER:
591 return info->score <= prop->value;
592 case MATCHING_NEWSGROUPS:
593 return matcherprop_string_match(prop, info->newsgroups);
594 case MATCHING_NOT_NEWSGROUPS:
595 return !matcherprop_string_match(prop, info->newsgroups);
596 case MATCHING_INREPLYTO:
597 return matcherprop_string_match(prop, info->inreplyto);
598 case MATCHING_NOT_INREPLYTO:
599 return !matcherprop_string_match(prop, info->inreplyto);
600 case MATCHING_REFERENCES:
601 return matcherprop_string_match(prop, info->references);
602 case MATCHING_NOT_REFERENCES:
603 return !matcherprop_string_match(prop, info->references);
604 case MATCHING_EXECUTE:
605 return matcherprop_match_execute(prop, info);
606 case MATCHING_NOT_EXECUTE:
607 return !matcherprop_match_execute(prop, info);
613 /* ********************* MatcherList *************************** */
616 /* parse for a list of conditions */
618 MatcherList * matcherlist_parse(gchar ** str)
621 MatcherProp * matcher;
622 GSList * matchers_list = NULL;
623 gboolean bool_and = TRUE;
626 gboolean main_bool_and = TRUE;
631 matcher = matcherprop_parse(&tmp);
637 matchers_list = g_slist_append(matchers_list, matcher);
640 bool_and = matcher_parse_boolean_op(&tmp);
646 main_bool_and = bool_and;
647 matcher = matcherprop_parse(&tmp);
650 g_slist_append(matchers_list, matcher);
653 for(l = matchers_list ; l != NULL ;
655 matcherprop_free((MatcherProp *)
657 g_slist_free(matchers_list);
664 cond = matcherlist_new(matchers_list, main_bool_and);
671 MatcherList * matcherlist_new(GSList * matchers, gboolean bool_and)
675 cond = g_new0(MatcherList, 1);
677 cond->matchers = matchers;
678 cond->bool_and = bool_and;
683 void matcherlist_free(MatcherList * cond)
687 for(l = cond->matchers ; l != NULL ; l = g_slist_next(l)) {
688 matcherprop_free((MatcherProp *) l->data);
697 static void matcherlist_skip_headers(FILE *fp)
701 while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1) {
706 matcherprop_match_one_header
707 returns TRUE if buf matchs the MatchersProp criteria
710 static gboolean matcherprop_match_one_header(MatcherProp * matcher,
716 switch(matcher->criteria) {
717 case MATCHING_HEADER:
718 case MATCHING_NOT_HEADER:
719 header = procheader_parse_header(buf);
722 if (procheader_headername_equal(header->name,
724 if (matcher->criteria == MATCHING_HEADER)
725 result = matcherprop_string_match(matcher, header->body);
727 result = !matcherprop_string_match(matcher, header->body);
728 procheader_header_free(header);
732 procheader_header_free(header);
735 case MATCHING_HEADERS_PART:
736 case MATCHING_MESSAGE:
737 return matcherprop_string_match(matcher, buf);
738 case MATCHING_NOT_MESSAGE:
739 case MATCHING_NOT_HEADERS_PART:
740 return !matcherprop_string_match(matcher, buf);
746 matcherprop_criteria_header
747 returns TRUE if the headers must be matched
750 static gboolean matcherprop_criteria_headers(MatcherProp * matcher)
752 switch(matcher->criteria) {
753 case MATCHING_HEADER:
754 case MATCHING_NOT_HEADER:
755 case MATCHING_HEADERS_PART:
756 case MATCHING_NOT_HEADERS_PART:
763 static gboolean matcherprop_criteria_message(MatcherProp * matcher)
765 switch(matcher->criteria) {
766 case MATCHING_MESSAGE:
767 case MATCHING_NOT_MESSAGE:
775 matcherlist_match_one_header
776 returns TRUE if match should stop
779 static gboolean matcherlist_match_one_header(MatcherList * matchers,
784 for(l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) {
785 MatcherProp * matcher = (MatcherProp *) l->data;
787 if (matcherprop_criteria_headers(matcher) ||
788 matcherprop_criteria_message(matcher)) {
789 if (matcherprop_match_one_header(matcher, buf)) {
790 matcher->result = TRUE;
794 if (matcherprop_criteria_headers(matcher)) {
795 if (matcher->result) {
796 if (!matchers->bool_and)
806 matcherlist_match_headers
807 returns TRUE if one of the headers matchs the MatcherList criteria
810 static gboolean matcherlist_match_headers(MatcherList * matchers, FILE * fp)
814 while (procheader_get_one_field(buf, sizeof(buf), fp, NULL) != -1)
815 if (matcherlist_match_one_header(matchers, buf))
822 matcherprop_criteria_body
823 returns TRUE if the body must be matched
826 static gboolean matcherprop_criteria_body(MatcherProp * matcher)
828 switch(matcher->criteria) {
829 case MATCHING_BODY_PART:
830 case MATCHING_NOT_BODY_PART:
838 matcherprop_match_line
839 returns TRUE if the string matchs the MatcherProp criteria
842 static gboolean matcherprop_match_line(MatcherProp * matcher, gchar * line)
844 switch(matcher->criteria) {
845 case MATCHING_BODY_PART:
846 case MATCHING_MESSAGE:
847 return matcherprop_string_match(matcher, line);
848 case MATCHING_NOT_BODY_PART:
849 case MATCHING_NOT_MESSAGE:
850 return !matcherprop_string_match(matcher, line);
856 matcherlist_match_line
857 returns TRUE if the string matchs the MatcherList criteria
860 static gboolean matcherlist_match_line(MatcherList * matchers, gchar * line)
864 for(l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) {
865 MatcherProp * matcher = (MatcherProp *) l->data;
867 if (matcherprop_criteria_body(matcher) ||
868 matcherprop_criteria_message(matcher)) {
869 if (matcherprop_match_line(matcher, line)) {
870 matcher->result = TRUE;
874 if (matcher->result) {
875 if (!matchers->bool_and)
883 matcherlist_match_body
884 returns TRUE if one line of the body matchs the MatcherList criteria
887 static gboolean matcherlist_match_body(MatcherList * matchers, FILE * fp)
891 while (fgets(buf, sizeof(buf), fp) != NULL)
892 if (matcherlist_match_line(matchers, buf))
898 gboolean matcherlist_match_file(MatcherList * matchers, MsgInfo * info,
901 gboolean read_headers;
907 /* file need to be read ? */
909 read_headers = FALSE;
911 for(l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) {
912 MatcherProp * matcher = (MatcherProp *) l->data;
914 if (matcherprop_criteria_headers(matcher))
916 if (matcherprop_criteria_body(matcher))
918 if (matcherprop_criteria_message(matcher)) {
922 matcher->result = FALSE;
925 if (!read_headers && !read_body)
928 file = procmsg_get_message_file(info);
932 if ((fp = fopen(file, "r")) == NULL) {
933 FILE_OP_ERROR(file, "fopen");
938 /* read the headers */
941 if (matcherlist_match_headers(matchers, fp))
945 matcherlist_skip_headers(fp);
950 matcherlist_match_body(matchers, fp);
953 for(l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) {
954 MatcherProp * matcher = (MatcherProp *) l->data;
956 if (matcherprop_criteria_headers(matcher) ||
957 matcherprop_criteria_body(matcher) ||
958 matcherprop_criteria_message(matcher))
959 if (matcher->result) {
960 if (!matchers->bool_and) {
966 if (matchers->bool_and) {
980 /* test a list of condition */
982 gboolean matcherlist_match(MatcherList * matchers, MsgInfo * info)
987 if (matchers->bool_and)
992 /* test the cached elements */
994 for(l = matchers->matchers ; l != NULL ; l = g_slist_next(l)) {
995 MatcherProp * matcher = (MatcherProp *) l->data;
997 switch(matcher->criteria) {
999 case MATCHING_UNREAD:
1000 case MATCHING_NOT_UNREAD:
1002 case MATCHING_NOT_NEW:
1003 case MATCHING_MARKED:
1004 case MATCHING_NOT_MARKED:
1005 case MATCHING_DELETED:
1006 case MATCHING_NOT_DELETED:
1007 case MATCHING_REPLIED:
1008 case MATCHING_NOT_REPLIED:
1009 case MATCHING_FORWARDED:
1010 case MATCHING_NOT_FORWARDED:
1011 case MATCHING_SUBJECT:
1012 case MATCHING_NOT_SUBJECT:
1014 case MATCHING_NOT_FROM:
1016 case MATCHING_NOT_TO:
1018 case MATCHING_NOT_CC:
1019 case MATCHING_TO_OR_CC:
1020 case MATCHING_NOT_TO_AND_NOT_CC:
1021 case MATCHING_AGE_GREATER:
1022 case MATCHING_AGE_LOWER:
1023 case MATCHING_NEWSGROUPS:
1024 case MATCHING_NOT_NEWSGROUPS:
1025 case MATCHING_INREPLYTO:
1026 case MATCHING_NOT_INREPLYTO:
1027 case MATCHING_REFERENCES:
1028 case MATCHING_NOT_REFERENCES:
1029 case MATCHING_SCORE_GREATER:
1030 case MATCHING_SCORE_LOWER:
1031 case MATCHING_EXECUTE:
1032 case MATCHING_NOT_EXECUTE:
1033 if (matcherprop_match(matcher, info)) {
1034 if (!matchers->bool_and) {
1039 if (matchers->bool_and) {
1046 /* test the condition on the file */
1048 if (matcherlist_match_file(matchers, info, result)) {
1049 if (!matchers->bool_and)
1053 if (matchers->bool_and)
1061 static void matcherprop_print(MatcherProp * matcher)
1065 if (matcher == NULL) {
1066 printf("no matcher\n");
1070 switch (matcher->matchtype) {
1071 case MATCHING_MATCH:
1074 case MATCHING_REGEXP:
1077 case MATCHING_MATCHCASE:
1078 printf("matchcase\n");
1080 case MATCHING_REGEXPCASE:
1081 printf("regexpcase\n");
1085 for(i = 0 ; i < (int) (sizeof(matchparser_tab) / sizeof(MatchParser)) ;
1087 if (matchparser_tab[i].id == matcher->criteria)
1088 printf("%s\n", matchparser_tab[i].str);
1092 printf("expr : %s\n", matcher->expr);
1094 printf("age: %i\n", matcher->value;
1096 printf("compiled : %s\n", matcher->preg != NULL ? "yes" : "no");
1097 printf("error: %i\n", matcher->error);
1101 gchar * matcherprop_to_string(MatcherProp * matcher)
1103 gchar * matcher_str = NULL;
1104 gchar * criteria_str;
1105 gchar * matchtype_str;
1112 criteria_str = NULL;
1113 for(i = 0 ; i < (int) (sizeof(matchparser_tab) / sizeof(MatchParser)) ;
1115 if (matchparser_tab[i].id == matcher->criteria)
1116 criteria_str = matchparser_tab[i].str;
1118 if (criteria_str == NULL)
1121 switch(matcher->criteria) {
1122 case MATCHING_AGE_GREATER:
1123 case MATCHING_AGE_LOWER:
1124 case MATCHING_SCORE_GREATER:
1125 case MATCHING_SCORE_LOWER:
1126 return g_strdup_printf("%s %i", criteria_str, matcher->value);
1129 case MATCHING_UNREAD:
1130 case MATCHING_NOT_UNREAD:
1132 case MATCHING_NOT_NEW:
1133 case MATCHING_MARKED:
1134 case MATCHING_NOT_MARKED:
1135 case MATCHING_DELETED:
1136 case MATCHING_NOT_DELETED:
1137 case MATCHING_REPLIED:
1138 case MATCHING_NOT_REPLIED:
1139 case MATCHING_FORWARDED:
1140 case MATCHING_NOT_FORWARDED:
1141 return g_strdup(criteria_str);
1144 matchtype_str = NULL;
1145 for(i = 0 ; i < (int) (sizeof(matchparser_tab) / sizeof(MatchParser)) ;
1147 if (matchparser_tab[i].id == matcher->matchtype)
1148 matchtype_str = matchparser_tab[i].str;
1151 if (matchtype_str == NULL)
1154 switch (matcher->matchtype) {
1155 case MATCHING_MATCH:
1156 case MATCHING_MATCHCASE:
1158 for(p = matcher->expr; *p != 0 ; p++)
1159 if (*p == '\"') count ++;
1161 expr_str = g_new(char, strlen(matcher->expr) + count + 1);
1163 for(p = matcher->expr, out = expr_str ; *p != 0 ; p++, out++) {
1173 if (matcher->header)
1175 g_strdup_printf("%s \"%s\" %s \"%s\"",
1176 criteria_str, matcher->header,
1177 matchtype_str, expr_str);
1180 g_strdup_printf("%s %s \"%s\"", criteria_str,
1181 matchtype_str, expr_str);
1187 case MATCHING_REGEXP:
1188 case MATCHING_REGEXPCASE:
1190 if (matcher->header)
1192 g_strdup_printf("%s \"%s\" %s /%s/",
1193 criteria_str, matcher->header,
1194 matchtype_str, matcher->expr);
1197 g_strdup_printf("%s %s /%s/", criteria_str,
1198 matchtype_str, matcher->expr);
1206 gchar * matcherlist_to_string(MatcherList * matchers)
1214 count = g_slist_length(matchers->matchers);
1215 vstr = g_new(gchar *, count + 1);
1217 for (l = matchers->matchers, cur_str = vstr ; l != NULL ;
1218 l = g_slist_next(l), cur_str ++) {
1219 *cur_str = matcherprop_to_string((MatcherProp *) l->data);
1220 if (*cur_str == NULL)
1225 if (matchers->bool_and)
1226 result = g_strjoinv(" & ", vstr);
1228 result = g_strjoinv(" | ", vstr);
1230 for(cur_str = vstr ; *cur_str != NULL ; cur_str ++)
1238 gchar * matching_build_command(gchar * cmd, MsgInfo * info)
1241 gchar * filename = NULL;
1242 gchar * processed_cmd;
1246 size = strlen(cmd) + 1;
1247 while (*s != '\0') {
1254 case 's': /* subject */
1255 size += strlen(info->subject) - 2;
1257 case 'f': /* from */
1258 size += strlen(info->from) - 2;
1261 size += strlen(info->to) - 2;
1264 size += strlen(info->cc) - 2;
1266 case 'd': /* date */
1267 size += strlen(info->date) - 2;
1269 case 'i': /* message-id */
1270 size += strlen(info->msgid) - 2;
1272 case 'n': /* newsgroups */
1273 size += strlen(info->newsgroups) - 2;
1275 case 'r': /* references */
1276 size += strlen(info->references) - 2;
1278 case 'F': /* file */
1279 filename = folder_item_fetch_msg(info->folder,
1282 if (filename == NULL) {
1283 g_warning(_("filename is not set"));
1287 size += strlen(filename) - 2;
1296 processed_cmd = g_new0(gchar, size);
1300 while (*s != '\0') {
1308 case 's': /* subject */
1309 if (info->subject != NULL)
1310 strcpy(p, info->subject);
1312 strcpy(p, "(none)");
1315 case 'f': /* from */
1316 if (info->from != NULL)
1317 strcpy(p, info->from);
1319 strcpy(p, "(none)");
1323 if (info->to != NULL)
1324 strcpy(p, info->to);
1326 strcpy(p, "(none)");
1330 if (info->cc != NULL)
1331 strcpy(p, info->cc);
1333 strcpy(p, "(none)");
1336 case 'd': /* date */
1337 if (info->date != NULL)
1338 strcpy(p, info->date);
1340 strcpy(p, "(none)");
1343 case 'i': /* message-id */
1344 if (info->msgid != NULL)
1345 strcpy(p, info->msgid);
1347 strcpy(p, "(none)");
1350 case 'n': /* newsgroups */
1351 if (info->newsgroups != NULL)
1352 strcpy(p, info->newsgroups);
1354 strcpy(p, "(none)");
1357 case 'r': /* references */
1358 if (info->references != NULL)
1359 strcpy(p, info->references);
1361 strcpy(p, "(none)");
1364 case 'F': /* file */
1365 strcpy(p, filename);
1383 return processed_cmd;
1387 /* ************************************************************ */
1390 static void matcher_parse (gchar * str)
1392 matcher_parser_scan_string(str);
1393 matcher_parserparse();