1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
7 * <brain@chatspike.net>
8 * <Craig@chatspike.net>
10 * Written by Craig Edwards, Craig McLure, and others.
11 * This program is free but copyrighted software; see
12 * the file COPYING for details.
14 * ---------------------------------------------------
20 #include "configreader.h"
24 /* $ModDesc: Provides support for unreal-style oper-override */
26 typedef std::map<std::string,std::string> override_t;
28 class ModuleOverride : public Module
34 int OverOps, OverDeops, OverVoices, OverDevoices, OverHalfops, OverDehalfops;
38 ModuleOverride(InspIRCd* Me)
41 // read our config options (main config file)
43 ServerInstance->SNO->EnableSnomask('O',"OVERRIDE");
44 OverriddenMode = false;
45 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
48 virtual void OnRehash(const std::string ¶meter)
50 // on a rehash we delete our classes for good measure and create them again.
51 ConfigReader* Conf = new ConfigReader(ServerInstance);
53 // re-read our config options on a rehash
54 NoisyOverride = Conf->ReadFlag("override","noisy",0);
56 for (int j =0; j < Conf->Enumerate("type"); j++)
58 std::string typen = Conf->ReadValue("type","name",j);
59 std::string tokenlist = Conf->ReadValue("type","override",j);
60 overrides[typen] = tokenlist;
66 void Implements(char* List)
68 List[I_OnRehash] = List[I_OnAccessCheck] = List[I_On005Numeric] = List[I_OnUserPreJoin] = List[I_OnUserPreKick] = List[I_OnPostCommand] = 1;
71 virtual void OnPostCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, CmdResult result, const std::string &original_line)
73 if ((NoisyOverride) && (OverriddenMode) && (irc::string(command.c_str()) == "MODE") && (result == CMD_SUCCESS))
75 int Total = OverOps + OverDeops + OverVoices + OverDevoices + OverHalfops + OverDehalfops;
77 ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" Overriding modes: "+ServerInstance->Modes->GetLastParse()+" "+(Total ? "[Detail: " : "")+
78 (OverOps ? ConvToStr(OverOps)+" op"+(OverOps != 1 ? "s" : "")+" " : "")+
79 (OverDeops ? ConvToStr(OverDeops)+" deop"+(OverDeops != 1 ? "s" : "")+" " : "")+
80 (OverVoices ? ConvToStr(OverVoices)+" voice"+(OverVoices != 1 ? "s" : "")+" " : "")+
81 (OverDevoices ? ConvToStr(OverDevoices)+" devoice"+(OverDevoices != 1 ? "s" : "")+" " : "")+
82 (OverHalfops ? ConvToStr(OverHalfops)+" halfop"+(OverHalfops != 1 ? "s" : "")+" " : "")+
83 (OverDehalfops ? ConvToStr(OverDehalfops)+" dehalfop"+(OverDehalfops != 1 ? "s" : "") : "")
86 OverriddenMode = false;
87 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
91 virtual void On005Numeric(std::string &output)
93 output.append(" OVERRIDE");
96 virtual bool CanOverride(userrec* source, char* token)
98 // checks to see if the oper's type has <type:override>
99 override_t::iterator j = overrides.find(source->oper);
101 if (j != overrides.end())
103 // its defined, return its value as a boolean for if the token is set
104 return (j->second.find(token, 0) != std::string::npos);
107 // its not defined at all, count as false
111 virtual int OnUserPreKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason)
113 if ((*source->oper) && (CanOverride(source,"KICK")))
115 if (((chan->GetStatus(source) == STATUS_HOP) && (chan->GetStatus(user) == STATUS_OP)) || (chan->GetStatus(source) < STATUS_VOICE))
117 ServerInstance->SNO->WriteToSnoMask('O',std::string(source->nick)+" Override-Kicked "+std::string(user->nick)+" on "+std::string(chan->name)+" ("+reason+")");
119 /* Returning -1 explicitly allows the kick */
125 virtual int OnAccessCheck(userrec* source,userrec* dest,chanrec* channel,int access_type)
129 if (source && channel)
131 // Fix by brain - allow the change if they arent on channel - rely on boolean short-circuit
132 // to not check the other items in the statement if they arent on the channel
133 int mode = channel->GetStatus(source);
137 ServerInstance->Log(DEBUG,"Override access check AC_DEOP");
138 if (CanOverride(source,"MODEDEOP"))
141 if ((!channel->HasUser(source)) || (mode < STATUS_OP))
151 ServerInstance->Log(DEBUG,"Override access check AC_OP");
152 if (CanOverride(source,"MODEOP"))
155 if ((!channel->HasUser(source)) || (mode < STATUS_OP))
165 ServerInstance->Log(DEBUG,"Override access check AC_VOICE");
166 if (CanOverride(source,"MODEVOICE"))
169 if ((!channel->HasUser(source)) || (mode < STATUS_HOP))
179 ServerInstance->Log(DEBUG,"Override access check AC_DEVOICE");
180 if (CanOverride(source,"MODEDEVOICE"))
183 if ((!channel->HasUser(source)) || (mode < STATUS_HOP))
193 ServerInstance->Log(DEBUG,"Override access check AC_HALFOP");
194 if (CanOverride(source,"MODEHALFOP"))
197 if ((!channel->HasUser(source)) || (mode < STATUS_OP))
207 ServerInstance->Log(DEBUG,"Override access check AC_DEHALFOP");
208 if (CanOverride(source,"MODEDEHALFOP"))
211 if ((!channel->HasUser(source)) || (mode < STATUS_OP))
222 if (CanOverride(source,"OTHERMODE"))
225 if ((!channel->HasUser(source)) || (mode < STATUS_OP))
227 ServerInstance->Log(DEBUG,"Overridden mode");
228 OverriddenMode = true;
229 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
243 virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname, std::string &privs)
249 if ((chan->modes[CM_INVITEONLY]) && (CanOverride(user,"INVITE")))
253 irc::string x = chan->name;
254 if (!user->IsInvited(x))
256 /* XXX - Ugly cast for a parameter that isn't used? :< - Om */
257 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass invite-only", cname, user->nick);
260 ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +i on "+std::string(cname));
264 if ((chan->key[0]) && (CanOverride(user,"KEY")))
267 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass the channel key", cname, user->nick);
268 ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +k on "+std::string(cname));
272 if ((chan->limit > 0) && (chan->GetUserCounter() >= chan->limit) && (CanOverride(user,"LIMIT")))
275 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass the channel limit", cname, user->nick);
276 ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +l on "+std::string(cname));
280 if (CanOverride(user,"BANWALK"))
282 if (chan->IsBanned(user))
286 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass channel ban", cname, user->nick);
287 ServerInstance->SNO->WriteToSnoMask('O',"%s used oper-override to bypass channel ban", cname, user->nick);
297 virtual ~ModuleOverride()
299 ServerInstance->SNO->DisableSnomask('O');
302 virtual Version GetVersion()
304 return Version(1,0,0,1,VF_VENDOR);
309 class ModuleOverrideFactory : public ModuleFactory
312 ModuleOverrideFactory()
316 ~ModuleOverrideFactory()
320 virtual Module * CreateModule(InspIRCd* Me)
322 return new ModuleOverride(Me);
328 extern "C" void * init_module( void )
330 return new ModuleOverrideFactory;