From: Francesco Chemolli Date: Wed, 7 Jan 2015 18:06:15 +0000 (+0100) Subject: Ported ACLUserData, to be finished X-Git-Tag: merge-candidate-3-v1~345^2~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=52669f3a3371ff5140ff895d89b71dabd5e8a967;p=thirdparty%2Fsquid.git Ported ACLUserData, to be finished --- diff --git a/src/acl/UserData.cc b/src/acl/UserData.cc index 8a59acfe28..eab9560cad 100644 --- a/src/acl/UserData.cc +++ b/src/acl/UserData.cc @@ -15,6 +15,8 @@ #include "Debug.h" #include "util.h" +#include + template inline void xRefFree(T &thing) @@ -24,28 +26,12 @@ xRefFree(T &thing) ACLUserData::~ACLUserData() { - if (names) { - names->destroy(xRefFree); - delete names; - } -} - -static int -splaystrcasecmp (char * const &l, char * const &r) -{ - return strcasecmp ((char *)l,(char *)r); -} - -static int -splaystrcmp (char * const &l, char * const &r) -{ - return strcmp ((char *)l,(char *)r); } bool ACLUserData::match(char const *user) { - debugs(28, 7, "aclMatchUser: user is " << user << ", case_insensitive is " << flags.case_insensitive); + debugs(28, 7, "user is " << user << ", case_insensitive is " << flags.case_insensitive); if (user == NULL || strcmp(user, "-") == 0) return 0; @@ -55,17 +41,9 @@ ACLUserData::match(char const *user) return 1; } - char * const *result; - - if (flags.case_insensitive) - result = names->find(const_cast(user), splaystrcasecmp); - else - result = names->find(const_cast(user), splaystrcmp); - - /* Top=splay_splay(user,Top,(splayNode::SPLAYCMP *)dumping_strcmp); */ - debugs(28, 7, "aclMatchUser: returning " << (result != NULL)); - - return (result != NULL); + bool result = (userDataNames.find(SBuf(user)) != userDataNames.end()); + debugs(28, 7, "returning " << result); + return result; } struct UserDataAclDumpVisitor { @@ -83,51 +61,56 @@ ACLUserData::dump() const if (flags.case_insensitive) sl.push_back(SBuf("-i")); - /* damn this is VERY inefficient for long ACL lists... filling - * a SBufList this way costs Sum(1,N) iterations. For instance - * a 1000-elements list will be filled in 499500 iterations. - */ if (flags.required) { sl.push_back(SBuf("REQUIRED")); - } else if (names) { - UserDataAclDumpVisitor visitor; - names->visit(visitor); - sl.splice(sl.end(),visitor.contents); + } else { + sl.insert(sl.end(), userDataNames.begin(), userDataNames.end()); } - return sl; } +static bool +CaseInsensitveSBufCompare(const SBuf &lhs, const SBuf &rhs) +{ + return (lhs.caseCmp(rhs) < 0); +} void ACLUserData::parse() { - debugs(28, 2, "aclParseUserList: parsing user list"); - - if (!names) - names = new Splay(); + debugs(28, 2, "parsing user list"); char *t = NULL; if ((t = ConfigParser::strtokFile())) { debugs(28, 5, "aclParseUserList: First token is " << t); if (strcmp("-i", t) == 0) { - debugs(28, 5, "aclParseUserList: Going case-insensitive"); + debugs(28, 5, "Going case-insensitive"); flags.case_insensitive = true; + // due to how the std::set API work, if we want to change + // the comparison function we have to create a new std::set + UserDataNames_t newUdn(CaseInsensitveSBufCompare); + newUdn.insert(userDataNames.begin(), userDataNames.end()); + swap(userDataNames,newUdn); } else if (strcmp("REQUIRED", t) == 0) { - debugs(28, 5, "aclParseUserList: REQUIRED-type enabled"); + debugs(28, 5, "REQUIRED-type enabled"); flags.required = true; + // empty already-accumulated values + userDataNames.clear(); } else { if (flags.case_insensitive) Tolower(t); - names->insert(xstrdup(t), splaystrcmp); + if (!flags.required) { // don't add new users if acl is REQUIRED + //TODO: emit one DBG_PARSE_NOTE warning about incorrect config + userDataNames.insert(SBuf(t)); + } } } - debugs(28, 3, "aclParseUserList: Case-insensitive-switch is " << flags.case_insensitive); + debugs(28, 3, "Case-insensitive-switch is " << flags.case_insensitive); /* we might inherit from a previous declaration */ - debugs(28, 4, "aclParseUserList: parsing user list"); + debugs(28, 4, "parsing user list"); while ((t = ConfigParser::strtokFile())) { debugs(28, 6, "aclParseUserList: Got token: " << t); @@ -135,21 +118,22 @@ ACLUserData::parse() if (flags.case_insensitive) Tolower(t); - names->insert(xstrdup(t), splaystrcmp); + if (!flags.required) { // don't add new users if acl is REQUIRED + //TODO: emit one DBG_PARSE_NOTE warning about incorrect config + userDataNames.insert(SBuf(t)); + } } } bool ACLUserData::empty() const { - return (!names || names->empty()) && !flags.required; + return userDataNames.empty() && !flags.required; } ACLData * ACLUserData::clone() const { - /* Splay trees don't clone yet. */ - assert (!names); return new ACLUserData; } diff --git a/src/acl/UserData.h b/src/acl/UserData.h index 521d779c86..458a08d9e0 100644 --- a/src/acl/UserData.h +++ b/src/acl/UserData.h @@ -11,8 +11,11 @@ #include "acl/Acl.h" #include "acl/Data.h" +#include "SBuf.h" #include "splay.h" +#include + class ACLUserData : public ACLData { MEMPROXY_CLASS(ACLUserData); @@ -25,12 +28,16 @@ public: bool empty() const; virtual ACLData *clone() const; - Splay *names; +private: + + typedef std::set UserDataNames_t; + UserDataNames_t userDataNames; struct { bool case_insensitive; bool required; } flags; + }; #endif /* SQUID_ACLUSERDATA_H */