diff options
author | Adam <Adam@anope.org> | 2016-02-13 14:16:29 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2016-02-13 14:16:29 -0500 |
commit | 4e2ca31cf5fc874ab928dc4d3735f4345a910d0d (patch) | |
tree | 1590da2a86eb164389dd781870648d8f3824f9a3 /src | |
parent | addd2a1987dccff6ad4c8a68f5c48c9f850912ec (diff) |
Rewrite access path system to be simplier and use recursion
Show where access is "from" in chanserv/status
Diffstat (limited to 'src')
-rw-r--r-- | src/access.cpp | 93 | ||||
-rw-r--r-- | src/regchannel.cpp | 102 |
2 files changed, 110 insertions, 85 deletions
diff --git a/src/access.cpp b/src/access.cpp index abd55714f..007e6d281 100644 --- a/src/access.cpp +++ b/src/access.cpp @@ -250,8 +250,10 @@ Serializable* ChanAccess::Unserialize(Serializable *obj, Serialize::Data &data) return access; } -bool ChanAccess::Matches(const User *u, const NickCore *acc, Path &p) const +bool ChanAccess::Matches(const User *u, const NickCore *acc, ChannelInfo* &next) const { + next = NULL; + if (this->nc) return this->nc == acc; @@ -276,28 +278,7 @@ bool ChanAccess::Matches(const User *u, const NickCore *acc, Path &p) const if (IRCD->IsChannelValid(this->mask)) { - ChannelInfo *tci = ChannelInfo::Find(this->mask); - if (tci) - { - for (unsigned i = 0; i < tci->GetAccessCount(); ++i) - { - ChanAccess *a = tci->GetAccess(i); - std::pair<const ChanAccess *, const ChanAccess *> pair = std::make_pair(this, a); - - std::pair<Set::iterator, Set::iterator> range = p.first.equal_range(this); - for (; range.first != range.second; ++range.first) - if (range.first->first == pair.first && range.first->second == pair.second) - goto cont; - - p.first.insert(pair); - if (a->Matches(u, acc, p)) - p.second.insert(pair); - - cont:; - } - - return p.second.count(this) > 0; - } + next = ChannelInfo::Find(this->mask); } return false; @@ -347,37 +328,30 @@ bool ChanAccess::operator<=(const ChanAccess &other) const return !(*this > other); } -AccessGroup::AccessGroup() : std::vector<ChanAccess *>() +AccessGroup::AccessGroup() { this->ci = NULL; this->nc = NULL; this->super_admin = this->founder = false; } -static bool HasPriv(const AccessGroup &ag, const ChanAccess *access, const Anope::string &name) +static bool HasPriv(const ChanAccess::Path &path, const Anope::string &name) { - EventReturn MOD_RESULT; - FOREACH_RESULT(OnCheckPriv, MOD_RESULT, (access, name)); - if (MOD_RESULT == EVENT_ALLOW || access->HasPriv(name)) + if (path.empty()) + return false; + + for (unsigned int i = 0; i < path.size(); ++i) { - typedef std::multimap<const ChanAccess *, const ChanAccess *> path; - std::pair<path::const_iterator, path::const_iterator> it = ag.path.second.equal_range(access); - if (it.first != it.second) - /* check all of the paths for this entry */ - for (; it.first != it.second; ++it.first) - { - const ChanAccess *a = it.first->second; - /* if only one path fully matches then we are ok */ - if (HasPriv(ag, a, name)) - return true; - } - else - /* entry is the end of a chain, all entries match, ok */ - return true; + ChanAccess *access = path[i]; + + EventReturn MOD_RESULT; + FOREACH_RESULT(OnCheckPriv, MOD_RESULT, (access, name)); + + if (MOD_RESULT != EVENT_ALLOW && !access->HasPriv(name)) + return false; } - /* entry does not match or none of the chains fully match */ - return false; + return true; } bool AccessGroup::HasPriv(const Anope::string &name) const @@ -393,7 +367,7 @@ bool AccessGroup::HasPriv(const Anope::string &name) const bool auto_mode = !name.find("AUTO"); /* Only grant founder privilege if this isn't an auto mode or if they don't match any entries in this group */ - if ((!auto_mode || this->empty()) && this->founder) + if ((!auto_mode || paths.empty()) && this->founder) return true; EventReturn MOD_RESULT; @@ -401,23 +375,40 @@ bool AccessGroup::HasPriv(const Anope::string &name) const if (MOD_RESULT != EVENT_CONTINUE) return MOD_RESULT == EVENT_ALLOW; - for (unsigned i = this->size(); i > 0; --i) + for (unsigned int i = paths.size(); i > 0; --i) { - ChanAccess *access = this->at(i - 1); + const ChanAccess::Path &path = paths[i - 1]; - if (::HasPriv(*this, access, name)) + if (::HasPriv(path, name)) return true; } return false; } +static ChanAccess *HighestInPath(const ChanAccess::Path &path) +{ + ChanAccess *highest = NULL; + + for (unsigned int i = 0; i < path.size(); ++i) + if (highest == NULL || *path[i] > *highest) + highest = path[i]; + + return highest; +} + const ChanAccess *AccessGroup::Highest() const { ChanAccess *highest = NULL; - for (unsigned i = 0; i < this->size(); ++i) - if (highest == NULL || *this->at(i) > *highest) - highest = this->at(i); + + for (unsigned int i = 0; i < paths.size(); ++i) + { + ChanAccess *hip = HighestInPath(paths[i]); + + if (highest == NULL || *hip > *highest) + highest = hip; + } + return highest; } diff --git a/src/regchannel.cpp b/src/regchannel.cpp index df7359bb9..fe985215d 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -384,6 +384,39 @@ ChanAccess *ChannelInfo::GetAccess(unsigned index) const return acc; } +static void FindMatchesRecurse(ChannelInfo *ci, const User *u, const NickCore *account, unsigned int depth, std::vector<ChanAccess::Path> &paths, ChanAccess::Path &path) +{ + if (depth > ChanAccess::MAX_DEPTH) + return; + + for (unsigned int i = 0; i < ci->GetAccessCount(); ++i) + { + ChanAccess *a = ci->GetAccess(i); + ChannelInfo *next = NULL; + + if (a->Matches(u, u->Account(), next)) + { + ChanAccess::Path next_path = path; + next_path.push_back(a); + + paths.push_back(next_path); + } + else if (next) + { + ChanAccess::Path next_path = path; + next_path.push_back(a); + + FindMatchesRecurse(next, u, account, depth + 1, paths, next_path); + } + } +} + +static void FindMatches(AccessGroup &group, ChannelInfo *ci, const User *u, const NickCore *account) +{ + ChanAccess::Path path; + FindMatchesRecurse(ci, u, account, 0, group.paths, path); +} + AccessGroup ChannelInfo::AccessFor(const User *u, bool updateLastUsed) { AccessGroup group; @@ -404,20 +437,20 @@ AccessGroup ChannelInfo::AccessFor(const User *u, bool updateLastUsed) group.ci = this; group.nc = nc; - for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i) - { - ChanAccess *a = this->GetAccess(i); - if (a->Matches(u, u->Account(), group.path)) - group.push_back(a); - } + FindMatches(group, this, u, u->Account()); - if (group.founder || !group.empty()) + if (group.founder || !group.paths.empty()) { if (updateLastUsed) this->last_used = Anope::CurTime; - for (unsigned i = 0; i < group.size(); ++i) - group[i]->last_seen = Anope::CurTime; + for (unsigned i = 0; i < group.paths.size(); ++i) + { + ChanAccess::Path &p = group.paths[i]; + + for (unsigned int j = 0; j < p.size(); ++j) + p[j]->last_seen = Anope::CurTime; + } } return group; @@ -431,14 +464,9 @@ AccessGroup ChannelInfo::AccessFor(const NickCore *nc, bool updateLastUsed) group.ci = this; group.nc = nc; - for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i) - { - ChanAccess *a = this->GetAccess(i); - if (a->Matches(NULL, nc, group.path)) - group.push_back(a); - } + FindMatches(group, this, NULL, nc); - if (group.founder || !group.empty()) + if (group.founder || !group.paths.empty()) if (updateLastUsed) this->last_used = Anope::CurTime; @@ -452,28 +480,34 @@ unsigned ChannelInfo::GetAccessCount() const return this->access->size(); } -unsigned ChannelInfo::GetDeepAccessCount() const +static unsigned int GetDeepAccessCount(const ChannelInfo *ci, std::set<const ChannelInfo *> &seen, unsigned int depth) { - ChanAccess::Path path; - for (unsigned i = 0, end = this->GetAccessCount(); i < end; ++i) - { - ChanAccess *a = this->GetAccess(i); - a->Matches(NULL, NULL, path); - } + if (depth > ChanAccess::MAX_DEPTH || seen.count(ci)) + return 0; + seen.insert(ci); - unsigned count = this->GetAccessCount(); - std::set<const ChannelInfo *> channels; - channels.insert(this); - for (ChanAccess::Set::iterator it = path.first.begin(); it != path.first.end(); ++it) + unsigned int total = 0; + + for (unsigned int i = 0; i < ci->GetAccessCount(); ++i) { - const ChannelInfo *ci = it->first->ci; - if (!channels.count(ci)) - { - channels.count(ci); - count += ci->GetAccessCount(); - } + ChanAccess::Path path; + ChanAccess *a = ci->GetAccess(i); + ChannelInfo *next = NULL; + + a->Matches(NULL, NULL, next); + ++total; + + if (next) + total += GetDeepAccessCount(ci, seen, depth + 1); } - return count; + + return total; +} + +unsigned ChannelInfo::GetDeepAccessCount() const +{ + std::set<const ChannelInfo *> seen; + return ::GetDeepAccessCount(this, seen, 0); } ChanAccess *ChannelInfo::EraseAccess(unsigned index) |