Mercurial > noffle
annotate src/filter.c @ 248:cd022deb8390 noffle
[svn] I've hopefully no further bugs introduced.
author | mirkol |
---|---|
date | Tue, 26 Mar 2002 17:52:48 +0000 |
parents | 21200ce10e68 |
children | 0340b9c17edc |
rev | line source |
---|---|
128 | 1 /* |
2 filter.c | |
3 | |
4 Article filtering. | |
5 | |
212 | 6 $Id: filter.c 331 2001-11-22 12:04:45Z mirkol $ |
128 | 7 */ |
8 | |
9 #if HAVE_CONFIG_H | |
10 #include <config.h> | |
11 #endif | |
12 | |
13 #include <ctype.h> | |
14 #include "common.h" | |
197
24d4cd032da5
[svn] * AUTHORS,INSTALL,NEWS,README,TODO,docs/NOTES,src/client.c,src/protocol.c,
bears
parents:
194
diff
changeset
|
15 #include "filter.h" |
128 | 16 #include "itemlist.h" |
17 #include "log.h" | |
18 #include "wildmat.h" | |
212 | 19 #include "group.h" |
128 | 20 |
21 struct | |
22 { | |
23 int nFilters; | |
24 int maxFilters; | |
25 const Filter **filters; | |
26 Bool needGroups; | |
27 } filter = { 0, 0, NULL, FALSE }; | |
28 | |
29 static unsigned long | |
30 countGroups( const char *grps ) | |
31 { | |
32 unsigned long res; | |
33 | |
34 res = 1; | |
35 while ( *grps != '\0' ) | |
36 { | |
37 if ( *grps == ',' ) | |
38 res++; | |
39 grps++; | |
40 } | |
41 | |
42 return res; | |
43 } | |
44 static unsigned long | |
45 countRefs( const char *refs ) | |
46 { | |
47 unsigned long res; | |
48 Bool inRef; | |
49 | |
50 res = 0; | |
51 inRef = FALSE; | |
52 | |
53 while ( *refs != '\0' ) | |
54 { | |
55 if ( inRef ) | |
56 { | |
57 if ( *refs == '>' ) | |
58 { | |
59 inRef = FALSE; | |
60 res++; | |
61 } | |
62 } | |
63 else if ( *refs == '<' ) | |
64 inRef = TRUE; | |
65 refs++; | |
66 } | |
67 | |
68 return res; | |
69 } | |
70 | |
71 /* Check a single rule to see if it passes. */ | |
72 static Bool | |
73 checkRule( const char *thisGrp, const char *newsgroups, | |
74 const Over *ov, const FilterRule *r ) | |
75 { | |
76 unsigned long ul; | |
77 ItemList *grps; | |
78 const char *p; | |
79 | |
80 switch( r->type ) | |
81 { | |
82 case RULE_NEWSGROUP: | |
83 if ( Wld_match( thisGrp, r->data.grp ) ) | |
84 return TRUE; | |
85 if ( newsgroups != NULL ) | |
86 { | |
87 grps = new_Itl( newsgroups, " ,\t" ); | |
88 for ( p = Itl_first( grps ); p != NULL; p = Itl_next( grps ) ) | |
89 if ( Wld_match( p, r->data.grp ) ) | |
90 return TRUE; | |
91 del_Itl( grps ); | |
92 } | |
93 return FALSE; | |
94 | |
95 case RULE_SUBJECT: | |
96 return ( regexec( &r->data.regex, Ov_subj( ov ), 0, NULL, 0 ) == 0 ); | |
97 | |
98 case RULE_FROM: | |
99 return ( regexec( &r->data.regex, Ov_from( ov ), 0, NULL, 0 ) == 0 ); | |
100 | |
101 case RULE_BYTES_LT: | |
102 return ( Ov_bytes( ov ) < r->data.amount ); | |
103 | |
104 case RULE_BYTES_EQ: | |
105 return ( Ov_bytes( ov ) == r->data.amount ); | |
106 | |
107 case RULE_BYTES_GT: | |
108 return ( Ov_bytes( ov ) > r->data.amount ); | |
109 | |
110 case RULE_LINES_LT: | |
111 return ( Ov_lines( ov ) < r->data.amount ); | |
112 | |
113 case RULE_LINES_EQ: | |
114 return ( Ov_lines( ov ) == r->data.amount ); | |
115 | |
116 case RULE_LINES_GT: | |
117 return ( Ov_lines( ov ) > r->data.amount ); | |
118 | |
119 case RULE_MSGID: | |
120 return ( regexec( &r->data.regex, Ov_msgId( ov ), 0, NULL, 0 ) == 0 ); | |
121 | |
122 case RULE_NOREFS_LT: | |
123 ul = countRefs( Ov_ref( ov ) ); | |
124 return ( ul < r->data.amount ); | |
125 | |
126 case RULE_NOREFS_EQ: | |
127 ul = countRefs( Ov_ref( ov ) ); | |
128 return ( ul == r->data.amount ); | |
129 | |
130 case RULE_NOREFS_GT: | |
131 ul = countRefs( Ov_ref( ov ) ); | |
132 return ( ul > r->data.amount ); | |
133 | |
134 case RULE_XPOSTS_LT: | |
135 if ( newsgroups == NULL ) | |
136 return FALSE; | |
137 ul = countGroups( newsgroups ); | |
138 return ( ul < r->data.amount ); | |
139 | |
140 case RULE_XPOSTS_EQ: | |
141 if ( newsgroups == NULL ) | |
142 return FALSE; | |
143 ul = countGroups( newsgroups ); | |
144 return ( ul == r->data.amount ); | |
145 | |
146 case RULE_XPOSTS_GT: | |
147 if ( newsgroups == NULL ) | |
148 return FALSE; | |
149 ul = countGroups( newsgroups ); | |
150 return ( ul > r->data.amount ); | |
212 | 151 |
152 case RULE_POST_STATUS: | |
153 if ( Grp_postAllow( thisGrp ) == r->data.postAllow ) | |
154 return TRUE; | |
155 return FALSE; | |
156 | |
128 | 157 } |
158 | |
159 ASSERT( FALSE ); /* Shouldn't get here */ | |
185
fed1334d766b
[svn] * src/client.c: Change variable only used on constant to 'const'.
bears
parents:
128
diff
changeset
|
160 return 0; /* Keep compiler quiet */ |
128 | 161 } |
162 | |
163 /* Check a single filter to see if it fires. */ | |
164 static Bool | |
165 checkFilter( const char *thisGrp, const char *newsgroups, | |
166 const Over *ov, const Filter *f ) | |
167 { | |
168 int i; | |
169 | |
170 for ( i = 0; i < f->nRules; i++ ) | |
171 if ( ! checkRule( thisGrp, newsgroups, ov, &f->rules[i] ) ) | |
172 return FALSE; | |
173 | |
174 return TRUE; | |
175 } | |
176 | |
177 /* Add a filter to the list of filters. */ | |
178 void | |
179 Flt_addFilter( const Filter *f ) | |
180 { | |
181 ASSERT( f != NULL ); | |
182 | |
183 if ( ( filter.nFilters + 1 ) > filter.maxFilters ) | |
184 { | |
185 filter.filters = | |
186 ( const Filter ** ) realloc( filter.filters, | |
187 ( filter.maxFilters + 5 ) | |
188 * sizeof( Filter * ) ); | |
189 if ( filter.filters == NULL ) | |
190 { | |
191 Log_err( "Could not realloc filter list" ); | |
192 exit( EXIT_FAILURE ); | |
193 } | |
194 filter.maxFilters += 5; | |
195 } | |
196 filter.filters[ filter.nFilters++ ] = f; | |
197 } | |
198 | |
199 /* | |
200 * Run the rules over the supplied overview. If a specific rule fires, | |
194
a4e9a20e50e5
[svn] * docs/noffle.conf.5,src/configfile.c,src/filter.h,src/filter.c:
bears
parents:
185
diff
changeset
|
201 * returns its action. If no rule fires, or a rule specifying the default |
a4e9a20e50e5
[svn] * docs/noffle.conf.5,src/configfile.c,src/filter.h,src/filter.c:
bears
parents:
185
diff
changeset
|
202 * action fires, return the default read mode. |
128 | 203 */ |
204 FilterAction | |
205 Flt_checkFilters( const char *thisGrp, const char *newsgroups, | |
206 const Over *ov, FetchMode mode ) | |
207 { | |
208 int i; | |
209 | |
210 for ( i = 0; i < filter.nFilters; i++ ) | |
211 if ( checkFilter( thisGrp, newsgroups, ov, filter.filters[ i ] ) ) | |
212 { | |
194
a4e9a20e50e5
[svn] * docs/noffle.conf.5,src/configfile.c,src/filter.h,src/filter.c:
bears
parents:
185
diff
changeset
|
213 FilterAction action = filter.filters[ i ]->action; |
a4e9a20e50e5
[svn] * docs/noffle.conf.5,src/configfile.c,src/filter.h,src/filter.c:
bears
parents:
185
diff
changeset
|
214 |
185
fed1334d766b
[svn] * src/client.c: Change variable only used on constant to 'const'.
bears
parents:
128
diff
changeset
|
215 Log_dbg( LOG_DBG_FILTER, |
fed1334d766b
[svn] * src/client.c: Change variable only used on constant to 'const'.
bears
parents:
128
diff
changeset
|
216 "Filter %d fired on message %s", |
fed1334d766b
[svn] * src/client.c: Change variable only used on constant to 'const'.
bears
parents:
128
diff
changeset
|
217 i, Ov_msgId( ov ) ); |
194
a4e9a20e50e5
[svn] * docs/noffle.conf.5,src/configfile.c,src/filter.h,src/filter.c:
bears
parents:
185
diff
changeset
|
218 if ( action == FILTER_DEFAULT ) |
a4e9a20e50e5
[svn] * docs/noffle.conf.5,src/configfile.c,src/filter.h,src/filter.c:
bears
parents:
185
diff
changeset
|
219 break; |
a4e9a20e50e5
[svn] * docs/noffle.conf.5,src/configfile.c,src/filter.h,src/filter.c:
bears
parents:
185
diff
changeset
|
220 else |
a4e9a20e50e5
[svn] * docs/noffle.conf.5,src/configfile.c,src/filter.h,src/filter.c:
bears
parents:
185
diff
changeset
|
221 return action; |
128 | 222 } |
223 | |
224 switch( mode ) | |
225 { | |
226 case FULL: return FILTER_FULL; | |
227 case THREAD: return FILTER_THREAD; | |
228 case OVER: return FILTER_XOVER; | |
229 } | |
230 | |
231 ASSERT( FALSE ); /* Shouldn't get here */ | |
185
fed1334d766b
[svn] * src/client.c: Change variable only used on constant to 'const'.
bears
parents:
128
diff
changeset
|
232 return FILTER_FULL; /* Keep compiler quiet */ |
128 | 233 } |
234 | |
235 Filter * | |
236 new_Filter( void ) | |
237 { | |
238 Filter *f; | |
239 | |
240 if ( ! ( f = ( Filter * ) malloc( sizeof( Filter ) ) ) ) | |
241 { | |
242 Log_err( "Cannot allocate Filter" ); | |
243 exit( EXIT_FAILURE ); | |
244 } | |
245 f->nRules = 0; | |
246 f->maxRules = 0; | |
247 f->rules = NULL; | |
194
a4e9a20e50e5
[svn] * docs/noffle.conf.5,src/configfile.c,src/filter.h,src/filter.c:
bears
parents:
185
diff
changeset
|
248 f->action = FILTER_DEFAULT; |
128 | 249 return f; |
250 } | |
251 | |
252 void | |
253 del_Filter( Filter *f ) | |
254 { | |
255 if ( f == NULL ) | |
256 return; | |
257 | |
258 if ( f->rules != NULL ) | |
259 free( f->rules ); | |
260 free( f ); | |
261 } | |
262 | |
263 FilterAction | |
264 Flt_action( const Filter *f ) | |
265 { | |
266 return f->action; | |
267 } | |
268 | |
269 int | |
270 Flt_nRules( const Filter *f ) | |
271 { | |
272 return f->nRules; | |
273 } | |
274 | |
275 /* | |
276 * Do we have a rule requiring us to fetch the Newsgroups: headers of | |
277 * articles? | |
278 */ | |
279 Bool | |
280 Flt_getNewsgroups( void ) | |
281 { | |
282 return filter.needGroups; | |
283 } | |
284 | |
285 FilterRule | |
286 Flt_rule( const Filter *f, int ruleNo ) | |
287 { | |
288 ASSERT( ruleNo < f->nRules ); | |
289 return f->rules[ ruleNo ]; | |
290 } | |
291 | |
292 void | |
293 Flt_setAction( Filter *f, FilterAction action ) | |
294 { | |
295 f->action = action; | |
296 } | |
297 | |
298 void | |
299 Flt_addRule( Filter *f, FilterRule rule ) | |
300 { | |
301 /* Does the rule require Newsgroups: headers to be fetched? */ | |
302 if ( rule.type == RULE_NEWSGROUP || | |
303 ( rule.type >= RULE_XPOSTS_LT && rule.type <= RULE_XPOSTS_GT ) ) | |
304 filter.needGroups = TRUE; | |
305 | |
306 if ( f->nRules + 1 > f->maxRules ) | |
307 { | |
308 f->rules = | |
309 ( FilterRule * ) realloc( f->rules, | |
310 ( f->maxRules + 5 ) | |
311 * sizeof( FilterRule ) ); | |
312 | |
313 if ( f->rules == NULL ) | |
314 { | |
315 Log_err( "Could not realloc rule list" ); | |
316 exit( EXIT_FAILURE ); | |
317 } | |
318 f->maxRules += 5; | |
319 } | |
320 f->rules[ f->nRules++ ] = rule; | |
321 } | |
322 | |
323 |