aboutsummaryrefslogtreecommitdiffstats
path: root/src/modules/m_chanacl.cpp
diff options
context:
space:
mode:
authorGravatar Daniel De Graaf2010-03-06 21:54:36 -0600
committerGravatar Daniel De Graaf2010-08-03 17:32:39 -0400
commit4e3d60e8cee7edfc0f8b0b5b239b22e8ac5d8aa7 (patch)
tree332d6b554a2d296a21cf68a188847db3c7177c2d /src/modules/m_chanacl.cpp
parentFix override permission checking the wrong list (diff)
Add m_chanacl, channel access control groups
Diffstat (limited to 'src/modules/m_chanacl.cpp')
-rw-r--r--src/modules/m_chanacl.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/modules/m_chanacl.cpp b/src/modules/m_chanacl.cpp
new file mode 100644
index 000000000..44877fd8d
--- /dev/null
+++ b/src/modules/m_chanacl.cpp
@@ -0,0 +1,138 @@
+/* +------------------------------------+
+ * | Inspire Internet Relay Chat Daemon |
+ * +------------------------------------+
+ *
+ * InspIRCd: (C) 2002-2010 InspIRCd Development Team
+ * See: http://wiki.inspircd.org/Credits
+ *
+ * This program is free but copyrighted software; see
+ * the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "opflags.h"
+#include "u_listmode.h"
+
+/* $ModDesc: Provides the ability to allow channel operators to be exempt from certain modes. */
+
+/** Handles channel mode +X
+ */
+class ChannelACLMode : public ListModeBase
+{
+ public:
+ ChannelACLMode(Module* Creator) : ListModeBase(Creator, "chanacl", 'W', "End of channel access group list", 954, 953, false, "chanacl") { fixed_letter = false; }
+
+ bool TellListTooLong(User* user, Channel* chan, std::string &word)
+ {
+ user->WriteNumeric(959, "%s %s %s :Channel access group list is full", user->nick.c_str(), chan->name.c_str(), word.c_str());
+ return true;
+ }
+
+ void TellAlreadyOnList(User* user, Channel* chan, std::string &word)
+ {
+ user->WriteNumeric(957, "%s %s :The word %s is already on the access group list",user->nick.c_str(), chan->name.c_str(), word.c_str());
+ }
+
+ void TellNotSet(User* user, Channel* chan, std::string &word)
+ {
+ user->WriteNumeric(958, "%s %s :No such access group is set",user->nick.c_str(), chan->name.c_str());
+ }
+};
+
+class ModuleChanACL : public Module
+{
+ ChannelACLMode ec;
+ dynamic_reference<OpFlagProvider> permcheck;
+
+ public:
+ ModuleChanACL() : ec(this), permcheck("opflags") {}
+
+ void init()
+ {
+ ec.init();
+ ServerInstance->Modules->AddService(ec);
+ Implementation eventlist[] = { I_OnRehash, I_OnPermissionCheck };
+ ServerInstance->Modules->Attach(eventlist, this, 2);
+
+ OnRehash(NULL);
+ }
+
+ void Prioritize()
+ {
+ ServerInstance->Modules->SetPriority(this, I_OnPermissionCheck, PRIORITY_AFTER, ServerInstance->Modules->Find("m_opflags.so"));
+ }
+
+ void OnPermissionCheck(PermissionData& perm)
+ {
+ if (!perm.chan || !perm.source || perm.result != MOD_RES_PASSTHRU)
+ return;
+
+ Membership* memb = perm.chan->GetUser(perm.user);
+ modelist* list = ec.extItem.get(perm.chan);
+ std::set<std::string> given;
+
+ if (list)
+ {
+ for (modelist::iterator i = list->begin(); i != list->end(); ++i)
+ {
+ std::string::size_type pos = (**i).mask.find(':');
+ if (pos == std::string::npos)
+ continue;
+ irc::commasepstream contents((**i).mask.substr(pos + 1));
+ std::string flag;
+ while (contents.GetToken(flag))
+ {
+ if (flag == perm.name)
+ given.insert((**i).mask.substr(0,pos));
+ }
+ }
+ }
+
+ // if the permission was never mentioned, fall back to default
+ if (given.empty())
+ return;
+ // otherwise, it was mentioned at least once: you must have an access on this list
+
+ // problem: the list will have both modes and flags. Pull out the modes first.
+ std::string flaglist;
+ unsigned int minrank = INT_MAX;
+ for(std::set<std::string>::iterator i = given.begin(); i != given.end(); i++)
+ {
+ ModeHandler* privmh = i->length() == 1 ?
+ ServerInstance->Modes->FindMode(i->at(0), MODETYPE_CHANNEL) :
+ ServerInstance->Modes->FindMode(*i);
+ if (privmh && privmh->GetPrefixRank())
+ {
+ if (privmh->GetPrefixRank() < minrank)
+ minrank = privmh->GetPrefixRank();
+ }
+ else
+ {
+ flaglist.push_back(',');
+ flaglist.append(*i);
+ }
+ }
+
+ if (permcheck)
+ perm.result = permcheck->PermissionCheck(memb, flaglist);
+ if (memb->getRank() >= minrank)
+ perm.result = MOD_RES_ALLOW;
+ if (perm.result != MOD_RES_ALLOW)
+ perm.result = MOD_RES_DENY;
+ }
+
+ Version GetVersion()
+ {
+ return Version("Provides the ability to allow channel operators to be exempt from certain modes.",VF_VENDOR);
+ }
+
+ void OnRehash(User* user)
+ {
+ ec.DoRehash();
+ }
+
+};
+
+MODULE_INIT(ModuleChanACL)