diff options
-rw-r--r-- | docs/inspircd.conf.example | 3 | ||||
-rw-r--r-- | docs/modules.conf.example | 9 | ||||
-rw-r--r-- | include/inspircd.h | 10 | ||||
-rw-r--r-- | include/modules.h | 8 | ||||
-rw-r--r-- | src/channels.cpp | 3 | ||||
-rw-r--r-- | src/helperfuncs.cpp | 25 | ||||
-rw-r--r-- | src/inspircd.cpp | 3 | ||||
-rw-r--r-- | src/modules.cpp | 1 | ||||
-rw-r--r-- | src/modules/m_blockcaps.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_blockcolor.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_censor.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_chanfilter.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_exemptchanops.cpp | 95 | ||||
-rw-r--r-- | src/modules/m_messageflood.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_nickflood.cpp | 4 | ||||
-rw-r--r-- | src/modules/m_noctcp.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_nonicks.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_nonotice.cpp | 2 | ||||
-rw-r--r-- | src/modules/m_services_account.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_stripcolor.cpp | 3 | ||||
-rw-r--r-- | src/modules/m_testnet.cpp | 1 |
21 files changed, 102 insertions, 89 deletions
diff --git a/docs/inspircd.conf.example b/docs/inspircd.conf.example index b3928712c..a292905c8 100644 --- a/docs/inspircd.conf.example +++ b/docs/inspircd.conf.example @@ -580,6 +580,9 @@ # moronbanner: This is the text that is sent to a user when they are # banned from the server. moronbanner="You're banned! Email haha@abuse.com with the ERROR line below for help." + + # exemptchanops: exemptions for channel access restrictions based on prefix. + exemptchanops="nonick:v flood:o" # invitebypassmodes: This allows /invite to bypass other channel modes. # (Such as +k, +j, +l, etc) diff --git a/docs/modules.conf.example b/docs/modules.conf.example index db4b1db52..02d80431d 100644 --- a/docs/modules.conf.example +++ b/docs/modules.conf.example @@ -735,15 +735,6 @@ # modes are blockcaps, noctcp, blockcolor, nickflood, flood, censor, # # filter, regmoderated, nonick, nonotice, and stripcolor. # #<module name="m_exemptchanops.so"> # -# # -#-#-#-#-#-#-#-#-#-#- EXEMPTCHANOPS CONFIGURATION -#-#-#-#-#-#-#-#-#-# -# defaults - default exemptions. These can be added to or overridden # -# by the channel mode +X. Each item is of the form # -# [mode]:[minstatus] where you must have [minstatus] in # -# order to be able to bypass [mode]. # -# Use "blockcolor:*" to override a default exemption # -#<exemptchanops defaults="nonick:v flood:o"> - #-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-# # Filter module: Provides message filtering, similar to SPAMFILTER. diff --git a/include/inspircd.h b/include/inspircd.h index a9a1af482..d973fb66c 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -77,7 +77,6 @@ CoreExport extern InspIRCd* ServerInstance; #include "socketengine.h" #include "snomasks.h" #include "filelogger.h" -#include "caller.h" #include "modules.h" #include "threadengine.h" #include "configreader.h" @@ -240,6 +239,7 @@ DEFINE_HANDLER1(FloodQuitUserHandler, void, User*); DEFINE_HANDLER2(IsChannelHandler, bool, const char*, size_t); DEFINE_HANDLER1(IsSIDHandler, bool, const std::string&); DEFINE_HANDLER1(RehashHandler, void, const std::string&); +DEFINE_HANDLER3(OnCheckExemptionHandler, ModResult, User*, Channel*, const std::string&); /** The main class of the irc server. * This class contains instances of all the other classes in this software. @@ -308,6 +308,7 @@ class CoreExport InspIRCd IsNickHandler HandleIsNick; IsIdentHandler HandleIsIdent; FloodQuitUserHandler HandleFloodQuitUser; + OnCheckExemptionHandler HandleOnCheckExemption; IsChannelHandler HandleIsChannel; IsSIDHandler HandleIsSID; RehashHandler HandleRehash; @@ -782,6 +783,13 @@ class CoreExport InspIRCd */ caller1<void, User*> FloodQuitUser; + /** Called to check whether a channel restriction mode applies to a user + * @param User that is attempting some action + * @param Channel that the action is being performed on + * @param Action name + */ + caller3<ModResult, User*, Channel*, const std::string&> OnCheckExemption; + /** Restart the server. * This function will not return. If an error occurs, * it will throw an instance of CoreException. diff --git a/include/modules.h b/include/modules.h index 4f60d55e4..71cbc8480 100644 --- a/include/modules.h +++ b/include/modules.h @@ -327,7 +327,7 @@ enum Implementation I_OnPostOper, I_OnSyncNetwork, I_OnSetAway, I_OnPostCommand, I_OnPostJoin, I_OnWhoisLine, I_OnBuildNeighborList, I_OnGarbageCollect, I_OnSetConnectClass, I_OnText, I_OnPassCompare, I_OnRunTestSuite, I_OnNamesListItem, I_OnNumeric, I_OnHookIO, - I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, I_OnChannelRestrictionApply, + I_OnPreRehash, I_OnModuleRehash, I_OnSendWhoLine, I_OnChangeIdent, I_END }; @@ -1278,12 +1278,6 @@ class CoreExport Module : public classbase, public usecountbase * @param line The raw line to send; modifiable, if empty no line will be returned. */ virtual void OnSendWhoLine(User* source, const std::vector<std::string>& params, User* user, Channel* channel, std::string& line); - - /** Called to check whether a channel restriction mode applies to a user on it - * @return MOD_RES_DENY to apply the restriction, MOD_RES_ALLOW to bypass - * the restriction, or MOD_RES_PASSTHRU to check restriction status normally - */ - virtual ModResult OnChannelRestrictionApply(User* user, Channel* chan, const char* restriction); }; diff --git a/src/channels.cpp b/src/channels.cpp index d0533aee6..5603ef1dd 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -92,9 +92,8 @@ int Channel::SetTopic(User *u, std::string &ntopic, bool forceset) return CMD_FAILURE; if (res != MOD_RES_ALLOW) { - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (u,this,"topiclock")); bool defok = IsModeSet('t') ? GetPrefixValue(u) >= HALFOP_VALUE : HasUser(u); - if (!res.check(defok)) + if (!ServerInstance->OnCheckExemption(u,this,"topiclock").check(defok)) { if (!this->HasUser(u)) u->WriteNumeric(442, "%s %s :You're not on that channel!",u->nick.c_str(), this->name.c_str()); diff --git a/src/helperfuncs.cpp b/src/helperfuncs.cpp index 66a84bbce..98dd1fc7f 100644 --- a/src/helperfuncs.cpp +++ b/src/helperfuncs.cpp @@ -439,3 +439,28 @@ void GenRandomHandler::Call(char *output, size_t max) for(unsigned int i=0; i < max; i++) output[i] = random(); } + +ModResult OnCheckExemptionHandler::Call(User* user, Channel* chan, const std::string& restriction) +{ + unsigned int mypfx = chan->GetPrefixValue(user); + char minmode; + std::string current; + + irc::spacesepstream defaultstream(ServerInstance->Config->ConfValue("options")->getString("exemptchanops")); + + while (defaultstream.GetToken(current)) + { + std::string::size_type pos = current.find(':'); + if (pos == std::string::npos) + continue; + if (current.substr(0,pos) == restriction) + minmode = current[pos+1]; + } + + ModeHandler* mh = ServerInstance->Modes->FindMode(minmode, MODETYPE_CHANNEL); + if (mh && mypfx >= mh->GetPrefixRank()) + return MOD_RES_ALLOW; + if (mh || minmode == '*') + return MOD_RES_DENY; + return MOD_RES_PASSTHRU; +} diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 27060be52..c6faf8802 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -305,7 +305,8 @@ InspIRCd::InspIRCd(int argc, char** argv) : Rehash(&HandleRehash), IsNick(&HandleIsNick), IsIdent(&HandleIsIdent), - FloodQuitUser(&HandleFloodQuitUser) + FloodQuitUser(&HandleFloodQuitUser), + OnCheckExemption(&HandleOnCheckExemption) { #ifdef WIN32 // Strict, frequent checking of memory on debug builds diff --git a/src/modules.cpp b/src/modules.cpp index 98788c616..83393c2ad 100644 --- a/src/modules.cpp +++ b/src/modules.cpp @@ -163,7 +163,6 @@ ModResult Module::OnNumeric(User*, unsigned int, const std::string&) { return MO void Module::OnHookIO(StreamSocket*, ListenSocket*) { } ModResult Module::OnAcceptConnection(int, ListenSocket*, irc::sockets::sockaddrs*, irc::sockets::sockaddrs*) { return MOD_RES_PASSTHRU; } void Module::OnSendWhoLine(User*, const std::vector<std::string>&, User*, Channel*, std::string&) { } -ModResult Module::OnChannelRestrictionApply(User*, Channel*, const char*) { return MOD_RES_PASSTHRU; } ModuleManager::ModuleManager() : ModCount(0) { diff --git a/src/modules/m_blockcaps.cpp b/src/modules/m_blockcaps.cpp index ade42cb4b..873cf46ca 100644 --- a/src/modules/m_blockcaps.cpp +++ b/src/modules/m_blockcaps.cpp @@ -59,8 +59,7 @@ public: return MOD_RES_PASSTHRU; Channel* c = (Channel*)dest; - ModResult res; - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,c,"blockcaps")); + ModResult res = ServerInstance->OnCheckExemption(user,c,"blockcaps"); if (res == MOD_RES_ALLOW) return MOD_RES_PASSTHRU; diff --git a/src/modules/m_blockcolor.cpp b/src/modules/m_blockcolor.cpp index 9ffb36b80..d19317074 100644 --- a/src/modules/m_blockcolor.cpp +++ b/src/modules/m_blockcolor.cpp @@ -47,8 +47,7 @@ class ModuleBlockColour : public Module if ((target_type == TYPE_CHANNEL) && (IS_LOCAL(user))) { Channel* c = (Channel*)dest; - ModResult res; - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,c,"blockcolor")); + ModResult res = ServerInstance->OnCheckExemption(user,c,"blockcolor"); if (res == MOD_RES_ALLOW) return MOD_RES_PASSTHRU; diff --git a/src/modules/m_censor.cpp b/src/modules/m_censor.cpp index 6a9f6941f..bf1f0225d 100644 --- a/src/modules/m_censor.cpp +++ b/src/modules/m_censor.cpp @@ -76,8 +76,7 @@ class ModuleCensor : public Module { active = ((Channel*)dest)->IsModeSet('G'); Channel* c = (Channel*)dest; - ModResult res; - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,c,"censor")); + ModResult res = ServerInstance->OnCheckExemption(user,c,"censor"); if (res == MOD_RES_ALLOW) return MOD_RES_PASSTHRU; diff --git a/src/modules/m_chanfilter.cpp b/src/modules/m_chanfilter.cpp index e790a15d8..faa064dbf 100644 --- a/src/modules/m_chanfilter.cpp +++ b/src/modules/m_chanfilter.cpp @@ -83,8 +83,7 @@ class ModuleChanFilter : public Module virtual ModResult ProcessMessages(User* user,Channel* chan,std::string &text) { - ModResult res; - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,chan,"filter")); + ModResult res = ServerInstance->OnCheckExemption(user,chan,"filter"); if (!IS_LOCAL(user) || res == MOD_RES_ALLOW) return MOD_RES_PASSTHRU; diff --git a/src/modules/m_exemptchanops.cpp b/src/modules/m_exemptchanops.cpp index 2677e66df..e92350eeb 100644 --- a/src/modules/m_exemptchanops.cpp +++ b/src/modules/m_exemptchanops.cpp @@ -52,42 +52,12 @@ class ExemptChanOps : public ListModeBase } }; -class ModuleExemptChanOps : public Module +class ExemptHandler : public HandlerBase3<ModResult, User*, Channel*, const std::string&> { - ExemptChanOps ec; - std::string defaults; - public: - - ModuleExemptChanOps() : ec(this) - { - } - - void init() - { - ServerInstance->Modules->AddService(ec); - Implementation eventlist[] = { I_OnChannelDelete, I_OnChannelRestrictionApply, I_OnRehash, I_OnSyncChannel }; - ServerInstance->Modules->Attach(eventlist, this, 4); - - OnRehash(NULL); - } - - Version GetVersion() - { - return Version("Provides the ability to allow channel operators to be exempt from certain modes.",VF_VENDOR); - } - - void OnRehash(User* user) - { - defaults = ServerInstance->Config->ConfValue("exemptchanops")->getString("defaults"); - ec.DoRehash(); - } - - void OnSyncChannel(Channel* chan, Module* proto, void* opaque) - { - ec.DoSyncChannel(chan, proto, opaque); - } - + ExemptChanOps ec; + ExemptHandler(Module* me) : ec(me) {} + ModeHandler* FindMode(const std::string& mid) { if (mid.length() == 1) @@ -101,21 +71,11 @@ class ModuleExemptChanOps : public Module return NULL; } - ModResult OnChannelRestrictionApply(User* user, Channel* chan, const char* restriction) + ModResult Call(User* user, Channel* chan, const std::string& restriction) { unsigned int mypfx = chan->GetPrefixValue(user); - irc::spacesepstream defaultstream(defaults); std::string minmode; - std::string current; - while (defaultstream.GetToken(current)) - { - std::string::size_type pos = current.find(':'); - if (pos == std::string::npos) - continue; - if (current.substr(0,pos) == restriction) - minmode = current[pos+1]; - } modelist* list = ec.extItem.get(chan); if (list) @@ -135,7 +95,50 @@ class ModuleExemptChanOps : public Module return MOD_RES_ALLOW; if (mh || minmode == "*") return MOD_RES_DENY; - return MOD_RES_PASSTHRU; + + return ServerInstance->HandleOnCheckExemption.Call(user, chan, restriction); + } +}; + +class ModuleExemptChanOps : public Module +{ + std::string defaults; + ExemptHandler eh; + + public: + + ModuleExemptChanOps() : eh(this) + { + } + + void init() + { + ServerInstance->Modules->AddService(eh.ec); + Implementation eventlist[] = { I_OnRehash, I_OnSyncChannel }; + ServerInstance->Modules->Attach(eventlist, this, 2); + ServerInstance->OnCheckExemption = &eh; + + OnRehash(NULL); + } + + ~ModuleExemptChanOps() + { + ServerInstance->OnCheckExemption = &ServerInstance->HandleOnCheckExemption; + } + + Version GetVersion() + { + return Version("Provides the ability to allow channel operators to be exempt from certain modes.",VF_VENDOR); + } + + void OnRehash(User* user) + { + eh.ec.DoRehash(); + } + + void OnSyncChannel(Channel* chan, Module* proto, void* opaque) + { + eh.ec.DoSyncChannel(chan, proto, opaque); } }; diff --git a/src/modules/m_messageflood.cpp b/src/modules/m_messageflood.cpp index c37537249..ccaf0a402 100644 --- a/src/modules/m_messageflood.cpp +++ b/src/modules/m_messageflood.cpp @@ -196,8 +196,7 @@ class ModuleMsgFlood : public Module ModResult ProcessMessages(User* user,Channel* dest, const std::string &text) { - ModResult res; - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,dest,"flood")); + ModResult res = ServerInstance->OnCheckExemption(user,dest,"flood"); if (!IS_LOCAL(user) || res == MOD_RES_ALLOW) return MOD_RES_PASSTHRU; diff --git a/src/modules/m_nickflood.cpp b/src/modules/m_nickflood.cpp index 47c8bc836..708d30e6b 100644 --- a/src/modules/m_nickflood.cpp +++ b/src/modules/m_nickflood.cpp @@ -209,7 +209,7 @@ class ModuleNickFlood : public Module nickfloodsettings *f = nf.ext.get(channel); if (f) { - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,channel,"nickflood")); + res = ServerInstance->OnCheckExemption(user,channel,"nickflood"); if (res == MOD_RES_ALLOW) continue; @@ -248,7 +248,7 @@ class ModuleNickFlood : public Module nickfloodsettings *f = nf.ext.get(channel); if (f) { - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,channel,"nickflood")); + res = ServerInstance->OnCheckExemption(user,channel,"nickflood"); if (res == MOD_RES_ALLOW) return; diff --git a/src/modules/m_noctcp.cpp b/src/modules/m_noctcp.cpp index 19f97b42c..680392ea9 100644 --- a/src/modules/m_noctcp.cpp +++ b/src/modules/m_noctcp.cpp @@ -78,8 +78,7 @@ class ModuleNoCTCP : public Module if ((target_type == TYPE_CHANNEL) && (IS_LOCAL(user))) { Channel* c = (Channel*)dest; - ModResult res; - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,c,"noctcp")); + ModResult res = ServerInstance->OnCheckExemption(user,c,"noctcp"); if (res == MOD_RES_ALLOW) return MOD_RES_PASSTHRU; diff --git a/src/modules/m_nonicks.cpp b/src/modules/m_nonicks.cpp index 8713ffe96..7a6d3ffd0 100644 --- a/src/modules/m_nonicks.cpp +++ b/src/modules/m_nonicks.cpp @@ -84,8 +84,7 @@ class ModuleNoNickChange : public Module { Channel* curr = *i; - ModResult res; - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,curr,"nonick")); + ModResult res = ServerInstance->OnCheckExemption(user,curr,"nonick"); if (res == MOD_RES_ALLOW) continue; diff --git a/src/modules/m_nonotice.cpp b/src/modules/m_nonotice.cpp index fe1e0a46d..b3f3d8da6 100644 --- a/src/modules/m_nonotice.cpp +++ b/src/modules/m_nonotice.cpp @@ -53,7 +53,7 @@ class ModuleNoNotice : public Module // ulines are exempt. return MOD_RES_PASSTHRU; } - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,c,"nonotice")); + res = ServerInstance->OnCheckExemption(user,c,"nonotice"); if (res == MOD_RES_ALLOW) return MOD_RES_PASSTHRU; else diff --git a/src/modules/m_services_account.cpp b/src/modules/m_services_account.cpp index 4b047ea07..61026c08f 100644 --- a/src/modules/m_services_account.cpp +++ b/src/modules/m_services_account.cpp @@ -175,8 +175,7 @@ class ModuleServicesAccount : public Module if (target_type == TYPE_CHANNEL) { Channel* c = (Channel*)dest; - ModResult res; - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,c,"regmoderated")); + ModResult res = ServerInstance->OnCheckExemption(user,c,"regmoderated"); if (c->IsModeSet('M') && !is_registered && res != MOD_RES_ALLOW) { diff --git a/src/modules/m_stripcolor.cpp b/src/modules/m_stripcolor.cpp index 113c931cb..c2246a0d9 100644 --- a/src/modules/m_stripcolor.cpp +++ b/src/modules/m_stripcolor.cpp @@ -114,8 +114,7 @@ class ModuleStripColor : public Module else if (target_type == TYPE_CHANNEL) { Channel* t = (Channel*)dest; - ModResult res; - FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,t,"stripcolor")); + ModResult res = ServerInstance->OnCheckExemption(user,t,"stripcolor"); if (res == MOD_RES_ALLOW) return MOD_RES_PASSTHRU; diff --git a/src/modules/m_testnet.cpp b/src/modules/m_testnet.cpp index faa0c7b2e..2f514cf0b 100644 --- a/src/modules/m_testnet.cpp +++ b/src/modules/m_testnet.cpp @@ -169,7 +169,6 @@ static void checkall(Module* noimpl) CHK(OnModuleRehash); CHK(OnSendWhoLine); CHK(OnChangeIdent); - CHK(OnChannelRestrictionApply); } class CommandTest : public Command |