2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2001 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.
28 #include <sys/types.h>
32 #include "procheader.h"
37 FolderItem
*filter_get_dest_folder(GSList
*fltlist
, const gchar
*file
)
39 static FolderItem
*dummy
= NULL
;
40 FolderItem
*dest_folder
= NULL
;
44 g_return_val_if_fail(file
!= NULL
, NULL
);
45 if (!fltlist
) return NULL
;
47 hlist
= procheader_get_header_list_from_file(file
);
48 if (!hlist
) return NULL
;
50 for (cur
= fltlist
; cur
!= NULL
; cur
= cur
->next
) {
51 filter
= (Filter
*)cur
->data
;
52 if (filter_match_condition(filter
, hlist
)) {
53 if (filter
->action
== FLT_NOTRECV
) {
55 dummy
= folder_item_new(NULL
, NULL
);
56 dummy
->path
= g_strdup(FILTER_NOT_RECEIVE
);
60 dest_folder
= folder_find_item_from_identifier
66 procheader_header_list_destroy(hlist
);
71 static gboolean
strfind(const gchar
*haystack
, const gchar
*needle
)
73 return strstr(haystack
, needle
) != NULL
? TRUE
: FALSE
;
76 static gboolean
strnotfind(const gchar
*haystack
, const gchar
*needle
)
78 return strstr(haystack
, needle
) != NULL
? FALSE
: TRUE
;
81 static gboolean
strcasefind(const gchar
*haystack
, const gchar
*needle
)
83 return strcasestr(haystack
, needle
) != NULL
? TRUE
: FALSE
;
86 static gboolean
strcasenotfind(const gchar
*haystack
, const gchar
*needle
)
88 return strcasestr(haystack
, needle
) != NULL
? FALSE
: TRUE
;
91 static gboolean
strmatch_regex(const gchar
*haystack
, const gchar
*needle
)
97 ret
= regcomp(&preg
, needle
, 0);
98 if (ret
!= 0) return FALSE
;
100 ret
= regexec(&preg
, haystack
, 1, pmatch
, 0);
103 if (ret
== REG_NOMATCH
) return FALSE
;
105 if (pmatch
[0].rm_so
!= -1)
111 gboolean
filter_match_condition(Filter
*filter
, GSList
*hlist
)
114 gboolean (*StrFind1
) (const gchar
*hs
, const gchar
*nd
);
115 gboolean (*StrFind2
) (const gchar
*hs
, const gchar
*nd
);
117 g_return_val_if_fail(filter
->name1
!= NULL
, FALSE
);
119 if (FLT_IS_REGEX(filter
->flag1
))
120 StrFind1
= strmatch_regex
;
121 else if (FLT_IS_CASE_SENS(filter
->flag1
))
122 StrFind1
= FLT_IS_CONTAIN(filter
->flag1
)
123 ? strfind
: strnotfind
;
125 StrFind1
= FLT_IS_CONTAIN(filter
->flag1
)
126 ? strcasefind
: strcasenotfind
;
128 if (FLT_IS_REGEX(filter
->flag2
))
129 StrFind2
= strmatch_regex
;
130 if (FLT_IS_CASE_SENS(filter
->flag2
))
131 StrFind2
= FLT_IS_CONTAIN(filter
->flag2
)
132 ? strfind
: strnotfind
;
134 StrFind2
= FLT_IS_CONTAIN(filter
->flag2
)
135 ? strcasefind
: strcasenotfind
;
137 if (filter
->cond
== FLT_AND
) {
138 gboolean match1
= FALSE
, match2
= FALSE
;
140 /* ignore second condition if not set */
141 if (!filter
->name2
) match2
= TRUE
;
143 for (; hlist
!= NULL
; hlist
= hlist
->next
) {
144 header
= hlist
->data
;
147 procheader_headername_equal(header
->name
,
149 if (!filter
->body1
||
150 StrFind1(header
->body
, filter
->body1
))
154 procheader_headername_equal(header
->name
,
156 if (!filter
->body2
||
157 StrFind2(header
->body
, filter
->body2
))
161 if (match1
&& match2
) return TRUE
;
163 } else if (filter
->cond
== FLT_OR
) {
164 for (; hlist
!= NULL
; hlist
= hlist
->next
) {
165 header
= hlist
->data
;
167 if (procheader_headername_equal(header
->name
,
169 if (!filter
->body1
||
170 StrFind1(header
->body
, filter
->body1
))
173 procheader_headername_equal(header
->name
,
175 if (!filter
->body2
||
176 StrFind2(header
->body
, filter
->body2
))
184 gchar
*filter_get_str(Filter
*filter
)
188 str
= g_strdup_printf
189 ("%s\t%s\t%c\t%s\t%s\t%s\t%d\t%d\t%c",
190 filter
->name1
, filter
->body1
? filter
->body1
: "",
191 filter
->name2
? (filter
->cond
== FLT_AND
? '&' : '|') : ' ',
192 filter
->name2
? filter
->name2
: "",
193 filter
->body2
? filter
->body2
: "",
194 filter
->dest
? filter
->dest
: "",
195 (guint
)filter
->flag1
, (guint
)filter
->flag2
,
196 filter
->action
== FLT_MOVE
? 'm' :
197 filter
->action
== FLT_NOTRECV
? 'n' :
198 filter
->action
== FLT_DELETE
? 'd' : ' ');
203 #define PARSE_ONE_PARAM(p, srcp) \
205 p = strchr(srcp, '\t'); \
206 if (!p) return NULL; \
211 Filter
*filter_read_str(const gchar
*str
)
215 gchar
*name1
, *body1
, *op
, *name2
, *body2
, *dest
;
216 gchar
*flag1
= NULL
, *flag2
= NULL
, *action
= NULL
;
218 Xstrdup_a(tmp
, str
, return NULL
);
221 PARSE_ONE_PARAM(body1
, name1
);
222 PARSE_ONE_PARAM(op
, body1
);
223 PARSE_ONE_PARAM(name2
, op
);
224 PARSE_ONE_PARAM(body2
, name2
);
225 PARSE_ONE_PARAM(dest
, body2
);
226 if (strchr(dest
, '\t')) {
229 PARSE_ONE_PARAM(flag1
, dest
);
230 PARSE_ONE_PARAM(flag2
, flag1
);
231 PARSE_ONE_PARAM(action
, flag2
);
232 if ((p
= strchr(action
, '\t'))) *p
= '\0';
235 filter
= g_new0(Filter
, 1);
236 filter
->name1
= *name1
? g_strdup(name1
) : NULL
;
237 filter
->body1
= *body1
? g_strdup(body1
) : NULL
;
238 filter
->name2
= *name2
? g_strdup(name2
) : NULL
;
239 filter
->body2
= *body2
? g_strdup(body2
) : NULL
;
240 filter
->cond
= (*op
== '|') ? FLT_OR
: FLT_AND
;
241 filter
->dest
= *dest
? g_strdup(dest
) : NULL
;
243 filter
->flag1
= FLT_CONTAIN
;
244 filter
->flag2
= FLT_CONTAIN
;
245 if (flag1
) filter
->flag1
= (FilterFlag
)strtoul(flag1
, NULL
, 10);
246 if (flag2
) filter
->flag2
= (FilterFlag
)strtoul(flag2
, NULL
, 10);
248 if (!strcmp2(dest
, FILTER_NOT_RECEIVE
))
249 filter
->action
= FLT_NOTRECV
;
251 filter
->action
= FLT_MOVE
;
254 case 'm': filter
->action
= FLT_MOVE
; break;
255 case 'n': filter
->action
= FLT_NOTRECV
; break;
256 case 'd': filter
->action
= FLT_DELETE
; break;
257 default: g_warning("Invalid action: `%c'\n", *action
);
264 void filter_free(Filter
*filter
)
268 g_free(filter
->name1
);
269 g_free(filter
->body1
);
271 g_free(filter
->name2
);
272 g_free(filter
->body2
);
274 g_free(filter
->dest
);