diff --git a/include/access.h b/include/access.h index 19b6b3b02..cb24a6030 100644 --- a/include/access.h +++ b/include/access.h @@ -123,8 +123,8 @@ class CoreExport ChanAccess : public Serializable virtual void AccessUnserialize(const Anope::string &data) = 0; /* Comparison operators to other Access entries */ - bool operator>(const ChanAccess &other) const; - bool operator<(const ChanAccess &other) const; + virtual bool operator>(const ChanAccess &other) const; + virtual bool operator<(const ChanAccess &other) const; bool operator>=(const ChanAccess &other) const; bool operator<=(const ChanAccess &other) const; }; diff --git a/include/anope.h b/include/anope.h index 51ece1cd6..07ed29ebf 100644 --- a/include/anope.h +++ b/include/anope.h @@ -762,17 +762,31 @@ template inline T convertTo(const Anope::string &s, bool failIfLefto */ #ifdef DEBUG_BUILD # include -#endif -template inline T anope_dynamic_static_cast(O ptr) + +template inline T anope_dynamic_static_cast(O* ptr) { -#ifdef DEBUG_BUILD T ret = dynamic_cast(ptr); if (ptr != NULL && ret == NULL) - throw CoreException(Anope::string("anope_dynamic_static_cast<") + typeid(T).name() + ">(" + typeid(O).name() + ") fail"); + throw CoreException(Anope::string("anope_dynamic_static_cast<") + typeid(T).name() + ">(" + typeid(O*).name() + ") fail"); return ret; -#else - return static_cast(ptr); -#endif } +template inline T anope_dynamic_static_cast(O& ref) +{ + try + { + return dynamic_cast(ref); + } + catch (const std::bad_cast &ex) + { + throw CoreException(Anope::string("std::bad_cast from anope_dynamic_static_cast<") + typeid(T).name() + ">(" + typeid(O&).name() + "): " + ex.what()); + } +} +#else +template inline T anope_dynamic_static_cast(O ptr) +{ + return static_cast(ptr); +} +#endif + #endif // ANOPE_H diff --git a/modules/commands/cs_access.cpp b/modules/commands/cs_access.cpp index 0ecf95106..7a2d1a35b 100644 --- a/modules/commands/cs_access.cpp +++ b/modules/commands/cs_access.cpp @@ -43,13 +43,32 @@ class AccessChanAccess : public ChanAccess { this->level = convertTo(data); } + + bool operator>(const ChanAccess &other) const anope_override + { + if (this->provider != other.provider) + return ChanAccess::operator>(other); + else + return this->level > anope_dynamic_static_cast(other).level; + } + + bool operator<(const ChanAccess &other) const anope_override + { + if (this->provider != other.provider) + return ChanAccess::operator<(other); + else + return this->level < anope_dynamic_static_cast(other).level; + } }; class AccessAccessProvider : public AccessProvider { public: + static AccessAccessProvider *me; + AccessAccessProvider(Module *o) : AccessProvider(o, "access/access") { + me = this; } ChanAccess *Create() anope_override @@ -57,6 +76,7 @@ class AccessAccessProvider : public AccessProvider return new AccessChanAccess(this); } }; +AccessAccessProvider* AccessAccessProvider::me; class CommandCSAccess : public Command { @@ -91,7 +111,7 @@ class CommandCSAccess : public Command AccessGroup u_access = source.AccessFor(ci); const ChanAccess *highest = u_access.Highest(); - AccessChanAccess tmp_access(NULL); + AccessChanAccess tmp_access(AccessAccessProvider::me); tmp_access.ci = ci; tmp_access.level = level; diff --git a/src/access.cpp b/src/access.cpp index 2533f4415..f4b97c21e 100644 --- a/src/access.cpp +++ b/src/access.cpp @@ -363,12 +363,11 @@ bool AccessGroup::HasPriv(const Anope::string &name) const const ChanAccess *AccessGroup::Highest() const { - const std::vector &privs = PrivilegeManager::GetPrivileges(); - for (unsigned i = privs.size(); i > 0; --i) - for (unsigned j = this->size(); j > 0; --j) - if (this->at(j - 1)->HasPriv(privs[i - 1].name)) - return this->at(j - 1); - return NULL; + ChanAccess *highest = NULL; + for (unsigned i = 0; i < this->size(); ++i) + if (highest == NULL || *this->at(i) > *highest) + highest = this->at(i); + return highest; } bool AccessGroup::operator>(const AccessGroup &other) const