diff --git a/src/mode.cpp b/src/mode.cpp index 5bad36de2..e64e4eb49 100644 --- a/src/mode.cpp +++ b/src/mode.cpp @@ -78,6 +78,8 @@ void ModeHandler::AdjustModeChar(char proposed_letter) { if (fixed_letter) return; + if (!proposed_letter && GetPrefixRank()) + return; mode = proposed_letter; } diff --git a/src/modules/m_censor.cpp b/src/modules/m_censor.cpp index 6a9f6941f..6f477376b 100644 --- a/src/modules/m_censor.cpp +++ b/src/modules/m_censor.cpp @@ -34,7 +34,7 @@ class CensorUser : public SimpleUserModeHandler class CensorChannel : public SimpleChannelModeHandler { public: - CensorChannel(Module* Creator) : SimpleChannelModeHandler(Creator, "censor", 'G') { } + CensorChannel(Module* Creator) : SimpleChannelModeHandler(Creator, "censor", 'G') { fixed_letter = false; } }; class ModuleCensor : public Module @@ -74,7 +74,7 @@ class ModuleCensor : public Module active = ((User*)dest)->IsModeSet('G'); else if (target_type == TYPE_CHANNEL) { - active = ((Channel*)dest)->IsModeSet('G'); + active = ((Channel*)dest)->IsModeSet(&cc); Channel* c = (Channel*)dest; ModResult res; FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,c,"censor")); diff --git a/src/modules/m_chanprotect.cpp b/src/modules/m_chanprotect.cpp index 303f13f44..3e646fcb6 100644 --- a/src/modules/m_chanprotect.cpp +++ b/src/modules/m_chanprotect.cpp @@ -29,53 +29,18 @@ struct ChanProtectSettings static ChanProtectSettings settings; -/** Handles basic operation of +qa channel modes - */ -class FounderProtectBase -{ - private: - const std::string type; - const char mode; - const int list; - const int end; - public: - FounderProtectBase(char Mode, const std::string &mtype, int l, int e) : - type(mtype), mode(Mode), list(l), end(e) - { - } - - void DisplayList(User* user, Channel* channel) - { - const UserMembList* cl = channel->GetUsers(); - for (UserMembCIter i = cl->begin(); i != cl->end(); ++i) - { - if (i->second->hasMode(mode)) - { - user->WriteServ("%d %s %s %s", list, user->nick.c_str(), channel->name.c_str(), i->first->nick.c_str()); - } - } - user->WriteServ("%d %s %s :End of channel %s list", end, user->nick.c_str(), channel->name.c_str(), type.c_str()); - } - - bool CanRemoveOthers(User* u1, Channel* c) - { - Membership* m1 = c->GetUser(u1); - return (settings.DeprivOthers && m1 && m1->hasMode(mode)); - } -}; - /** Abstraction of FounderProtectBase for channel mode +q */ -class ChanFounder : public ModeHandler, public FounderProtectBase +class ChanFounder : public ModeHandler { public: ChanFounder(Module* Creator) - : ModeHandler(Creator, "founder", 'q', PARAM_ALWAYS, MODETYPE_CHANNEL), - FounderProtectBase('q', "founder", 386, 387) + : ModeHandler(Creator, "founder", 'q', PARAM_ALWAYS, MODETYPE_CHANNEL) { ModeHandler::list = true; levelrequired = FOUNDER_VALUE; m_paramtype = TR_NICK; + fixed_letter = false; } void setPrefix(int pfx) @@ -95,7 +60,7 @@ class ChanFounder : public ModeHandler, public FounderProtectBase if (source == theuser && !adding && settings.DeprivSelf) return MOD_RES_ALLOW; - if (!adding && FounderProtectBase::CanRemoveOthers(source, channel)) + if (!adding && CanRemoveOthers(source, channel)) { return MOD_RES_PASSTHRU; } @@ -113,22 +78,36 @@ class ChanFounder : public ModeHandler, public FounderProtectBase void DisplayList(User* user, Channel* channel) { - FounderProtectBase::DisplayList(user,channel); + const UserMembList* cl = channel->GetUsers(); + for (UserMembCIter i = cl->begin(); i != cl->end(); ++i) + { + if (i->second->hasMode(mode)) + { + user->WriteServ("386 %s %s %s", user->nick.c_str(), channel->name.c_str(), i->first->nick.c_str()); + } + } + user->WriteServ("387 %s %s :End of channel founder list", user->nick.c_str(), channel->name.c_str()); + } + + bool CanRemoveOthers(User* u1, Channel* c) + { + Membership* m1 = c->GetUser(u1); + return (settings.DeprivOthers && m1 && m1->hasMode(mode)); } }; /** Abstraction of FounderProtectBase for channel mode +a */ -class ChanProtect : public ModeHandler, public FounderProtectBase +class ChanProtect : public ModeHandler { public: ChanProtect(Module* Creator) - : ModeHandler(Creator, "protected", 'a', PARAM_ALWAYS, MODETYPE_CHANNEL), - FounderProtectBase('a',"protected user", 388, 389) + : ModeHandler(Creator, "protected", 'a', PARAM_ALWAYS, MODETYPE_CHANNEL) { ModeHandler::list = true; levelrequired = PROTECT_VALUE; m_paramtype = TR_NICK; + fixed_letter = false; } void setPrefix(int pfx) @@ -152,7 +131,7 @@ class ChanProtect : public ModeHandler, public FounderProtectBase if (source == theuser && !adding && settings.DeprivSelf) return MOD_RES_ALLOW; - if (!adding && FounderProtectBase::CanRemoveOthers(source, channel)) + if (!adding && CanRemoveOthers(source, channel)) { return MOD_RES_PASSTHRU; } @@ -170,9 +149,22 @@ class ChanProtect : public ModeHandler, public FounderProtectBase void DisplayList(User* user, Channel* channel) { - FounderProtectBase::DisplayList(user, channel); + const UserMembList* cl = channel->GetUsers(); + for (UserMembCIter i = cl->begin(); i != cl->end(); ++i) + { + if (i->second->hasMode(mode)) + { + user->WriteServ("388 %s %s %s", user->nick.c_str(), channel->name.c_str(), i->first->nick.c_str()); + } + } + user->WriteServ("389 %s %s :End of channel protected user list", user->nick.c_str(), channel->name.c_str()); } + bool CanRemoveOthers(User* u1, Channel* c) + { + Membership* m1 = c->GetUser(u1); + return (settings.DeprivOthers && m1 && m1->hasMode(mode)); + } }; class ModuleChanProtect : public Module @@ -186,6 +178,7 @@ class ModuleChanProtect : public Module void init() { + settings.booting = true; /* Load config stuff */ LoadSettings(); settings.booting = false; @@ -233,7 +226,7 @@ class ModuleChanProtect : public Module // the config option for it is set if (settings.FirstInGetsFounder && !chan) - privs += 'q'; + privs += cf.GetModeChar(); return MOD_RES_PASSTHRU; } diff --git a/src/modules/m_knock.cpp b/src/modules/m_knock.cpp index e85b3e049..63f9e701f 100644 --- a/src/modules/m_knock.cpp +++ b/src/modules/m_knock.cpp @@ -44,9 +44,10 @@ class CommandKnock : public Command return CMD_FAILURE; } - if (c->IsModeSet('K')) + ModeHandler* mh = ServerInstance->Modes->FindMode("noknock"); + if (c->IsModeSet(mh)) { - user->WriteNumeric(480, "%s :Can't KNOCK on %s, +K is set.",user->nick.c_str(), c->name.c_str()); + user->WriteNumeric(480, "%s :Can't KNOCK on %s, noknock mode is set.",user->nick.c_str(), c->name.c_str()); return CMD_FAILURE; } @@ -78,7 +79,7 @@ class CommandKnock : public Command class Knock : public SimpleChannelModeHandler { public: - Knock(Module* Creator) : SimpleChannelModeHandler(Creator, "noknock", 'K') { } + Knock(Module* Creator) : SimpleChannelModeHandler(Creator, "noknock", 'K') { fixed_letter = false; } }; class ModuleKnock : public Module @@ -88,18 +89,15 @@ class ModuleKnock : public Module public: ModuleKnock() : cmd(this), kn(this) { - if (!ServerInstance->Modes->AddMode(&kn)) - throw ModuleException("Could not add new modes!"); - ServerInstance->AddCommand(&cmd); - } - - virtual ~ModuleKnock() + void init() { + ServerInstance->Modules->AddService(kn); + ServerInstance->Modules->AddService(cmd); } - virtual Version GetVersion() + Version GetVersion() { return Version("Provides support for /KNOCK and mode +K", VF_OPTCOMMON | VF_VENDOR); } diff --git a/src/modules/m_ojoin.cpp b/src/modules/m_ojoin.cpp index 6f150e21f..6e9212f8d 100644 --- a/src/modules/m_ojoin.cpp +++ b/src/modules/m_ojoin.cpp @@ -100,6 +100,7 @@ class NetworkPrefix : public ModeHandler prefix = NPrefix; levelrequired = INT_MAX; m_paramtype = TR_NICK; + fixed_letter = false; } unsigned int GetPrefixRank() @@ -155,7 +156,7 @@ class ModuleOjoin : public Module { if (mycommand.active) { - privs += 'Y'; + privs += np->GetModeChar(); if (op) privs += 'o'; return MOD_RES_ALLOW; @@ -185,7 +186,7 @@ class ModuleOjoin : public Module ModResult OnUserPreKick(User* source, Membership* memb, const std::string &reason) { // Don't do anything if they're not +Y - if (!memb->hasMode('Y')) + if (!memb->hasMode(np->GetModeChar())) return MOD_RES_PASSTHRU; // Let them do whatever they want to themselves. diff --git a/src/modules/m_permchannels.cpp b/src/modules/m_permchannels.cpp index 5770a6a3f..205db14ff 100644 --- a/src/modules/m_permchannels.cpp +++ b/src/modules/m_permchannels.cpp @@ -17,7 +17,7 @@ // Not in a class due to circular dependancy hell. static std::string permchannelsconf; -static bool WriteDatabase() +static bool WriteDatabase(ModeHandler* p) { FILE *f; @@ -46,7 +46,7 @@ static bool WriteDatabase() for (chan_hash::const_iterator i = ServerInstance->chanlist->begin(); i != ServerInstance->chanlist->end(); i++) { Channel* chan = i->second; - if (!chan->IsModeSet('P')) + if (!chan->IsModeSet(p)) continue; char line[1024]; @@ -110,21 +110,26 @@ static bool WriteDatabase() class PermChannel : public ModeHandler { public: - PermChannel(Module* Creator) : ModeHandler(Creator, "permanent", 'P', PARAM_NONE, MODETYPE_CHANNEL) { oper = true; } + PermChannel(Module* Creator) : ModeHandler(Creator, "permanent", 'P', PARAM_NONE, MODETYPE_CHANNEL) + { + oper = true; + fixed_letter = false; + } ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { if (adding) { - if (!channel->IsModeSet('P')) + if (!channel->IsModeSet(this)) { - channel->SetMode('P',true); + channel->SetMode(this,true); + return MODEACTION_ALLOW; } } else { - if (channel->IsModeSet('P')) + if (channel->IsModeSet(this)) { channel->SetMode(this,false); if (channel->GetUserCounter() == 0) @@ -160,26 +165,6 @@ public: CullResult cull() { - /* - * DelMode can't remove the +P mode on empty channels, or it will break - * merging modes with remote servers. Remove the empty channels now as - * we know this is not the case. - */ - chan_hash::iterator iter = ServerInstance->chanlist->begin(); - while (iter != ServerInstance->chanlist->end()) - { - Channel* c = iter->second; - if (c->GetUserCounter() == 0) - { - chan_hash::iterator at = iter; - iter++; - FOREACH_MOD(I_OnChannelDelete, OnChannelDelete(c)); - ServerInstance->chanlist->erase(at); - ServerInstance->GlobalCulls.AddItem(c); - } - else - iter++; - } ServerInstance->Modes->DelMode(&p); return Module::cull(); } @@ -230,25 +215,13 @@ public: continue; irc::spacesepstream list(modes); - std::string modeseq; - std::string par; + std::vector seq; + seq.push_back(c->name); + std::string token; + while (list.GetToken(token)) + seq.push_back(token); - list.GetToken(modeseq); - - // XXX bleh, should we pass this to the mode parser instead? ugly. --w00t - for (std::string::iterator n = modeseq.begin(); n != modeseq.end(); ++n) - { - ModeHandler* mode = ServerInstance->Modes->FindMode(*n, MODETYPE_CHANNEL); - if (mode) - { - if (mode->GetNumParams(true)) - list.GetToken(par); - else - par.clear(); - - mode->OnModeChange(ServerInstance->FakeClient, ServerInstance->FakeClient, c, par, true); - } - } + ServerInstance->SendMode(seq, ServerInstance->FakeClient); } } } @@ -256,20 +229,20 @@ public: void OnMode(User*, Extensible* dest, const irc::modestacker&) { Channel* chan = dynamic_cast(dest); - if (chan && chan->IsModeSet('P')) + if (chan && chan->IsModeSet(&p)) dirty = true; } - virtual void OnPostTopicChange(User*, Channel *c, const std::string&) + void OnPostTopicChange(User*, Channel *c, const std::string&) { - if (c->IsModeSet('P')) + if (c->IsModeSet(&p)) dirty = true; } void OnBackgroundTimer(time_t) { if (dirty) - WriteDatabase(); + WriteDatabase(&p); dirty = false; } @@ -280,7 +253,7 @@ public: virtual ModResult OnChannelPreDelete(Channel *c) { - if (c->IsModeSet('P')) + if (c->IsModeSet(&p)) return MOD_RES_DENY; return MOD_RES_PASSTHRU; diff --git a/src/modules/m_redirect.cpp b/src/modules/m_redirect.cpp index eeca44e7d..0b20c052d 100644 --- a/src/modules/m_redirect.cpp +++ b/src/modules/m_redirect.cpp @@ -20,7 +20,7 @@ class Redirect : public ModeHandler { public: - Redirect(Module* Creator) : ModeHandler(Creator, "redirect", 'L', PARAM_SETONLY, MODETYPE_CHANNEL) { } + Redirect(Module* Creator) : ModeHandler(Creator, "redirect", 'L', PARAM_SETONLY, MODETYPE_CHANNEL) { fixed_letter = false; } ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { @@ -57,14 +57,14 @@ class Redirect : public ModeHandler * We used to do some checking for circular +L here, but there is no real need for this any more especially as we * now catch +L looping in PreJoin. Remove it, since O(n) logic makes me sad, and we catch it anyway. :) -- w00t */ - channel->SetModeParam('L', parameter); + channel->SetModeParam(this, parameter); return MODEACTION_ALLOW; } else { - if (channel->IsModeSet('L')) + if (channel->IsModeSet(this)) { - channel->SetModeParam('L', ""); + channel->SetModeParam(this, ""); return MODEACTION_ALLOW; } } @@ -96,16 +96,16 @@ class ModuleRedirect : public Module { if (chan) { - if (chan->IsModeSet('L') && chan->IsModeSet('l')) + if (chan->IsModeSet(&re) && chan->IsModeSet('l')) { if (chan->GetUserCounter() >= atoi(chan->GetModeParameter('l').c_str())) { - std::string channel = chan->GetModeParameter('L'); + std::string channel = chan->GetModeParameter(&re); /* sometimes broken ulines can make circular or chained +L, avoid this */ Channel* destchan = NULL; destchan = ServerInstance->FindChan(channel); - if (destchan && destchan->IsModeSet('L')) + if (destchan && destchan->IsModeSet(&re)) { user->WriteNumeric(470, "%s %s * :You may not join this channel. A redirect is set, but you may not be redirected as it is a circular loop.", user->nick.c_str(), cname); return MOD_RES_DENY; diff --git a/src/modules/m_services_account.cpp b/src/modules/m_services_account.cpp index 4b047ea07..ae817565e 100644 --- a/src/modules/m_services_account.cpp +++ b/src/modules/m_services_account.cpp @@ -21,7 +21,7 @@ class Channel_r : public ModeHandler { public: - Channel_r(Module* Creator) : ModeHandler(Creator, "c_registered", 'r', PARAM_NONE, MODETYPE_CHANNEL) { } + Channel_r(Module* Creator) : ModeHandler(Creator, "c_registered", 'r', PARAM_NONE, MODETYPE_CHANNEL) { fixed_letter = false; } ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string ¶meter, bool adding) { @@ -29,9 +29,9 @@ class Channel_r : public ModeHandler if (!IS_LOCAL(source) || ServerInstance->ULine(source->nick.c_str()) || ServerInstance->ULine(source->server)) { // Only change the mode if it's not redundant - if ((adding && !channel->IsModeSet('r')) || (!adding && channel->IsModeSet('r'))) + if ((adding && !channel->IsModeSet(this)) || (!adding && channel->IsModeSet(this))) { - channel->SetMode('r',adding); + channel->SetMode(this,adding); return MODEACTION_ALLOW; } @@ -93,27 +93,27 @@ class AUser_R : public SimpleUserModeHandler class AChannel_M : public SimpleChannelModeHandler { public: - AChannel_M(Module* Creator) : SimpleChannelModeHandler(Creator, "regmoderated", 'M') { } + AChannel_M(Module* Creator) : SimpleChannelModeHandler(Creator, "regmoderated", 'M') { fixed_letter = false; } }; class ModuleServicesAccount : public Module { - AChannel_R m1; - AChannel_M m2; + AChannel_R chanR; + AChannel_M chanM; AUser_R m3; Channel_r m4; User_r m5; AccountExtItem accountname; public: - ModuleServicesAccount() : m1(this), m2(this), m3(this), m4(this), m5(this), + ModuleServicesAccount() : chanR(this), chanM(this), m3(this), m4(this), m5(this), accountname("accountname", this) { } void init() { - ServerInstance->Modules->AddService(m1); - ServerInstance->Modules->AddService(m2); + ServerInstance->Modules->AddService(chanR); + ServerInstance->Modules->AddService(chanM); ServerInstance->Modules->AddService(m3); ServerInstance->Modules->AddService(m4); ServerInstance->Modules->AddService(m5); @@ -178,7 +178,7 @@ class ModuleServicesAccount : public Module ModResult res; FIRST_MOD_RESULT(OnChannelRestrictionApply, res, (user,c,"regmoderated")); - if (c->IsModeSet('M') && !is_registered && res != MOD_RES_ALLOW) + if (c->IsModeSet(&chanM) && !is_registered && res != MOD_RES_ALLOW) { // user messaging a +M channel and is not registered user->WriteNumeric(477, ""+std::string(user->nick)+" "+std::string(c->name)+" :You need to be identified to a registered account to message this channel"); @@ -231,7 +231,7 @@ class ModuleServicesAccount : public Module return MOD_RES_PASSTHRU; } - if (chan->IsModeSet('R')) + if (chan->IsModeSet(&chanR)) { if (!is_registered) {