X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Fm_nickflood.cpp;h=4e6dca5b9ea376f3cdcaa40a0bac1eb2e864715e;hb=6d03943426dcce76ba66567a9b18425a5ebb4c0c;hp=4961e97a0f31e90730bd91c4db535f18008e3f6d;hpb=164998f1e6e2cb885fb4d630ded29ed5191218c8;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/modules/m_nickflood.cpp b/src/modules/m_nickflood.cpp index 4961e97a0..4e6dca5b9 100644 --- a/src/modules/m_nickflood.cpp +++ b/src/modules/m_nickflood.cpp @@ -2,8 +2,8 @@ * | Inspire Internet Relay Chat Daemon | * +------------------------------------+ * - * InspIRCd: (C) 2002-2008 InspIRCd Development Team - * See: http://www.inspircd.org/wiki/index.php/Credits + * InspIRCd: (C) 2002-2009 InspIRCd Development Team + * See: http://wiki.inspircd.org/Credits * * This program is free but copyrighted software; see * the file COPYING for details. @@ -20,16 +20,12 @@ class nickfloodsettings : public classbase { public: - int secs; int nicks; time_t reset; time_t unlocktime; int counter; bool locked; - InspIRCd* ServerInstance; - - nickfloodsettings() : secs(0), nicks(0) {}; nickfloodsettings(int b, int c) : secs(b), nicks(c) { @@ -50,7 +46,11 @@ class nickfloodsettings : public classbase bool shouldlock() { - return (counter >= this->nicks); + /* XXX HACK: using counter + 1 here now to allow the counter to only be incremented + * on successful nick changes; this will be checked before the counter is + * incremented. + */ + return (counter + 1 >= this->nicks); } void clear() @@ -88,27 +88,22 @@ class nickfloodsettings : public classbase class NickFlood : public ModeHandler { public: - NickFlood(InspIRCd* Instance) : ModeHandler(Instance, 'F', 1, 0, false, MODETYPE_CHANNEL, false) { } + SimpleExtItem ext; + NickFlood(Module* Creator) : ModeHandler(Creator, 'F', PARAM_SETONLY, MODETYPE_CHANNEL), + ext("nickflood", Creator) { } ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string ¶meter) { - nickfloodsettings* x; - if (channel->GetExt("nickflood",x)) + nickfloodsettings* x = ext.get(channel); + if (x) return std::make_pair(true, ConvToStr(x->nicks)+":"+ConvToStr(x->secs)); else return std::make_pair(false, parameter); } - bool CheckTimeStamp(time_t theirs, time_t ours, const std::string &their_param, const std::string &our_param, Channel* channel) - { - /* When TS is equal, the alphabetically later one wins */ - return (their_param < our_param); - } - - ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding, bool) + ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { - nickfloodsettings* dummy; - + nickfloodsettings *f = ext.get(channel); if (adding) { char ndata[MAXBUF]; @@ -128,7 +123,6 @@ class NickFlood : public ModeHandler else data++; } if (secs) - { /* Set up the flood parameters for this channel */ int nnicks = atoi(nicks); @@ -141,13 +135,12 @@ class NickFlood : public ModeHandler } else { - if (!channel->GetExt("nickflood", dummy)) + if (!f) { parameter = ConvToStr(nnicks) + ":" +ConvToStr(nsecs); - nickfloodsettings *f = new nickfloodsettings(nsecs,nnicks); - channel->Extend("nickflood", f); - channel->SetMode('F', true); - channel->SetModeParam('F', parameter.c_str(), true); + f = new nickfloodsettings(nsecs, nnicks); + ext.set(channel, f); + channel->SetModeParam('F', parameter); return MODEACTION_ALLOW; } else @@ -164,14 +157,9 @@ class NickFlood : public ModeHandler // new mode param, replace old with new if ((nsecs > 0) && (nnicks > 0)) { - nickfloodsettings* f; - channel->GetExt("nickflood", f); - delete f; f = new nickfloodsettings(nsecs, nnicks); - channel->Shrink("nickflood"); - channel->Extend("nickflood", f); - channel->SetModeParam('F', cur_param.c_str(), false); - channel->SetModeParam('F', parameter.c_str(), true); + ext.set(channel, f); + channel->SetModeParam('F', parameter); return MODEACTION_ALLOW; } else @@ -190,13 +178,10 @@ class NickFlood : public ModeHandler } else { - if (channel->GetExt("nickflood", dummy)) + if (f) { - nickfloodsettings *f; - channel->GetExt("nickflood", f); - delete f; - channel->Shrink("nickflood"); - channel->SetMode('F', false); + ext.unset(channel); + channel->SetModeParam('F', ""); return MODEACTION_ALLOW; } } @@ -206,76 +191,90 @@ class NickFlood : public ModeHandler class ModuleNickFlood : public Module { - NickFlood* jf; + NickFlood nf; public: - ModuleNickFlood(InspIRCd* Me) - : Module(Me) + ModuleNickFlood() + : nf(this) { - - jf = new NickFlood(ServerInstance); - if (!ServerInstance->Modes->AddMode(jf)) + if (!ServerInstance->Modes->AddMode(&nf)) throw ModuleException("Could not add new modes!"); - Implementation eventlist[] = { I_OnChannelDelete, I_OnUserPreNick }; + Extensible::Register(&nf.ext); + Implementation eventlist[] = { I_OnUserPreNick, I_OnUserPostNick }; ServerInstance->Modules->Attach(eventlist, this, 2); } - virtual int OnUserPreNick(User* user, const std::string &newnick) + ModResult OnUserPreNick(User* user, const std::string &newnick) { if (isdigit(newnick[0])) /* allow switches to UID */ - return 0; + return MOD_RES_PASSTHRU; for (UCListIter i = user->chans.begin(); i != user->chans.end(); i++) { - Channel *channel = i->first; + Channel *channel = *i; - nickfloodsettings *f; - if (channel->GetExt("nickflood", f)) + nickfloodsettings *f = nf.ext.get(channel); + if (f) { - if (CHANOPS_EXEMPT(ServerInstance, 'F') && channel->GetStatus(user) == STATUS_OP) + if (CHANOPS_EXEMPT('F') && channel->GetPrefixValue(user) == OP_VALUE) continue; if (f->islocked()) { user->WriteNumeric(447, "%s :%s has been locked for nickchanges for 60 seconds because there have been more than %d nick changes in %d seconds", user->nick.c_str(), channel->name.c_str(), f->nicks, f->secs); - return 1; + return MOD_RES_DENY; } - f->addnick(); if (f->shouldlock()) { f->clear(); f->lock(); channel->WriteChannelWithServ((char*)ServerInstance->Config->ServerName, "NOTICE %s :No nick changes are allowed for 60 seconds because there have been more than %d nick changes in %d seconds.", channel->name.c_str(), f->nicks, f->secs); - return 1; + return MOD_RES_DENY; } } } - return 0; + return MOD_RES_PASSTHRU; } - void OnChannelDelete(Channel* chan) + /* + * XXX: HACK: We do the increment on the *POST* event here (instead of all together) because we have no way of knowing whether other modules would block a nickchange. + */ + void OnUserPostNick(User* user, const std::string &oldnick) { - nickfloodsettings *f; - if (chan->GetExt("nickflood",f)) + if (isdigit(user->nick[0])) /* allow switches to UID */ + return; + + for (UCListIter i = user->chans.begin(); i != user->chans.end(); ++i) { - delete f; - chan->Shrink("nickflood"); + Channel *channel = *i; + + nickfloodsettings *f = nf.ext.get(channel); + if (f) + { + if (CHANOPS_EXEMPT('F') && channel->GetPrefixValue(user) == OP_VALUE) + return; + + /* moved this here to avoid incrementing the counter for nick + * changes that are denied for some other reason (bans, +N, etc.) + * per bug #874. + */ + f->addnick(); + } } + return; } - - virtual ~ModuleNickFlood() + ~ModuleNickFlood() { - ServerInstance->Modes->DelMode(jf); - delete jf; + ServerInstance->Modes->DelMode(&nf); } - virtual Version GetVersion() + Version GetVersion() { - return Version("$Id$", VF_COMMON | VF_VENDOR, API_VERSION); + return Version("Channel mode F - nick flood protection", VF_COMMON | VF_VENDOR); } };