1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd: (C) 2002-2007 InspIRCd Development Team
6 * See: http://www.inspircd.org/wiki/index.php/Credits
8 * This program is free but copyrighted software; see
9 * the file COPYING for details.
11 * ---------------------------------------------------
17 #include "configreader.h"
21 /* $ModDesc: Provides support for unreal-style oper-override */
23 typedef std::map<std::string,std::string> override_t;
25 class ModuleOverride : public Module
31 int OverOps, OverDeops, OverVoices, OverDevoices, OverHalfops, OverDehalfops;
35 ModuleOverride(InspIRCd* Me)
38 // read our config options (main config file)
40 ServerInstance->SNO->EnableSnomask('O',"OVERRIDE");
41 OverriddenMode = false;
42 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
45 virtual void OnRehash(userrec* user, const std::string ¶meter)
47 // on a rehash we delete our classes for good measure and create them again.
48 ConfigReader* Conf = new ConfigReader(ServerInstance);
50 // re-read our config options on a rehash
51 NoisyOverride = Conf->ReadFlag("override","noisy",0);
53 for (int j =0; j < Conf->Enumerate("type"); j++)
55 std::string typen = Conf->ReadValue("type","name",j);
56 std::string tokenlist = Conf->ReadValue("type","override",j);
57 overrides[typen] = tokenlist;
63 void Implements(char* List)
65 List[I_OnRehash] = List[I_OnAccessCheck] = List[I_On005Numeric] = List[I_OnUserPreJoin] = List[I_OnUserPreKick] = List[I_OnPostCommand] = 1;
68 virtual void OnPostCommand(const std::string &command, const char** parameters, int pcnt, userrec *user, CmdResult result, const std::string &original_line)
70 if ((NoisyOverride) && (OverriddenMode) && (irc::string(command.c_str()) == "MODE") && (result == CMD_SUCCESS))
72 int Total = OverOps + OverDeops + OverVoices + OverDevoices + OverHalfops + OverDehalfops;
74 ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" Overriding modes: "+ServerInstance->Modes->GetLastParse()+" "+(Total ? "[Detail: " : "")+
75 (OverOps ? ConvToStr(OverOps)+" op"+(OverOps != 1 ? "s" : "")+" " : "")+
76 (OverDeops ? ConvToStr(OverDeops)+" deop"+(OverDeops != 1 ? "s" : "")+" " : "")+
77 (OverVoices ? ConvToStr(OverVoices)+" voice"+(OverVoices != 1 ? "s" : "")+" " : "")+
78 (OverDevoices ? ConvToStr(OverDevoices)+" devoice"+(OverDevoices != 1 ? "s" : "")+" " : "")+
79 (OverHalfops ? ConvToStr(OverHalfops)+" halfop"+(OverHalfops != 1 ? "s" : "")+" " : "")+
80 (OverDehalfops ? ConvToStr(OverDehalfops)+" dehalfop"+(OverDehalfops != 1 ? "s" : "") : "")
83 OverriddenMode = false;
84 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
88 virtual void On005Numeric(std::string &output)
90 output.append(" OVERRIDE");
93 virtual bool CanOverride(userrec* source, char* token)
95 // checks to see if the oper's type has <type:override>
96 override_t::iterator j = overrides.find(source->oper);
98 if (j != overrides.end())
100 // its defined or * is set, return its value as a boolean for if the token is set
101 return ((j->second.find(token, 0) != std::string::npos) || (j->second.find("*", 0) != std::string::npos));
104 // its not defined at all, count as false
108 virtual int OnUserPreKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason)
110 if ((*source->oper) && (CanOverride(source,"KICK")))
112 if (((chan->GetStatus(source) == STATUS_HOP) && (chan->GetStatus(user) == STATUS_OP)) || (chan->GetStatus(source) < STATUS_VOICE))
114 ServerInstance->SNO->WriteToSnoMask('O',std::string(source->nick)+" Override-Kicked "+std::string(user->nick)+" on "+std::string(chan->name)+" ("+reason+")");
116 /* Returning -1 explicitly allows the kick */
122 virtual int OnAccessCheck(userrec* source,userrec* dest,chanrec* channel,int access_type)
126 if (source && channel)
128 // Fix by brain - allow the change if they arent on channel - rely on boolean short-circuit
129 // to not check the other items in the statement if they arent on the channel
130 int mode = channel->GetStatus(source);
134 if (CanOverride(source,"MODEDEOP"))
137 if ((!channel->HasUser(source)) || (mode < STATUS_OP))
147 if (CanOverride(source,"MODEOP"))
150 if ((!channel->HasUser(source)) || (mode < STATUS_OP))
160 if (CanOverride(source,"MODEVOICE"))
163 if ((!channel->HasUser(source)) || (mode < STATUS_HOP))
173 if (CanOverride(source,"MODEDEVOICE"))
176 if ((!channel->HasUser(source)) || (mode < STATUS_HOP))
186 if (CanOverride(source,"MODEHALFOP"))
189 if ((!channel->HasUser(source)) || (mode < STATUS_OP))
199 if (CanOverride(source,"MODEDEHALFOP"))
202 if ((!channel->HasUser(source)) || (mode < STATUS_OP))
213 if (CanOverride(source,"OTHERMODE"))
216 if ((!channel->HasUser(source)) || (mode < STATUS_OP))
218 OverriddenMode = true;
219 OverOps = OverDeops = OverVoices = OverDevoices = OverHalfops = OverDehalfops = 0;
233 virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname, std::string &privs)
239 if ((chan->modes[CM_INVITEONLY]) && (CanOverride(user,"INVITE")))
241 irc::string x = chan->name;
242 if (!user->IsInvited(x))
244 /* XXX - Ugly cast for a parameter that isn't used? :< - Om */
246 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass invite-only", cname, user->nick);
247 ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +i on "+std::string(cname));
252 if ((*chan->key) && (CanOverride(user,"KEY")))
255 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass the channel key", cname, user->nick);
256 ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +k on "+std::string(cname));
260 if ((chan->limit > 0) && (chan->GetUserCounter() >= chan->limit) && (CanOverride(user,"LIMIT")))
263 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass the channel limit", cname, user->nick);
264 ServerInstance->SNO->WriteToSnoMask('O',std::string(user->nick)+" used operoverride to bypass +l on "+std::string(cname));
268 if (CanOverride(user,"BANWALK"))
270 if (chan->IsBanned(user))
273 chan->WriteChannelWithServ(ServerInstance->Config->ServerName, "NOTICE %s :%s used oper-override to bypass channel ban", cname, user->nick);
274 ServerInstance->SNO->WriteToSnoMask('O',"%s used oper-override to bypass channel ban on %s", user->nick, cname);
283 virtual ~ModuleOverride()
285 ServerInstance->SNO->DisableSnomask('O');
288 virtual Version GetVersion()
290 return Version(1,1,0,1,VF_VENDOR,API_VERSION);
295 class ModuleOverrideFactory : public ModuleFactory
298 ModuleOverrideFactory()
302 ~ModuleOverrideFactory()
306 virtual Module * CreateModule(InspIRCd* Me)
308 return new ModuleOverride(Me);
314 extern "C" void * init_module( void )
316 return new ModuleOverrideFactory;