diff options
| author | 2010-03-06 21:54:36 -0600 | |
|---|---|---|
| committer | 2010-08-03 17:32:39 -0400 | |
| commit | 4e3d60e8cee7edfc0f8b0b5b239b22e8ac5d8aa7 (patch) | |
| tree | 332d6b554a2d296a21cf68a188847db3c7177c2d /src/modules/m_chanacl.cpp | |
| parent | Fix 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.cpp | 138 |
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) |
