summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2013-11-01 04:58:38 -0400
committerAdam <Adam@anope.org>2013-11-01 04:58:38 -0400
commit4ee9021adbb10140c30d6027a97e4748cb2f5903 (patch)
treef587e7492f142f8d4e7a908190c83a22087559b0
parentc8db362bca238aaedf9113383a731d18ba88594f (diff)
Compare access entries created with the levels access system by access level and not by privilege set, as two entries can have the same privset but different levels, but still represent two different levels of access. This prevented users from adding other users at a lower access level when that level had the same privset as them. Spotted by TSG.
-rw-r--r--include/access.h4
-rw-r--r--include/anope.h24
-rw-r--r--modules/commands/cs_access.cpp22
-rw-r--r--src/access.cpp11
4 files changed, 47 insertions, 14 deletions
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<typename T> inline T convertTo(const Anope::string &s, bool failIfLefto
*/
#ifdef DEBUG_BUILD
# include <typeinfo>
-#endif
-template<typename T, typename O> inline T anope_dynamic_static_cast(O ptr)
+
+template<typename T, typename O> inline T anope_dynamic_static_cast(O* ptr)
{
-#ifdef DEBUG_BUILD
T ret = dynamic_cast<T>(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;
+}
+
+template<typename T, typename O> inline T anope_dynamic_static_cast(O& ref)
+{
+ try
+ {
+ return dynamic_cast<T>(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<typename T, typename O> inline T anope_dynamic_static_cast(O ptr)
+{
return static_cast<T>(ptr);
-#endif
}
+#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<int>(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<const AccessChanAccess &>(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<const AccessChanAccess &>(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<Privilege> &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