ACLRegexData::~ACLRegexData()
{
- delete data;
}
bool
ACLRegexData::match(char const *word)
{
- if (word == NULL)
+ if (!word)
return 0;
- debugs(28, 3, "aclRegexData::match: checking '" << word << "'");
+ debugs(28, 3, "checking '" << word << "'");
- RegexList *first, *prev;
-
- first = data;
-
- prev = NULL;
-
- RegexList *current = first;
-
- while (current) {
- debugs(28, 3, "aclRegexData::match: looking for '" << current->pattern << "'");
-
- if (regexec(¤t->regex, word, 0, 0, 0) == 0) {
- if (prev != NULL) {
- /* shift the element just found to the second position
- * in the list */
- prev->next = current->next;
- current->next = first->next;
- first->next = current;
- }
-
- debugs(28, 2, "aclRegexData::match: match '" << current->pattern << "' found in '" << word << "'");
+ // walk the list of patterns to see if one matches
+ for (auto &i : data) {
+ if (regexec(&i.regex, word, 0, 0, 0) == 0) {
+ debugs(28, 2, "'" << i.pattern << "' found in '" << word << "'");
+ // TODO: old code also popped the pattern to second place of the list
+ // in order to reduce patterns search times.
return 1;
}
-
- prev = current;
- current = current->next;
}
return 0;
ACLRegexData::dump() const
{
SBufList sl;
- RegexList *temp = data;
int flags = REG_EXTENDED | REG_NOSUB;
- while (temp != NULL) {
- if (temp->flags != flags) {
- if ((temp->flags®_ICASE) != 0) {
+ // walk and dump the list
+ // keeping the flags values consistent
+ for (auto &i : data) {
+ if (i.flags != flags) {
+ if ((i.flags®_ICASE) != 0) {
sl.push_back(SBuf("-i"));
} else {
sl.push_back(SBuf("+i"));
}
- flags = temp->flags;
+ flags = i.flags;
}
- sl.push_back(SBuf(temp->pattern));
- temp = temp->next;
+ sl.push_back(SBuf(i.pattern));
}
return sl;
return t;
}
-static RegexList **
-compileRE(RegexList **Tail, char * RE, int flags)
+static bool
+compileRE(std::list<RegexPattern> &curlist, char * RE, int flags)
{
- int errcode;
- RegexList *q;
- regex_t comp;
+ if (RE == NULL || *RE == '\0')
+ return curlist.empty(); // XXX: old code did this. It looks wrong.
- if (RE == NULL || *RE == '\0')
- return Tail;
-
- if ((errcode = regcomp(&comp, RE, flags)) != 0) {
+ regex_t comp;
+ if (int errcode = regcomp(&comp, RE, flags)) {
char errbuf[256];
regerror(errcode, &comp, errbuf, sizeof errbuf);
debugs(28, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
debugs(28, DBG_CRITICAL, "ERROR: invalid regular expression: '" << RE << "': " << errbuf);
- return NULL;
+ return false;
}
- debugs(28, 2, "compileRE: compiled '" << RE << "' with flags " << flags );
+ debugs(28, 2, "compiled '" << RE << "' with flags " << flags);
- q = new RegexList(flags, RE);
- q->regex = comp;
- *(Tail) = q;
- Tail = &q->next;
+ curlist.emplace_back(flags, RE);
+ curlist.back().regex = comp;
- return Tail;
+ return true;
}
/** Compose and compile one large RE from a set of (small) REs.
* called only once per ACL.
*/
static int
-compileOptimisedREs(RegexList **curlist, wordlist * wl)
+compileOptimisedREs(std::list<RegexPattern> &curlist, wordlist * wl)
{
- RegexList **Tail;
- RegexList *newlist;
- RegexList **newlistp;
+ std::list<RegexPattern> newlist;
int numREs = 0;
int flags = REG_EXTENDED | REG_NOSUB;
int largeREindex = 0;
char largeRE[BUFSIZ];
-
- newlist = NULL;
- newlistp = &newlist;
-
- largeRE[0] = '\0';
+ *largeRE = 0;
while (wl != NULL) {
int RElen;
debugs(28, 2, "compileOptimisedREs: optimisation of -i ... -i" );
} else {
debugs(28, 2, "compileOptimisedREs: -i" );
- newlistp = compileRE( newlistp, largeRE, flags );
- if (newlistp == NULL) {
- delete newlist;
+ if (!compileRE(newlist, largeRE, flags))
return 0;
- }
flags |= REG_ICASE;
largeRE[largeREindex=0] = '\0';
}
debugs(28, 2, "compileOptimisedREs: optimisation of +i ... +i");
} else {
debugs(28, 2, "compileOptimisedREs: +i");
- newlistp = compileRE( newlistp, largeRE, flags );
- if (newlistp == NULL) {
- delete newlist;
+ if (!compileRE(newlist, largeRE, flags))
return 0;
- }
flags &= ~REG_ICASE;
largeRE[largeREindex=0] = '\0';
}
++numREs;
} else {
debugs(28, 2, "compileOptimisedREs: buffer full, generating new optimised RE..." );
- newlistp = compileRE( newlistp, largeRE, flags );
- if (newlistp == NULL) {
- delete newlist;
+ if (!compileRE(newlist, largeRE, flags))
return 0;
- }
largeRE[largeREindex=0] = '\0';
continue; /* do the loop again to add the RE to largeRE */
}
wl = wl->next;
}
- newlistp = compileRE( newlistp, largeRE, flags );
- if (newlistp == NULL) {
- delete newlist;
+ if (!compileRE(newlist, largeRE, flags))
return 0;
- }
/* all was successful, so put the new list at the tail */
- if (*curlist == NULL) {
- *curlist = newlist;
- } else {
- for (Tail = curlist; *Tail != NULL; Tail = &((*Tail)->next))
- ;
- (*Tail) = newlist;
- }
+ curlist.splice(curlist.end(), newlist);
debugs(28, 2, "compileOptimisedREs: " << numREs << " REs are optimised into one RE.");
if (numREs > 100) {
}
static void
-compileUnoptimisedREs(RegexList **curlist, wordlist * wl)
+compileUnoptimisedREs(std::list<RegexPattern> &curlist, wordlist * wl)
{
- RegexList **Tail;
- RegexList **newTail;
int flags = REG_EXTENDED | REG_NOSUB;
- for (Tail = curlist; *Tail != NULL; Tail = &((*Tail)->next))
- ;
-
while (wl != NULL) {
if (strcmp(wl->key, "-i") == 0) {
flags |= REG_ICASE;
} else if (strcmp(wl->key, "+i") == 0) {
flags &= ~REG_ICASE;
} else {
- newTail = compileRE( Tail, wl->key , flags );
- if (newTail == NULL)
+ if (!compileRE(curlist, wl->key , flags))
debugs(28, DBG_CRITICAL, "ERROR: Skipping regular expression. Compile failed: '" << wl->key << "'");
- else
- Tail = newTail;
}
wl = wl->next;
}
}
-static void
-aclParseRegexList(RegexList **curlist)
+void
+ACLRegexData::parse()
{
- char *t;
- wordlist *wl = NULL;
+ debugs(28, 2, "new Regex line or file");
- debugs(28, 2, HERE << "aclParseRegexList: new Regex line or file");
-
- while ((t = ConfigParser::RegexStrtokFile()) != NULL) {
+ wordlist *wl = NULL;
+ while (char *t = ConfigParser::RegexStrtokFile()) {
const char *clean = removeUnnecessaryWildcards(t);
if (strlen(clean) > BUFSIZ-1) {
debugs(28, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
debugs(28, DBG_CRITICAL, "ERROR: Skipping regular expression. Larger than " << BUFSIZ-1 << " characters: '" << clean << "'");
} else {
- debugs(28, 3, "aclParseRegexList: buffering RE '" << clean << "'");
+ debugs(28, 3, "buffering RE '" << clean << "'");
wordlistAdd(&wl, clean);
}
}
- if (!compileOptimisedREs(curlist, wl)) {
+ if (!compileOptimisedREs(data, wl)) {
debugs(28, DBG_IMPORTANT, "WARNING: optimisation of regular expressions failed; using fallback method without optimisation");
- compileUnoptimisedREs(curlist, wl);
+ compileUnoptimisedREs(data, wl);
}
wordlistDestroy(&wl);
}
-void
-ACLRegexData::parse()
-{
- aclParseRegexList(&data);
-}
-
bool
ACLRegexData::empty() const
{
- return data == NULL;
+ return data.empty();
}
ACLData<char const *> *
ACLRegexData::clone() const
{
/* Regex's don't clone yet. */
- assert (!data);
+ assert(data.empty());
return new ACLRegexData;
}