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
00188 const string& getRulelist (void) {
00189 return rulelist;
00190 }
00191
00203 int matches(const char *newsgroup) const {
00204 char c;
00205 int j, clen, bmlen = 0, bmrej = 0;
00206 int rejrule = 0;
00207
00208 j = 0;
00209 do {
00210 clen = 0;
00211 if (c_rulelist[j] == '!') {
00212 j++;
00213 rejrule = 1;
00214 } else {
00215 rejrule = 0;
00216 }
00217 while ((c = c_rulelist[j]) && c == newsgroup[clen]) {
00218 clen++;
00219 j++;
00220 }
00221
00222 switch (c) {
00223 case ',':
00224 case '\0':
00225 if (newsgroup[clen] != '\0'
00226 && !isspace(newsgroup[clen])) {
00227 clen = -2;
00228 }
00229 clen++;
00230 break;
00231 case '*':
00232 clen++;
00233 break;
00234 default:
00235 clen = -1;
00236 break;
00237 }
00238
00239 if (clen > bmlen) {
00240 bmlen = clen;
00241 bmrej = rejrule;
00242 }
00243
00244 while (c && c != ',') {
00245 j++;
00246 c = c_rulelist[j];
00247 }
00248 j++;
00249 } while (c);
00250
00251 if (bmrej) {
00252 return -bmlen;
00253 } else if (!WildmatSearch) {
00254 return bmlen;
00255 } else {
00256 return (wildmat(newsgroup, Wildmat.c_str())? (1)
00257 : (0));
00258 }
00259
00260 }
00261
00270 NewsgroupFilter & operator|=(const NewsgroupFilter & filter2) {
00271 string new_rulelist;
00272 RuleIterator begin, end;
00273 const char *grp;
00274
00275 begin = this->begin();
00276 end = this->end();
00277 while (begin != end) {
00278
00279
00280 if ((grp = *begin)[0] != '!'
00281 || filter2.matches(grp + 1) <= 0) {
00282 add_rule_to_rulelist(new_rulelist, grp);
00283 }
00284 ++begin;
00285 }
00286
00287 begin = filter2.begin();
00288 end = filter2.end();
00289 while (begin != end) {
00290
00291 if ((grp = *begin)[0] != '!') {
00292 if (matches(grp) <= 0) {
00293 add_rule_to_rulelist(new_rulelist,
00294 grp);
00295 }
00296 } else if (matches(grp + 1) <= 0) {
00297 add_rule_to_rulelist(new_rulelist, grp);
00298 }
00299 ++begin;
00300 }
00301
00302 long l;
00303 if ((l = new_rulelist.length()) > 0) {
00304 new_rulelist.replace(l - 1, l, "");
00305 }
00306 rulelist = new_rulelist;
00307 c_rulelist = rulelist.c_str();
00308 return *this;
00309 }
00310
00319 NewsgroupFilter & operator&=(const NewsgroupFilter & filter2) {
00320 string new_rulelist;
00321 RuleIterator begin, end;
00322 const char *grp;
00323
00324 begin = this->begin();
00325 end = this->end();
00326 while (begin != end) {
00327
00328
00329 if ((grp = *begin)[0] == '!'
00330 || filter2.matches(grp) > 0) {
00331 add_rule_to_rulelist(new_rulelist, grp);
00332 }
00333 ++begin;
00334 }
00335
00336 begin = filter2.begin();
00337 end = filter2.end();
00338 while (begin != end) {
00339
00340 if ((grp = *begin)[0] != '!') {
00341 if (matches(grp) > 0) {
00342 add_rule_to_rulelist(new_rulelist,
00343 grp);
00344 }
00345 } else if (matches(grp + 1) > 0) {
00346 add_rule_to_rulelist(new_rulelist, grp);
00347 }
00348 ++begin;
00349 }
00350
00351 long l;
00352 if ((l = new_rulelist.length()) > 0) {
00353 new_rulelist.replace(l - 1, l, "");
00354 }
00355 rulelist = new_rulelist;
00356 c_rulelist = rulelist.c_str();
00357 return *this;
00358 }
00359
00360 friend std::ostream & operator <<(std::ostream & os,
00361 const NewsgroupFilter & f) {
00362 os << f.rulelist;
00363 return os;
00364 }
00365 };
00366
00367 #endif