#include "Debug.h"
#include "util.h"
+#include <algorithm>
+
template<class T>
inline void
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;
return 1;
}
- char * const *result;
-
- if (flags.case_insensitive)
- result = names->find(const_cast<char *>(user), splaystrcasecmp);
- else
- result = names->find(const_cast<char *>(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 {
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<char *>();
+ 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);
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<char const *> *
ACLUserData::clone() const
{
- /* Splay trees don't clone yet. */
- assert (!names);
return new ACLUserData;
}