Add the rest of the <modeletters> support

This commit is contained in:
Daniel De Graaf 2010-02-09 19:17:39 -06:00
parent bc6f9b687f
commit ecdf81507a
8 changed files with 94 additions and 127 deletions

View File

@ -78,6 +78,8 @@ void ModeHandler::AdjustModeChar(char proposed_letter)
{
if (fixed_letter)
return;
if (!proposed_letter && GetPrefixRank())
return;
mode = proposed_letter;
}

View File

@ -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"));

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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.

View File

@ -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 &parameter, 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<std::string> 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<Channel*>(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;

View File

@ -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 &parameter, 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;

View File

@ -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 &parameter, 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)
{