/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "base/polygraph.h"
#include "xstd/h/sstream.h"
#include "xstd/RegEx.h"
#include "xstd/NetAddr.h"
#include "base/polyLogCats.h"
#include "runtime/AddrMap.h"
#include "runtime/ErrorMgr.h"
#include "runtime/LogComment.h"
#include "runtime/polyErrors.h"
#include "client/MembershipMap.h"
#include "client/RegExGroups.h"
/* RegExGrpOne */
RegExGrpOne::RegExGrpOne(RegEx *aVal): theVal(aVal) {
}
bool RegExGrpOne::match(const RegExMatchee &m, int flags, int *errNo) const {
Assert(theVal);
if (theVal->image().cmp("user_group=", 11) == 0)
return matchGroups(m, flags, errNo);
else
return matchUrl(m, flags, errNo);
}
bool RegExGrpOne::matchUrl(const RegExMatchee &m, int flags, int *errNo) const {
const char *str = 0; // optimize: cache the lookup
if (theVal->image().cmp("url=", 4) == 0)
str = m.url;
else
if (theVal->image().cmp("url_host=", 9) == 0)
str = m.urlHost;
else
if (theVal->image().cmp("url_host_ip=", 12) == 0)
str = hostIps(m.urlHost);
else
if (theVal->image().cmp("url_path=", 9) == 0)
str = m.urlPath;
if (!Should(str))
str = m.url;
return theVal->match(str, flags, errNo);
}
// there is a match if any of the groups matches
bool RegExGrpOne::matchGroups(const RegExMatchee &m, int flags, int *errNo) const {
int err;
if (!errNo)
errNo = &err;
*errNo = 0;
Assert(m.memberships);
const Array<MembershipMap*> &ms = *m.memberships;
for (int i = 0; !*errNo && i < ms.count(); ++i) {
if (ms[i]->match(theVal, m.userName, flags, errNo))
return true;
}
return false;
}
const char *RegExGrpOne::hostIps(const char *hostName) const {
Assert(TheAddrMap);
const NetAddr host(hostName, -1);
if (!host.isDomainName()) // already an IP address
return hostName;
if (!TheAddrMap->has(host)) {
if (ReportError2(errAclHostIpLookup, lgcCltSide))
Comment << "address maps cannot resolve: " << hostName << endc;
return hostName;
}
static ostringstream os;
streamFreeze(os, false);
os.seekp(0);
for (AddrMapAddrIter i = TheAddrMap->addrIter(host); i; ++i) {
if (os.tellp())
os << ',';
os << i.addr().addrA();
}
os << ends;
return os.str().c_str();
}
ostream &RegExGrpOne::print(ostream &os) const {
if (theVal)
return theVal->print(os);
else
return os << "<none>";
};
/* RegExGrpNot */
RegExGrpNot::RegExGrpNot(RegExGroup *aVal): theVal(aVal) {
}
bool RegExGrpNot::match(const RegExMatchee &m, int flags, int *errNo) const {
int err = 0;
if (!errNo)
errNo = &err;
const bool res = theVal->match(m, flags, errNo);
return (*errNo) ? false : !res;
}
ostream &RegExGrpNot::print(ostream &os) const {
if (theVal)
return theVal->print(os << "!(") << ')';
else
return os << "<none>";
}
/* RegExGrpOper */
void RegExGrpOper::add(RegExGroup *item) {
theItems.append(item);
}
ostream &RegExGrpOper::print(ostream &os) const {
if (!theItems.count()) {
os << "<none>";
} else
if (theItems.count() == 1) {
theItems.last()->print(os);
} else {
os << '(';
for (int i = 0; i < theItems.count(); ++i) {
if (i)
os << ' ' << operImage() << ' ';
theItems[i]->print(os);
}
os << ')';
}
return os;
}
/* RegExGrpAnd */
bool RegExGrpAnd::match(const RegExMatchee &m, int flags, int *) const {
for (int i = 0; i < theItems.count(); ++i) {
if (!theItems[i]->match(m, flags))
return false;
}
return true; // zero &&s is true (just like zero *s is 1)
}
const char *RegExGrpAnd::operImage() const {
return "&&";
}
/* RegExGrpOr */
bool RegExGrpOr::match(const RegExMatchee &m, int flags, int *) const {
for (int i = 0; i < theItems.count(); ++i) {
if (theItems[i]->match(m, flags))
return true;
}
return false; // zero ||s is false (just like zero +s is 0)
}
const char *RegExGrpOr::operImage() const {
return "||";
}
syntax highlighted by Code2HTML, v. 0.9.1