]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Ported ACLUserData, to be finished
authorFrancesco Chemolli <kinkie@squid-cache.org>
Wed, 7 Jan 2015 18:06:15 +0000 (19:06 +0100)
committerFrancesco Chemolli <kinkie@squid-cache.org>
Wed, 7 Jan 2015 18:06:15 +0000 (19:06 +0100)
src/acl/UserData.cc
src/acl/UserData.h

index 8a59acfe28f20968b31eb1951556d6841a905795..eab9560cad707c16318a85b0b95c1786d1c11b7c 100644 (file)
@@ -15,6 +15,8 @@
 #include "Debug.h"
 #include "util.h"
 
+#include <algorithm>
+
 template<class T>
 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<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 {
@@ -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<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);
@@ -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<char const *> *
 ACLUserData::clone() const
 {
-    /* Splay trees don't clone yet. */
-    assert (!names);
     return new ACLUserData;
 }
 
index 521d779c86fdf43bc55db3df685bc0ed0d014db5..458a08d9e01e3d9b3548d383142e605aef04c766 100644 (file)
 
 #include "acl/Acl.h"
 #include "acl/Data.h"
+#include "SBuf.h"
 #include "splay.h"
 
+#include <set>
+
 class ACLUserData : public ACLData<char const *>
 {
     MEMPROXY_CLASS(ACLUserData);
@@ -25,12 +28,16 @@ public:
     bool empty() const;
     virtual ACLData<char const *> *clone() const;
 
-    Splay<char *> *names;
+private:
+
+    typedef std::set<SBuf,bool(*)(const SBuf&, const SBuf&)> UserDataNames_t;
+    UserDataNames_t userDataNames;
 
     struct {
         bool case_insensitive;
         bool required;
     } flags;
+
 };
 
 #endif /* SQUID_ACLUSERDATA_H */