00001
00002
00003
00004
00005 #ifndef __NewsgroupFilter_h__
00006 #define __NewsgroupFilter_h__
00007
00008 #include <string>
00009
00010 #include "Newsgroup.h"
00011 #include "wildmat.h"
00012
00019 class NewsgroupFilter {
00020 private:
00021 string rulelist;
00022 const char *c_rulelist;
00023 string Wildmat;
00024 int WildmatSearch;
00025
00026 class RuleIterator {
00027 const char *rulelist, *rulelistp;
00028 char rule[1 + MAXNEWSGROUPNAMELEN];
00029
00030 public:
00031 enum { iter_begin, iter_end };
00032
00033 RuleIterator():rulelist(NULL), rulelistp(NULL) {
00034 rule[0] = '\0';
00035 } RuleIterator(const char *rulelist, int pos)
00036 :rulelist(rulelist) {
00037 if (pos == iter_begin) {
00038 char *rulep = rule;
00039 char c;
00040 rulelistp = rulelist;
00041 while ((c = *rulelistp) && c != ',') {
00042 *rulep = c;
00043 ++rulelistp;
00044 ++rulep;
00045 } *rulep = '\0';
00046 } else {
00047 rulelistp = NULL;
00048 }
00049 }
00050
00051 RuleIterator & operator++() {
00052 char *rulep = rule;
00053 char c;
00054 if (*rulelistp) {
00055 ++rulelistp;
00056 while ((c = *rulelistp) && c != ',') {
00057 *rulep = c;
00058 ++rulelistp;
00059 ++rulep;
00060 }
00061 *rulep = '\0';
00062 } else {
00063 rulelistp = NULL;
00064 }
00065
00066 return *this;
00067 }
00068
00069 const char *operator*() {
00070 return rule;
00071 }
00072
00073 int operator==(const RuleIterator & iter2) {
00074 return rulelistp == iter2.rulelistp;
00075 }
00076
00077 int operator!=(const RuleIterator & iter2) {
00078 return rulelistp != iter2.rulelistp;
00079 }
00080
00081 const RuleIterator & operator=(const RuleIterator & iter2) {
00082 rulelistp = iter2.rulelistp;
00083 strcpy(rule, iter2.rule);
00084 return *this;
00085 }
00086 };
00087
00094 void add_rule_to_rulelist(string & rulelist, const char *rule) {
00095 const char *p = rulelist.c_str(), *q;
00096
00097 do {
00098 q = rule;
00099 while (*p == *q) {
00100 ++p;
00101 ++q;
00102 }
00103 if (*q == '\0' && (*p == '\0' || *p == ',')) {
00104
00105 return;
00106 }
00107 while (*p && *p++ != ',');
00108 } while (*p);
00109
00110 rulelist += rule;
00111 rulelist += ',';
00112 }
00113
00114 RuleIterator begin() const {
00115 return RuleIterator(c_rulelist, RuleIterator::iter_begin);
00116 } RuleIterator end() const {
00117 return RuleIterator(c_rulelist, RuleIterator::iter_end);
00118 } public:
00119 NewsgroupFilter():WildmatSearch(0) {
00120 c_rulelist = rulelist.c_str();
00121 }
00122
00128 NewsgroupFilter(const NewsgroupFilter & filter)
00129 : rulelist(filter.rulelist), WildmatSearch(0) {
00130 this->c_rulelist = this->rulelist.c_str();
00131 }
00132
00140 NewsgroupFilter(const char *rulelist)
00141 :rulelist(rulelist), WildmatSearch(0) {
00142 this->c_rulelist = this->rulelist.c_str();
00143 }
00144
00145 NewsgroupFilter & operator=(const NewsgroupFilter & filter) {
00146 this->rulelist = filter.rulelist;
00147 this->c_rulelist = rulelist.c_str();
00148 this->WildmatSearch = filter.WildmatSearch;
00149 if (this->WildmatSearch) {
00150 this->Wildmat = filter.Wildmat;
00151 }
00152 return *this;
00153 }
00154
00155 NewsgroupFilter & operator=(const char *rulelist) {
00156 this->rulelist = rulelist;
00157 this->c_rulelist = this->rulelist.c_str();
00158 return *this;
00159 }
00160
00161 NewsgroupFilter & operator=(const string & rulelist) {
00162 this->rulelist = rulelist;
00163 this->c_rulelist = this->rulelist.c_str();
00164 return *this;
00165 }
00166
00167 int operator==(const char *rulelist) {
00168 return this->rulelist == rulelist;
00169 }
00170
00178 void setWildmat(const char *pWildmat) {
00179 Wildmat = pWildmat;
00180 WildmatSearch = 1;
00181 }
00182
00189 const string& getRulelist (void) {
00190 return rulelist;
00191 }
00192
00204 int matches(const char *newsgroup) const {
00205 char c;
00206 int j, clen, bmlen = 0, bmrej = 0;
00207 int rejrule = 0;
00208
00209 j = 0;
00210 do {
00211 clen = 0;
00212 if (c_rulelist[j] == '!') {
00213 j++;
00214 rejrule = 1;
00215 } else {
00216 rejrule = 0;
00217 }
00218 while ((c = c_rulelist[j]) && c == newsgroup[clen]) {
00219 clen++;
00220 j++;
00221 }
00222
00223 switch (c) {
00224 case ',':
00225 case '\0':
00226 if (newsgroup[clen] != '\0'
00227 && !isspace(newsgroup[clen])) {
00228 clen = -2;
00229 }
00230 clen++;
00231 break;
00232 case '*':
00233 clen++;
00234 break;
00235 default:
00236 clen = -1;
00237 break;
00238 }
00239
00240 if (clen > bmlen) {
00241 bmlen = clen;
00242 bmrej = rejrule;
00243 }
00244
00245 while (c && c != ',') {
00246 j++;
00247 c = c_rulelist[j];
00248 }
00249 j++;
00250 } while (c);
00251
00252 if (bmrej) {
00253 return -bmlen;
00254 } else if (!WildmatSearch) {
00255 return bmlen;
00256 } else {
00257 return (wildmat(newsgroup, Wildmat.c_str())? (1)
00258 : (0));
00259 }
00260
00261 }
00262
00271 NewsgroupFilter & operator|=(const NewsgroupFilter & filter2) {
00272 string new_rulelist;
00273 RuleIterator begin, end;
00274 const char *grp;
00275
00276 begin = this->begin();
00277 end = this->end();
00278 while (begin != end) {
00279
00280
00281 if ((grp = *begin)[0] != '!'
00282 || filter2.matches(grp + 1) <= 0) {
00283 add_rule_to_rulelist(new_rulelist, grp);
00284 }
00285 ++begin;
00286 }
00287
00288 begin = filter2.begin();
00289 end = filter2.end();
00290 while (begin != end) {
00291
00292 if ((grp = *begin)[0] != '!') {
00293 if (matches(grp) <= 0) {
00294 add_rule_to_rulelist(new_rulelist,
00295 grp);
00296 }
00297 } else if (matches(grp + 1) <= 0) {
00298 add_rule_to_rulelist(new_rulelist, grp);
00299 }
00300 ++begin;
00301 }
00302
00303 long l;
00304 if ((l = new_rulelist.length()) > 0) {
00305 new_rulelist.replace(l - 1, l, "");
00306 }
00307 rulelist = new_rulelist;
00308 c_rulelist = rulelist.c_str();
00309 return *this;
00310 }
00311
00320 NewsgroupFilter & operator&=(const NewsgroupFilter & filter2) {
00321 string new_rulelist;
00322 RuleIterator begin, end;
00323 const char *grp;
00324
00325 begin = this->begin();
00326 end = this->end();
00327 while (begin != end) {
00328
00329
00330 if ((grp = *begin)[0] == '!'
00331 || filter2.matches(grp) > 0) {
00332 add_rule_to_rulelist(new_rulelist, grp);
00333 }
00334 ++begin;
00335 }
00336
00337 begin = filter2.begin();
00338 end = filter2.end();
00339 while (begin != end) {
00340
00341 if ((grp = *begin)[0] != '!') {
00342 if (matches(grp) > 0) {
00343 add_rule_to_rulelist(new_rulelist,
00344 grp);
00345 }
00346 } else if (matches(grp + 1) > 0) {
00347 add_rule_to_rulelist(new_rulelist, grp);
00348 }
00349 ++begin;
00350 }
00351
00352 long l;
00353 if ((l = new_rulelist.length()) > 0) {
00354 new_rulelist.replace(l - 1, l, "");
00355 }
00356 rulelist = new_rulelist;
00357 c_rulelist = rulelist.c_str();
00358 return *this;
00359 }
00360
00361 friend std::ostream & operator <<(std::ostream & os,
00362 const NewsgroupFilter & f) {
00363 os << f.rulelist;
00364 return os;
00365 }
00366 };
00367
00368 #endif