2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999,2000 Hiroyuki Yamamoto
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #include "procheader.h"
35 FolderItem *filter_get_dest_folder(GSList *fltlist, const gchar *file)
37 static FolderItem *dummy = NULL;
38 FolderItem *dest_folder = NULL;
42 g_return_val_if_fail(file != NULL, NULL);
43 if (!fltlist) return NULL;
45 hlist = procheader_get_header_list(file);
46 if (!hlist) return NULL;
48 for (cur = fltlist; cur != NULL; cur = cur->next) {
49 filter = (Filter *)cur->data;
50 if (filter_match_condition(filter, hlist)) {
51 if (filter->action == FLT_NOTRECV) {
53 dummy = folder_item_new(NULL, NULL);
54 dummy->path = g_strdup(FILTER_NOT_RECEIVE);
58 dest_folder = folder_find_item_from_path
64 procheader_header_list_destroy(hlist);
69 static gboolean strfind(const gchar *haystack, const gchar *needle)
71 return strstr(haystack, needle) != NULL ? TRUE : FALSE;
74 static gboolean strnotfind(const gchar *haystack, const gchar *needle)
76 return strstr(haystack, needle) != NULL ? FALSE : TRUE;
79 static gboolean strcasefind(const gchar *haystack, const gchar *needle)
81 return strcasestr(haystack, needle) != NULL ? TRUE : FALSE;
84 static gboolean strcasenotfind(const gchar *haystack, const gchar *needle)
86 return strcasestr(haystack, needle) != NULL ? FALSE : TRUE;
89 gboolean filter_match_condition(Filter *filter, GSList *hlist)
92 gboolean (*StrFind1) (const gchar *hs, const gchar *nd);
93 gboolean (*StrFind2) (const gchar *hs, const gchar *nd);
95 g_return_val_if_fail(filter->name1 != NULL, FALSE);
97 if (FLT_IS_CASE_SENS(filter->flag1))
98 StrFind1 = FLT_IS_CONTAIN(filter->flag1)
99 ? strfind : strnotfind;
101 StrFind1 = FLT_IS_CONTAIN(filter->flag1)
102 ? strcasefind : strcasenotfind;
104 if (FLT_IS_CASE_SENS(filter->flag2))
105 StrFind2 = FLT_IS_CONTAIN(filter->flag2)
106 ? strfind : strnotfind;
108 StrFind2 = FLT_IS_CONTAIN(filter->flag2)
109 ? strcasefind : strcasenotfind;
111 if (filter->cond == FLT_AND) {
112 gboolean match1 = FALSE, match2 = FALSE;
114 /* ignore second condition if not set */
115 if (!filter->name2) match2 = TRUE;
117 for (; hlist != NULL; hlist = hlist->next) {
118 header = hlist->data;
121 !strcasecmp(header->name, filter->name1)) {
122 if (!filter->body1 ||
123 StrFind1(header->body, filter->body1))
127 !strcasecmp(header->name, filter->name2)) {
128 if (!filter->body2 ||
129 StrFind2(header->body, filter->body2))
133 if (match1 && match2) return TRUE;
135 } else if (filter->cond == FLT_OR) {
136 for (; hlist != NULL; hlist = hlist->next) {
137 header = hlist->data;
139 if (!strcasecmp(header->name, filter->name1))
140 if (!filter->body1 ||
141 StrFind1(header->body, filter->body1))
144 !strcasecmp(header->name, filter->name2))
145 if (!filter->body2 ||
146 StrFind2(header->body, filter->body2))
154 gchar *filter_get_str(Filter *filter)
158 str = g_strdup_printf
159 ("%s\t%s\t%c\t%s\t%s\t%s\t%d\t%d\t%c",
160 filter->name1, filter->body1 ? filter->body1 : "",
161 filter->name2 ? (filter->cond == FLT_AND ? '&' : '|') : ' ',
162 filter->name2 ? filter->name2 : "",
163 filter->body2 ? filter->body2 : "",
164 filter->dest ? filter->dest : "",
165 (guint)filter->flag1, (guint)filter->flag2,
166 filter->action == FLT_MOVE ? 'm' :
167 filter->action == FLT_NOTRECV ? 'n' :
168 filter->action == FLT_DELETE ? 'd' : ' ');
173 #define PARSE_ONE_PARAM(p, srcp) \
175 p = strchr(srcp, '\t'); \
176 if (!p) return NULL; \
181 Filter *filter_read_str(const gchar *str)
185 gchar *name1, *body1, *op, *name2, *body2, *dest;
186 gchar *flag1 = NULL, *flag2 = NULL, *action = NULL;
188 Xalloca(tmp, strlen(str) + 1, return NULL);
192 PARSE_ONE_PARAM(body1, name1);
193 PARSE_ONE_PARAM(op, body1);
194 PARSE_ONE_PARAM(name2, op);
195 PARSE_ONE_PARAM(body2, name2);
196 PARSE_ONE_PARAM(dest, body2);
197 if (strchr(dest, '\t')) {
200 PARSE_ONE_PARAM(flag1, dest);
201 PARSE_ONE_PARAM(flag2, flag1);
202 PARSE_ONE_PARAM(action, flag2);
203 if ((p = strchr(action, '\t'))) *p = '\0';
206 filter = g_new0(Filter, 1);
207 filter->name1 = *name1 ? g_strdup(name1) : NULL;
208 filter->body1 = *body1 ? g_strdup(body1) : NULL;
209 filter->name2 = *name2 ? g_strdup(name2) : NULL;
210 filter->body2 = *body2 ? g_strdup(body2) : NULL;
211 filter->cond = (*op == '|') ? FLT_OR : FLT_AND;
212 filter->dest = *dest ? g_strdup(dest) : NULL;
214 filter->flag1 = FLT_CONTAIN;
215 filter->flag2 = FLT_CONTAIN;
216 if (flag1) filter->flag1 = (FilterFlag)strtoul(flag1, NULL, 10);
217 if (flag2) filter->flag2 = (FilterFlag)strtoul(flag2, NULL, 10);
219 if (!strcmp2(dest, FILTER_NOT_RECEIVE))
220 filter->action = FLT_NOTRECV;
222 filter->action = FLT_MOVE;
225 case 'm': filter->action = FLT_MOVE; break;
226 case 'n': filter->action = FLT_NOTRECV; break;
227 case 'd': filter->action = FLT_DELETE; break;
228 default: g_warning("Invalid action: `%c'\n", *action);
235 void filter_free(Filter *filter)
239 g_free(filter->name1);
240 g_free(filter->body1);
242 g_free(filter->name2);
243 g_free(filter->body2);
245 g_free(filter->dest);