mirror of
https://github.com/anope/anope.git
synced 2026-06-29 02:26:38 +02:00
Add "virtual mode" support
This allows fully tracking extbans and other modes set by a different underlying mode, such as InspIRCd's namedmodes Add two configuration options to cs_ban to configure which mode is set and whether or not to kick banned users. Add default "mute" fantasy command to botserv.example.conf
This commit is contained in:
@@ -386,6 +386,7 @@ fantasy { name = "LEVELS"; command = "chanserv/levels"; }
|
||||
fantasy { name = "LIST"; command = "chanserv/list"; prepend_channel = false; }
|
||||
fantasy { name = "LOG"; command = "chanserv/log"; }
|
||||
fantasy { name = "MODE"; command = "chanserv/mode"; }
|
||||
fantasy { name = "MUTE"; command = "chanserv/ban"; kick = no; mode = "QUIET"; }
|
||||
fantasy { name = "OP"; command = "chanserv/modes"; }
|
||||
fantasy { name = "OWNER"; command = "chanserv/modes"; }
|
||||
fantasy { name = "PROTECT"; command = "chanserv/modes"; }
|
||||
|
||||
@@ -868,6 +868,12 @@ command { service = "ChanServ"; name = "AKICK"; command = "chanserv/akick"; grou
|
||||
*
|
||||
* Provides the command chanserv/ban.
|
||||
*
|
||||
* The configuration option 'kick' may be set in a command block for this command to control
|
||||
* whether or not users will be kicked from the channel once banned. The default is 'yes'.
|
||||
*
|
||||
* The configuration option 'mode' may be set to control which mode is set, such as BAN or QUIET.
|
||||
* The default is BAN.
|
||||
*
|
||||
* Used for banning users from channels.
|
||||
*/
|
||||
module { name = "cs_ban" }
|
||||
|
||||
+2
-1
@@ -276,10 +276,11 @@ class CoreExport Channel : public Base, public Extensible
|
||||
|
||||
/** Unbans a user from this channel.
|
||||
* @param u The user to unban
|
||||
* @param mode The mode to unban
|
||||
* @param full Whether or not to match using the user's real host and IP
|
||||
* @return whether or not a ban was removed
|
||||
*/
|
||||
bool Unban(User *u, bool full = false);
|
||||
bool Unban(User *u, const Anope::string &mode, bool full = false);
|
||||
|
||||
/** Check whether a user is permitted to be on this channel
|
||||
* @param u The user
|
||||
|
||||
@@ -138,6 +138,8 @@ namespace Configuration
|
||||
Block *GetModule(const Anope::string &name);
|
||||
|
||||
BotInfo *GetClient(const Anope::string &name);
|
||||
|
||||
Block *GetCommand(CommandSource &);
|
||||
};
|
||||
|
||||
struct Uplink
|
||||
|
||||
+34
-7
@@ -96,6 +96,9 @@ class CoreExport UserModeParam : public UserMode
|
||||
class CoreExport ChannelMode : public Mode
|
||||
{
|
||||
public:
|
||||
/* channel modes that can posssibly unwrap this mode */
|
||||
std::vector<ChannelMode *> listeners;
|
||||
|
||||
/** constructor
|
||||
* @param name The mode name
|
||||
* @param mc The mode char
|
||||
@@ -103,6 +106,18 @@ class CoreExport ChannelMode : public Mode
|
||||
ChannelMode(const Anope::string &name, char mc);
|
||||
|
||||
bool CanSet(User *u) const anope_override;
|
||||
|
||||
/** 'wrap' this channel mode and param to the underlying mode and param
|
||||
*/
|
||||
virtual ChannelMode *Wrap(Anope::string ¶m);
|
||||
|
||||
/** 'unwrap' this mode to our internal representation
|
||||
*/
|
||||
ChannelMode *Unwrap(Anope::string ¶m);
|
||||
|
||||
/** called when a mode is being unwrapped, and is asking us if we can unwrap it
|
||||
*/
|
||||
virtual ChannelMode *Unwrap(ChannelMode *, Anope::string ¶m);
|
||||
};
|
||||
|
||||
/** This is a mode for lists, eg b/e/I. These modes should inherit from this
|
||||
@@ -186,6 +201,25 @@ class CoreExport ChannelModeStatus : public ChannelMode
|
||||
ChannelModeStatus(const Anope::string &name, char mc, char msymbol, short mlevel);
|
||||
};
|
||||
|
||||
/** A virtual mode. This mode doesn't natively exist on the IRCd (like extbans),
|
||||
* but we still have a representation for it.
|
||||
*/
|
||||
template<typename T>
|
||||
class ChannelModeVirtual : public T
|
||||
{
|
||||
Anope::string base;
|
||||
ChannelMode *basech;
|
||||
|
||||
public:
|
||||
ChannelModeVirtual(const Anope::string &mname, const Anope::string &basename);
|
||||
|
||||
~ChannelModeVirtual();
|
||||
|
||||
ChannelMode *Wrap(Anope::string ¶m) anope_override;
|
||||
|
||||
ChannelMode *Unwrap(ChannelMode *cm, Anope::string ¶m) = 0;
|
||||
};
|
||||
|
||||
/* The status a user has on a channel (+v, +h, +o) etc */
|
||||
class CoreExport ChannelStatus
|
||||
{
|
||||
@@ -257,13 +291,6 @@ class CoreExport ChannelModeNoone : public ChannelMode
|
||||
*/
|
||||
class CoreExport ModeManager
|
||||
{
|
||||
protected:
|
||||
/* Array of all modes Anope knows about. Modes are in this array at position
|
||||
* modechar. Additionally, status modes are in this array (again) at statuschar.
|
||||
*/
|
||||
static std::vector<ChannelMode *> ChannelModes;
|
||||
static std::vector<UserMode *> UserModes;
|
||||
|
||||
public:
|
||||
|
||||
/* Number of generic channel and user modes we are tracking */
|
||||
|
||||
+28
-19
@@ -19,15 +19,16 @@ class TempBan : public Timer
|
||||
private:
|
||||
Anope::string channel;
|
||||
Anope::string mask;
|
||||
Anope::string mode;
|
||||
|
||||
public:
|
||||
TempBan(time_t seconds, Channel *c, const Anope::string &banmask) : Timer(me, seconds), channel(c->name), mask(banmask) { }
|
||||
TempBan(time_t seconds, Channel *c, const Anope::string &banmask, const Anope::string &mod) : Timer(me, seconds), channel(c->name), mask(banmask), mode(mod) { }
|
||||
|
||||
void Tick(time_t ctime) anope_override
|
||||
{
|
||||
Channel *c = Channel::Find(this->channel);
|
||||
if (c)
|
||||
c->RemoveMode(NULL, "BAN", this->mask);
|
||||
c->RemoveMode(NULL, mode, this->mask);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -43,6 +44,8 @@ class CommandCSBan : public Command
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
|
||||
{
|
||||
const Anope::string &chan = params[0];
|
||||
Configuration::Block *block = Config->GetCommand(source);
|
||||
const Anope::string &mode = block->Get<Anope::string>("mode", "BAN");
|
||||
|
||||
ChannelInfo *ci = ChannelInfo::Find(chan);
|
||||
if (ci == NULL)
|
||||
@@ -57,9 +60,9 @@ class CommandCSBan : public Command
|
||||
source.Reply(CHAN_X_NOT_IN_USE, chan.c_str());
|
||||
return;
|
||||
}
|
||||
else if (IRCD->GetMaxListFor(c) && c->HasMode("BAN") >= IRCD->GetMaxListFor(c))
|
||||
else if (IRCD->GetMaxListFor(c) && c->HasMode(mode) >= IRCD->GetMaxListFor(c))
|
||||
{
|
||||
source.Reply(_("The ban list for %s is full."), c->name.c_str());
|
||||
source.Reply(_("The %s list for %s is full."), mode.lower().c_str(), c->name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -126,12 +129,12 @@ class CommandCSBan : public Command
|
||||
bool override = !u_access.HasPriv("BAN") || (u != u2 && ci->HasExt("PEACE") && u2_access >= u_access);
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << mask;
|
||||
|
||||
if (!c->HasMode("BAN", mask))
|
||||
if (!c->HasMode(mode, mask))
|
||||
{
|
||||
c->SetMode(NULL, "BAN", mask);
|
||||
c->SetMode(NULL, mode, mask);
|
||||
if (ban_time)
|
||||
{
|
||||
new TempBan(ban_time, c, mask);
|
||||
new TempBan(ban_time, c, mask, mode);
|
||||
source.Reply(_("Ban on \002%s\002 expires in %s."), mask.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
|
||||
}
|
||||
}
|
||||
@@ -140,10 +143,13 @@ class CommandCSBan : public Command
|
||||
if (!c->FindUser(u2))
|
||||
return;
|
||||
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK")))
|
||||
c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), source.GetNick().c_str());
|
||||
else
|
||||
c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
|
||||
if (block->Get<bool>("kick", "yes"))
|
||||
{
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !source.AccessFor(ci).HasPriv("SIGNKICK")))
|
||||
c->Kick(ci->WhoSends(), u2, "%s (%s)", reason.c_str(), source.GetNick().c_str());
|
||||
else
|
||||
c->Kick(ci->WhoSends(), u2, "%s", reason.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -152,12 +158,12 @@ class CommandCSBan : public Command
|
||||
bool override = !founder && !u_access.HasPriv("BAN");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "for " << target;
|
||||
|
||||
if (!c->HasMode("BAN", target))
|
||||
if (!c->HasMode(mode, target))
|
||||
{
|
||||
c->SetMode(NULL, "BAN", target);
|
||||
c->SetMode(NULL, mode, target);
|
||||
if (ban_time)
|
||||
{
|
||||
new TempBan(ban_time, c, target);
|
||||
new TempBan(ban_time, c, target, mode);
|
||||
source.Reply(_("Ban on \002%s\002 expires in %s."), target.c_str(), Anope::Duration(ban_time, source.GetAccount()).c_str());
|
||||
}
|
||||
}
|
||||
@@ -183,11 +189,14 @@ class CommandCSBan : public Command
|
||||
else if (uc->user->IsProtected())
|
||||
continue;
|
||||
|
||||
++kicked;
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), target.c_str(), source.GetNick().c_str());
|
||||
else
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), target.c_str());
|
||||
if (block->Get<bool>("kick", "yes"))
|
||||
{
|
||||
++kicked;
|
||||
if (ci->HasExt("SIGNKICK") || (ci->HasExt("SIGNKICK_LEVEL") && !u_access.HasPriv("SIGNKICK")))
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s) (%s)", reason.c_str(), target.c_str(), source.GetNick().c_str());
|
||||
else
|
||||
c->Kick(ci->WhoSends(), uc->user, "%s (Matches %s)", reason.c_str(), target.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -488,8 +488,7 @@ class CommandCSMode : public Command
|
||||
for (unsigned j = 0; j < ModeManager::GetChannelModes().size(); ++j)
|
||||
{
|
||||
ChannelMode *cm = ModeManager::GetChannelModes()[j];
|
||||
if (!cm)
|
||||
continue;
|
||||
|
||||
if (!u || cm->CanSet(u) || can_override)
|
||||
{
|
||||
if (cm->type == MODE_REGULAR || (!adding && cm->type == MODE_PARAM))
|
||||
|
||||
@@ -22,6 +22,13 @@ class CommandCSUnban : public Command
|
||||
|
||||
void Execute(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override
|
||||
{
|
||||
ChannelMode *cm = ModeManager::FindChannelModeByName("BAN");
|
||||
if (!cm)
|
||||
return;
|
||||
|
||||
std::vector<ChannelMode *> modes = cm->listeners;
|
||||
modes.push_back(cm);
|
||||
|
||||
if (params.empty())
|
||||
{
|
||||
if (!source.GetUser())
|
||||
@@ -38,8 +45,9 @@ class CommandCSUnban : public Command
|
||||
if (!ci->c || !source.AccessFor(ci).HasPriv("UNBAN"))
|
||||
continue;
|
||||
|
||||
if (ci->c->Unban(source.GetUser(), true))
|
||||
++count;
|
||||
for (unsigned j = 0; j < modes.size(); ++j)
|
||||
if (ci->c->Unban(source.GetUser(), modes[j]->name, true))
|
||||
++count;
|
||||
}
|
||||
|
||||
Log(LOG_COMMAND, source, this, NULL) << "on all channels";
|
||||
@@ -80,7 +88,8 @@ class CommandCSUnban : public Command
|
||||
bool override = !source.AccessFor(ci).HasPriv("UNBAN") && source.HasPriv("chanserv/kick");
|
||||
Log(override ? LOG_OVERRIDE : LOG_COMMAND, source, this, ci) << "to unban " << u2->nick;
|
||||
|
||||
ci->c->Unban(u2, source.GetUser() == u2);
|
||||
for (unsigned i = 0; i < modes.size(); ++i)
|
||||
ci->c->Unban(u2, modes[i]->name, source.GetUser() == u2);
|
||||
if (u2 == source.GetUser())
|
||||
source.Reply(_("You have been unbanned from \002%s\002."), ci->c->name.c_str());
|
||||
else
|
||||
|
||||
+162
-37
@@ -77,25 +77,61 @@ class InspIRCd20Proto : public IRCDProto
|
||||
bool IsIdentValid(const Anope::string &ident) anope_override { return insp12->IsIdentValid(ident); }
|
||||
};
|
||||
|
||||
class InspIRCdExtBan : public ChannelModeList
|
||||
class InspIRCdExtBan : public ChannelModeVirtual<ChannelModeList>
|
||||
{
|
||||
char ext;
|
||||
|
||||
public:
|
||||
InspIRCdExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { }
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
InspIRCdExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual<ChannelModeList>(mname, basename)
|
||||
, ext(extban)
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
}
|
||||
|
||||
if (mask.find("m:") == 0 || mask.find("N:") == 0)
|
||||
ChannelMode *Wrap(Anope::string ¶m) anope_override
|
||||
{
|
||||
param = Anope::string(ext) + ":" + param;
|
||||
return ChannelModeVirtual<ChannelModeList>::Wrap(param);
|
||||
}
|
||||
|
||||
ChannelMode *Unwrap(ChannelMode *cm, Anope::string ¶m) anope_override
|
||||
{
|
||||
if (cm->type != MODE_LIST || param.length() < 3 || param[0] != ext || param[1] != ':')
|
||||
return cm;
|
||||
|
||||
param = param.substr(2);
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
namespace InspIRCdExtban
|
||||
{
|
||||
class EntryMatcher : public InspIRCdExtBan
|
||||
{
|
||||
public:
|
||||
EntryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
|
||||
Entry en(this->name, real_mask);
|
||||
if (en.Matches(u))
|
||||
return true;
|
||||
return Entry(this->name, real_mask).Matches(u);
|
||||
}
|
||||
else if (mask.find("j:") == 0)
|
||||
};
|
||||
|
||||
class ChannelMatcher : public InspIRCdExtBan
|
||||
{
|
||||
public:
|
||||
ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
|
||||
Anope::string channel = mask.substr(3);
|
||||
|
||||
ChannelMode *cm = NULL;
|
||||
@@ -116,39 +152,87 @@ class InspIRCdExtBan : public ChannelModeList
|
||||
if (cm == NULL || uc->status.HasMode(cm->mchar))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (mask.find("R:") == 0)
|
||||
};
|
||||
|
||||
class AccountMatcher : public InspIRCdExtBan
|
||||
{
|
||||
public:
|
||||
AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
|
||||
if (u->IsIdentified() && real_mask.equals_ci(u->Account()->display))
|
||||
return true;
|
||||
return u->IsIdentified() && real_mask.equals_ci(u->Account()->display);
|
||||
}
|
||||
else if (mask.find("r:") == 0)
|
||||
};
|
||||
|
||||
class RealnameMatcher : public InspIRCdExtBan
|
||||
{
|
||||
public:
|
||||
RealnameMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
return Anope::Match(u->realname, real_mask);
|
||||
}
|
||||
};
|
||||
|
||||
class ServerMatcher : public InspIRCdExtBan
|
||||
{
|
||||
public:
|
||||
ServerMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
return Anope::Match(u->server->GetName(), real_mask);
|
||||
}
|
||||
};
|
||||
|
||||
class FinerprintMatcher : public InspIRCdExtBan
|
||||
{
|
||||
public:
|
||||
FinerprintMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
return !u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask);
|
||||
}
|
||||
};
|
||||
|
||||
class UnidentifiedMatcher : public InspIRCdExtBan
|
||||
{
|
||||
public:
|
||||
UnidentifiedMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c)
|
||||
{
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
|
||||
if (Anope::Match(u->realname, real_mask))
|
||||
return true;
|
||||
}
|
||||
else if (mask.find("s:") == 0)
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
|
||||
if (Anope::Match(u->server->GetName(), real_mask))
|
||||
return true;
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
return !u->Account() && Entry("BAN", real_mask).Matches(u);
|
||||
}
|
||||
else if (mask.find("z:") == 0)
|
||||
{
|
||||
Anope::string real_mask = mask.substr(2);
|
||||
|
||||
if (!u->fingerprint.empty() && Anope::Match(u->fingerprint, real_mask))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
class ColonDelimitedParamMode : public ChannelModeParam
|
||||
{
|
||||
@@ -304,17 +388,26 @@ struct IRCDMessageCapab : Message::Capab
|
||||
if (modename.equals_cs("admin"))
|
||||
cm = new ChannelModeStatus("PROTECT", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 3);
|
||||
else if (modename.equals_cs("allowinvite"))
|
||||
{
|
||||
cm = new ChannelMode("ALLINVITE", modechar[0]);
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("INVITEBAN", "BAN", 'A'));
|
||||
}
|
||||
else if (modename.equals_cs("auditorium"))
|
||||
cm = new ChannelMode("AUDITORIUM", modechar[0]);
|
||||
else if (modename.equals_cs("ban"))
|
||||
cm = new InspIRCdExtBan("BAN", modechar[0]);
|
||||
cm = new ChannelModeList("BAN", modechar[0]);
|
||||
else if (modename.equals_cs("banexception"))
|
||||
cm = new InspIRCdExtBan("EXCEPT", 'e');
|
||||
cm = new ChannelModeList("EXCEPT", modechar[0]);
|
||||
else if (modename.equals_cs("blockcaps"))
|
||||
{
|
||||
cm = new ChannelMode("BLOCKCAPS", modechar[0]);
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("BLOCKCAPSBAN", "BAN", 'B'));
|
||||
}
|
||||
else if (modename.equals_cs("blockcolor"))
|
||||
{
|
||||
cm = new ChannelMode("BLOCKCOLOR", modechar[0]);
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("BLOCKCOLORBAN", "BAN", 'c'));
|
||||
}
|
||||
else if (modename.equals_cs("c_registered"))
|
||||
cm = new ChannelModeNoone("REGISTERED", modechar[0]);
|
||||
else if (modename.equals_cs("censor"))
|
||||
@@ -334,7 +427,7 @@ struct IRCDMessageCapab : Message::Capab
|
||||
else if (modename.equals_cs("history"))
|
||||
cm = new ChannelModeHistory(modechar[0]);
|
||||
else if (modename.equals_cs("invex"))
|
||||
cm = new InspIRCdExtBan("INVITEOVERRIDE", 'I');
|
||||
cm = new ChannelModeList("INVITEOVERRIDE", modechar[0]);
|
||||
else if (modename.equals_cs("inviteonly"))
|
||||
cm = new ChannelMode("INVITE", modechar[0]);
|
||||
else if (modename.equals_cs("joinflood"))
|
||||
@@ -350,17 +443,29 @@ struct IRCDMessageCapab : Message::Capab
|
||||
else if (modename.equals_cs("nickflood"))
|
||||
cm = new ColonDelimitedParamMode("NICKFLOOD", modechar[0]);
|
||||
else if (modename.equals_cs("noctcp"))
|
||||
{
|
||||
cm = new ChannelMode("NOCTCP", modechar[0]);
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NOCTCPBAN", "BAN", 'C'));
|
||||
}
|
||||
else if (modename.equals_cs("noextmsg"))
|
||||
cm = new ChannelMode("NOEXTERNAL", modechar[0]);
|
||||
else if (modename.equals_cs("nokick"))
|
||||
{
|
||||
cm = new ChannelMode("NOKICK", modechar[0]);
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NOKICKBAN", "BAN", 'Q'));
|
||||
}
|
||||
else if (modename.equals_cs("noknock"))
|
||||
cm = new ChannelMode("NOKNOCK", modechar[0]);
|
||||
else if (modename.equals_cs("nonick"))
|
||||
{
|
||||
cm = new ChannelMode("NONICK", modechar[0]);
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NONICKBAN", "BAN", 'N'));
|
||||
}
|
||||
else if (modename.equals_cs("nonotice"))
|
||||
{
|
||||
cm = new ChannelMode("NONOTICE", modechar[0]);
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("NONOTICEBAN", "BAN", 'T'));
|
||||
}
|
||||
else if (modename.equals_cs("op"))
|
||||
cm = new ChannelModeStatus("OP", modechar.length() > 1 ? modechar[1] : modechar[0], modechar.length() > 1 ? modechar[0] : 0, 2);
|
||||
else if (modename.equals_cs("operonly"))
|
||||
@@ -378,9 +483,15 @@ struct IRCDMessageCapab : Message::Capab
|
||||
else if (modename.equals_cs("secret"))
|
||||
cm = new ChannelMode("SECRET", modechar[0]);
|
||||
else if (modename.equals_cs("sslonly"))
|
||||
{
|
||||
cm = new ChannelMode("SSL", modechar[0]);
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::FinerprintMatcher("SSLBAN", "BAN", 'z'));
|
||||
}
|
||||
else if (modename.equals_cs("stripcolor"))
|
||||
{
|
||||
cm = new ChannelMode("STRIPCOLOR", modechar[0]);
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("STRIPCOLORBAN", "BAN", 'S'));
|
||||
}
|
||||
else if (modename.equals_cs("topiclock"))
|
||||
cm = new ChannelMode("TOPIC", modechar[0]);
|
||||
else if (modename.equals_cs("voice"))
|
||||
@@ -481,11 +592,25 @@ struct IRCDMessageCapab : Message::Capab
|
||||
while (ssep.GetToken(module))
|
||||
{
|
||||
if (module.equals_cs("m_services_account.so"))
|
||||
{
|
||||
Servers::Capab.insert("SERVICES");
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::AccountMatcher("ACCOUNTBAN", "BAN", 'R'));
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::UnidentifiedMatcher("UNREGISTEREDBAN", "BAN", 'U'));
|
||||
}
|
||||
else if (module.equals_cs("m_chghost.so"))
|
||||
Servers::Capab.insert("CHGHOST");
|
||||
else if (module.equals_cs("m_chgident.so"))
|
||||
Servers::Capab.insert("CHGIDENT");
|
||||
else if (module == "m_channelban.so")
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::ChannelMatcher("CHANNELBAN", "BAN", 'j'));
|
||||
else if (module == "m_gecosban.so")
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::RealnameMatcher("REALNAMEBAN", "BAN", 'r'));
|
||||
else if (module == "m_nopartmessage.so")
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("PARTMESSAGEBAN", "BAN", 'p'));
|
||||
else if (module == "m_serverban.so")
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::ServerMatcher("SERVERBAN", "BAN", 's'));
|
||||
else if (module == "m_muteban.so")
|
||||
ModeManager::AddChannelMode(new InspIRCdExtban::EntryMatcher("QUIET", "BAN", 'm'));
|
||||
}
|
||||
}
|
||||
else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1)
|
||||
|
||||
+98
-28
@@ -415,17 +415,44 @@ class UnrealIRCdProto : public IRCDProto
|
||||
}
|
||||
};
|
||||
|
||||
class UnrealExtBan : public ChannelModeList
|
||||
class UnrealExtBan : public ChannelModeVirtual<ChannelModeList>
|
||||
{
|
||||
char ext;
|
||||
|
||||
public:
|
||||
UnrealExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { }
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
UnrealExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual<ChannelModeList>(mname, basename)
|
||||
, ext(extban)
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
}
|
||||
|
||||
if (mask.find("~c:") == 0)
|
||||
ChannelMode *Wrap(Anope::string ¶m) anope_override
|
||||
{
|
||||
param = "~" + Anope::string(ext) + ":" + param;
|
||||
return ChannelModeVirtual<ChannelModeList>::Wrap(param);
|
||||
}
|
||||
|
||||
ChannelMode *Unwrap(ChannelMode *cm, Anope::string ¶m) anope_override
|
||||
{
|
||||
if (cm->type != MODE_LIST || param.length() < 4 || param[0] != '~' || param[1] != ext || param[2] != ':')
|
||||
return cm;
|
||||
|
||||
param = param.substr(3);
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
namespace UnrealExtban
|
||||
{
|
||||
class ChannelMatcher : public UnrealExtBan
|
||||
{
|
||||
public:
|
||||
ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string channel = mask.substr(3);
|
||||
|
||||
ChannelMode *cm = NULL;
|
||||
@@ -446,38 +473,73 @@ class UnrealExtBan : public ChannelModeList
|
||||
if (cm == NULL || uc->status.HasMode(cm->mchar))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (mask.find("~j:") == 0 || mask.find("~n:") == 0 || mask.find("~q:") == 0)
|
||||
};
|
||||
|
||||
class EntryMatcher : public UnrealExtBan
|
||||
{
|
||||
public:
|
||||
EntryMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
|
||||
Entry en(this->name, real_mask);
|
||||
if (en.Matches(u))
|
||||
return true;
|
||||
return Entry(this->name, real_mask).Matches(u);
|
||||
}
|
||||
else if (mask.find("~r:") == 0)
|
||||
};
|
||||
|
||||
class RealnameMatcher : public UnrealExtBan
|
||||
{
|
||||
public:
|
||||
RealnameMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
|
||||
if (Anope::Match(u->realname, real_mask))
|
||||
return true;
|
||||
return Anope::Match(u->realname, real_mask);
|
||||
}
|
||||
else if (mask.find("~R:") == 0)
|
||||
};
|
||||
|
||||
class RegisteredMatcher : public UnrealExtBan
|
||||
{
|
||||
public:
|
||||
RegisteredMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
if (u->HasMode("REGISTERED") && mask.equals_ci(u->nick))
|
||||
return true;
|
||||
const Anope::string &mask = e->GetMask();
|
||||
return u->HasMode("REGISTERED") && mask.equals_ci(u->nick);
|
||||
}
|
||||
else if (mask.find("~a:") == 0)
|
||||
{
|
||||
};
|
||||
|
||||
class AccountMatcher : public UnrealExtBan
|
||||
{
|
||||
public:
|
||||
AccountMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : UnrealExtBan(mname, mbase, c)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matches(User *u, const Entry *e) anope_override
|
||||
{
|
||||
const Anope::string &mask = e->GetMask();
|
||||
Anope::string real_mask = mask.substr(3);
|
||||
|
||||
if (u->Account() && Anope::Match(u->Account()->display, real_mask))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
return u->Account() && Anope::Match(u->Account()->display, real_mask);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class ChannelModeFlood : public ChannelModeParam
|
||||
{
|
||||
@@ -565,13 +627,21 @@ struct IRCDMessageCapab : Message::Capab
|
||||
switch (modebuf[t])
|
||||
{
|
||||
case 'b':
|
||||
ModeManager::AddChannelMode(new UnrealExtBan("BAN", 'b'));
|
||||
ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b'));
|
||||
|
||||
ModeManager::AddChannelMode(new UnrealExtban::ChannelMatcher("CHANNELBAN", "BAN", 'c'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("JOINBAN", "BAN", 'j'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("NONICKBAN", "BAN", 'n'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::EntryMatcher("QUIET", "BAN", 'q'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::RealnameMatcher("REALNAMEBAN", "BAN", 'r'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::RegisteredMatcher("REGISTEREDBAN", "BAN", 'R'));
|
||||
ModeManager::AddChannelMode(new UnrealExtban::AccountMatcher("ACCOUNTBAN", "BAN", 'a'));
|
||||
continue;
|
||||
case 'e':
|
||||
ModeManager::AddChannelMode(new UnrealExtBan("EXCEPT", 'e'));
|
||||
ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e'));
|
||||
continue;
|
||||
case 'I':
|
||||
ModeManager::AddChannelMode(new UnrealExtBan("INVITEOVERRIDE", 'I'));
|
||||
ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I'));
|
||||
continue;
|
||||
default:
|
||||
ModeManager::AddChannelMode(new ChannelModeList("", modebuf[t]));
|
||||
|
||||
@@ -61,7 +61,7 @@ bool WebCPanel::ChanServ::Modes::OnRequest(HTTPProvider *server, const Anope::st
|
||||
{
|
||||
ChannelMode *cm = ModeManager::GetChannelModes()[i];
|
||||
|
||||
if (cm && cm->type == MODE_LIST)
|
||||
if (cm->type == MODE_LIST)
|
||||
replacements["LISTMODES"] = cm->mchar;
|
||||
}
|
||||
|
||||
|
||||
+25
-13
@@ -248,11 +248,14 @@ std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> Channel::Get
|
||||
return std::make_pair(it, it_end);
|
||||
}
|
||||
|
||||
void Channel::SetModeInternal(MessageSource &setter, ChannelMode *cm, const Anope::string ¶m, bool enforce_mlock)
|
||||
void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
|
||||
{
|
||||
if (!cm)
|
||||
if (!ocm)
|
||||
return;
|
||||
|
||||
Anope::string param = oparam;
|
||||
ChannelMode *cm = ocm->Unwrap(param);
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
|
||||
/* Setting v/h/o/a/q etc */
|
||||
@@ -315,11 +318,14 @@ void Channel::SetModeInternal(MessageSource &setter, ChannelMode *cm, const Anop
|
||||
this->CheckModes();
|
||||
}
|
||||
|
||||
void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *cm, const Anope::string ¶m, bool enforce_mlock)
|
||||
void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
|
||||
{
|
||||
if (!cm)
|
||||
if (!ocm)
|
||||
return;
|
||||
|
||||
Anope::string param = oparam;
|
||||
ChannelMode *cm = ocm->Unwrap(param);
|
||||
|
||||
EventReturn MOD_RESULT;
|
||||
|
||||
/* Setting v/h/o/a/q etc */
|
||||
@@ -433,9 +439,12 @@ void Channel::SetMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶m,
|
||||
this->chanserv_modecount++;
|
||||
}
|
||||
|
||||
ModeManager::StackerAdd(bi, this, cm, true, param);
|
||||
Anope::string wparam = param;
|
||||
ChannelMode *wcm = cm->Wrap(wparam);
|
||||
|
||||
ModeManager::StackerAdd(bi, this, wcm, true, wparam);
|
||||
MessageSource ms(bi);
|
||||
SetModeInternal(ms, cm, param, enforce_mlock);
|
||||
SetModeInternal(ms, wcm, wparam, enforce_mlock);
|
||||
}
|
||||
|
||||
void Channel::SetMode(BotInfo *bi, const Anope::string &mname, const Anope::string ¶m, bool enforce_mlock)
|
||||
@@ -484,9 +493,12 @@ void Channel::RemoveMode(BotInfo *bi, ChannelMode *cm, const Anope::string ¶
|
||||
this->chanserv_modecount++;
|
||||
}
|
||||
|
||||
ModeManager::StackerAdd(bi, this, cm, false, realparam);
|
||||
Anope::string wparam = realparam;
|
||||
ChannelMode *wcm = cm->Wrap(wparam);
|
||||
|
||||
ModeManager::StackerAdd(bi, this, wcm, false, wparam);
|
||||
MessageSource ms(bi);
|
||||
RemoveModeInternal(ms, cm, realparam, enforce_mlock);
|
||||
RemoveModeInternal(ms, wcm, wparam, enforce_mlock);
|
||||
}
|
||||
|
||||
void Channel::RemoveMode(BotInfo *bi, const Anope::string &mname, const Anope::string ¶m, bool enforce_mlock)
|
||||
@@ -849,21 +861,21 @@ void Channel::SetCorrectModes(User *user, bool give_modes)
|
||||
}
|
||||
}
|
||||
|
||||
bool Channel::Unban(User *u, bool full)
|
||||
bool Channel::Unban(User *u, const Anope::string &mode, bool full)
|
||||
{
|
||||
if (!this->HasMode("BAN"))
|
||||
if (!this->HasMode(mode))
|
||||
return false;
|
||||
|
||||
bool ret = false;
|
||||
|
||||
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = this->GetModeList("BAN");
|
||||
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = this->GetModeList(mode);
|
||||
for (; bans.first != bans.second;)
|
||||
{
|
||||
Entry ban("BAN", bans.first->second);
|
||||
Entry ban(mode, bans.first->second);
|
||||
++bans.first;
|
||||
if (ban.Matches(u, full))
|
||||
{
|
||||
this->RemoveMode(NULL, "BAN", ban.GetMask());
|
||||
this->RemoveMode(NULL, mode, ban.GetMask());
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,6 +620,21 @@ BotInfo *Conf::GetClient(const Anope::string &cname)
|
||||
return GetClient(cname);
|
||||
}
|
||||
|
||||
Block *Conf::GetCommand(CommandSource &source)
|
||||
{
|
||||
const Anope::string &block_name = source.c ? "fantasy" : "command";
|
||||
|
||||
for (std::pair<block_map::iterator, block_map::iterator> iters = blocks.equal_range(block_name); iters.first != iters.second; ++iters.first)
|
||||
{
|
||||
Block *b = &iters.first->second;
|
||||
|
||||
if (b->Get<Anope::string>("name") == source.command)
|
||||
return b;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
File::File(const Anope::string &n, bool e) : name(n), executable(e), fp(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
+123
-37
@@ -21,9 +21,15 @@ struct StackerInfo;
|
||||
static std::map<User *, StackerInfo *> UserStackerObjects;
|
||||
static std::map<Channel *, StackerInfo *> ChannelStackerObjects;
|
||||
|
||||
/* List of all modes Anope knows about */
|
||||
std::vector<ChannelMode *> ModeManager::ChannelModes;
|
||||
std::vector<UserMode *> ModeManager::UserModes;
|
||||
/* Array of all modes Anope knows about.*/
|
||||
static std::vector<ChannelMode *> ChannelModes;
|
||||
static std::vector<UserMode *> UserModes;
|
||||
|
||||
/* Modes are in this array are at position
|
||||
* modechar. Additionally, status modes are in this array (again) at statuschar.
|
||||
*/
|
||||
static std::vector<ChannelMode *> ChannelModesIdx;
|
||||
static std::vector<UserMode *> UserModesIdx;
|
||||
|
||||
static std::map<Anope::string, ChannelMode *> ChannelModesByName;
|
||||
static std::map<Anope::string, UserMode *> UserModesByName;
|
||||
@@ -142,6 +148,28 @@ bool ChannelMode::CanSet(User *u) const
|
||||
return MOD_RESULT != EVENT_STOP;
|
||||
}
|
||||
|
||||
ChannelMode *ChannelMode::Wrap(Anope::string ¶m)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
ChannelMode *ChannelMode::Unwrap(Anope::string ¶m)
|
||||
{
|
||||
for (unsigned i = 0; i < listeners.size(); ++i)
|
||||
{
|
||||
ChannelMode *cm = listeners[i]->Unwrap(this, param);
|
||||
if (cm != this)
|
||||
return cm;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
ChannelMode *ChannelMode::Unwrap(ChannelMode *, Anope::string ¶m)
|
||||
{
|
||||
throw CoreException("Unwrap in channel mode");
|
||||
}
|
||||
|
||||
ChannelModeList::ChannelModeList(const Anope::string &cm, char mch) : ChannelMode(cm, mch)
|
||||
{
|
||||
this->type = MODE_LIST;
|
||||
@@ -157,6 +185,42 @@ ChannelModeStatus::ChannelModeStatus(const Anope::string &mname, char modeChar,
|
||||
this->type = MODE_STATUS;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ChannelModeVirtual<T>::ChannelModeVirtual(const Anope::string &mname, const Anope::string &basename) : T(mname, 0)
|
||||
, base(basename)
|
||||
{
|
||||
basech = ModeManager::FindChannelModeByName(base);
|
||||
if (basech)
|
||||
basech->listeners.push_back(this);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ChannelModeVirtual<T>::~ChannelModeVirtual()
|
||||
{
|
||||
if (basech)
|
||||
{
|
||||
std::vector<ChannelMode *>::iterator it = std::find(basech->listeners.begin(), basech->listeners.end(), this);
|
||||
if (it != basech->listeners.end())
|
||||
basech->listeners.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ChannelMode *ChannelModeVirtual<T>::Wrap(Anope::string ¶m)
|
||||
{
|
||||
if (basech == NULL)
|
||||
{
|
||||
basech = ModeManager::FindChannelModeByName(base);
|
||||
if (basech)
|
||||
basech->listeners.push_back(this);
|
||||
}
|
||||
|
||||
return basech;
|
||||
}
|
||||
|
||||
template class ChannelModeVirtual<ChannelMode>;
|
||||
template class ChannelModeVirtual<ChannelModeList>;
|
||||
|
||||
bool UserModeOperOnly::CanSet(User *u) const
|
||||
{
|
||||
return u && u->HasMode("OPER");
|
||||
@@ -321,6 +385,8 @@ bool ModeManager::AddUserMode(UserMode *um)
|
||||
{
|
||||
if (ModeManager::FindUserModeByChar(um->mchar) != NULL)
|
||||
return false;
|
||||
if (ModeManager::FindUserModeByName(um->name) != NULL)
|
||||
return false;
|
||||
|
||||
if (um->name.empty())
|
||||
{
|
||||
@@ -329,12 +395,14 @@ bool ModeManager::AddUserMode(UserMode *um)
|
||||
}
|
||||
|
||||
unsigned want = um->mchar;
|
||||
if (want >= ModeManager::UserModes.size())
|
||||
ModeManager::UserModes.resize(want + 1);
|
||||
ModeManager::UserModes[want] = um;
|
||||
if (want >= UserModesIdx.size())
|
||||
UserModesIdx.resize(want + 1);
|
||||
UserModesIdx[want] = um;
|
||||
|
||||
UserModesByName[um->name] = um;
|
||||
|
||||
UserModes.push_back(um);
|
||||
|
||||
FOREACH_MOD(OnUserModeAdd, (um));
|
||||
|
||||
return true;
|
||||
@@ -342,7 +410,9 @@ bool ModeManager::AddUserMode(UserMode *um)
|
||||
|
||||
bool ModeManager::AddChannelMode(ChannelMode *cm)
|
||||
{
|
||||
if (ModeManager::FindChannelModeByChar(cm->mchar) != NULL)
|
||||
if (cm->mchar && ModeManager::FindChannelModeByChar(cm->mchar) != NULL)
|
||||
return false;
|
||||
if (ModeManager::FindChannelModeByName(cm->name) != NULL)
|
||||
return false;
|
||||
|
||||
if (cm->name.empty())
|
||||
@@ -351,24 +421,29 @@ bool ModeManager::AddChannelMode(ChannelMode *cm)
|
||||
Log() << "ModeManager: Added generic support for channel mode " << cm->mchar;
|
||||
}
|
||||
|
||||
unsigned want = cm->mchar;
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
ModeManager::ChannelModes.resize(want + 1);
|
||||
ModeManager::ChannelModes[want] = cm;
|
||||
if (cm->mchar)
|
||||
{
|
||||
unsigned want = cm->mchar;
|
||||
if (want >= ChannelModesIdx.size())
|
||||
ChannelModesIdx.resize(want + 1);
|
||||
ChannelModesIdx[want] = cm;
|
||||
}
|
||||
|
||||
if (cm->type == MODE_STATUS)
|
||||
{
|
||||
ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
|
||||
want = cms->symbol;
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
ModeManager::ChannelModes.resize(want + 1);
|
||||
ModeManager::ChannelModes[want] = cms;
|
||||
unsigned want = cms->symbol;
|
||||
if (want >= ChannelModesIdx.size())
|
||||
ChannelModesIdx.resize(want + 1);
|
||||
ChannelModesIdx[want] = cms;
|
||||
|
||||
RebuildStatusModes();
|
||||
}
|
||||
|
||||
ChannelModesByName[cm->name] = cm;
|
||||
|
||||
ChannelModes.push_back(cm);
|
||||
|
||||
FOREACH_MOD(OnChannelModeAdd, (cm));
|
||||
|
||||
return true;
|
||||
@@ -378,18 +453,22 @@ void ModeManager::RemoveUserMode(UserMode *um)
|
||||
{
|
||||
if (!um)
|
||||
return;
|
||||
|
||||
|
||||
unsigned want = um->mchar;
|
||||
if (want >= ModeManager::UserModes.size())
|
||||
if (want >= UserModesIdx.size())
|
||||
return;
|
||||
|
||||
if (ModeManager::UserModes[want] != um)
|
||||
if (UserModesIdx[want] != um)
|
||||
return;
|
||||
|
||||
ModeManager::UserModes[want] = NULL;
|
||||
UserModesIdx[want] = NULL;
|
||||
|
||||
UserModesByName.erase(um->name);
|
||||
|
||||
std::vector<UserMode *>::iterator it = std::find(UserModes.begin(), UserModes.end(), um);
|
||||
if (it != UserModes.end())
|
||||
UserModes.erase(it);
|
||||
|
||||
StackerDel(um);
|
||||
}
|
||||
|
||||
@@ -397,53 +476,60 @@ void ModeManager::RemoveChannelMode(ChannelMode *cm)
|
||||
{
|
||||
if (!cm)
|
||||
return;
|
||||
|
||||
if (cm->mchar)
|
||||
{
|
||||
unsigned want = cm->mchar;
|
||||
if (want >= ChannelModesIdx.size())
|
||||
return;
|
||||
|
||||
unsigned want = cm->mchar;
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
return;
|
||||
if (ChannelModesIdx[want] != cm)
|
||||
return;
|
||||
|
||||
if (ModeManager::ChannelModes[want] != cm)
|
||||
return;
|
||||
|
||||
ModeManager::ChannelModes[want] = NULL;
|
||||
ChannelModesIdx[want] = NULL;
|
||||
}
|
||||
|
||||
if (cm->type == MODE_STATUS)
|
||||
{
|
||||
ChannelModeStatus *cms = anope_dynamic_static_cast<ChannelModeStatus *>(cm);
|
||||
want = cms->symbol;
|
||||
unsigned want = cms->symbol;
|
||||
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
if (want >= ChannelModesIdx.size())
|
||||
return;
|
||||
|
||||
if (ModeManager::ChannelModes[want] != cm)
|
||||
if (ChannelModesIdx[want] != cm)
|
||||
return;
|
||||
|
||||
ModeManager::ChannelModes[want] = NULL;
|
||||
ChannelModesIdx[want] = NULL;
|
||||
|
||||
RebuildStatusModes();
|
||||
}
|
||||
|
||||
ChannelModesByName.erase(cm->name);
|
||||
|
||||
std::vector<ChannelMode *>::iterator it = std::find(ChannelModes.begin(), ChannelModes.end(), cm);
|
||||
if (it != ChannelModes.end())
|
||||
ChannelModes.erase(it);
|
||||
|
||||
StackerDel(cm);
|
||||
}
|
||||
|
||||
ChannelMode *ModeManager::FindChannelModeByChar(char mode)
|
||||
{
|
||||
unsigned want = mode;
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
if (want >= ChannelModesIdx.size())
|
||||
return NULL;
|
||||
|
||||
return ModeManager::ChannelModes[want];
|
||||
return ChannelModesIdx[want];
|
||||
}
|
||||
|
||||
UserMode *ModeManager::FindUserModeByChar(char mode)
|
||||
{
|
||||
unsigned want = mode;
|
||||
if (want >= ModeManager::UserModes.size())
|
||||
if (want >= UserModesIdx.size())
|
||||
return NULL;
|
||||
|
||||
return ModeManager::UserModes[want];
|
||||
return UserModesIdx[want];
|
||||
}
|
||||
|
||||
ChannelMode *ModeManager::FindChannelModeByName(const Anope::string &name)
|
||||
@@ -465,10 +551,10 @@ UserMode *ModeManager::FindUserModeByName(const Anope::string &name)
|
||||
char ModeManager::GetStatusChar(char value)
|
||||
{
|
||||
unsigned want = value;
|
||||
if (want >= ModeManager::ChannelModes.size())
|
||||
if (want >= ChannelModesIdx.size())
|
||||
return 0;
|
||||
|
||||
ChannelMode *cm = ModeManager::ChannelModes[want];
|
||||
ChannelMode *cm = ChannelModesIdx[want];
|
||||
if (cm == NULL || cm->type != MODE_STATUS || cm->mchar == value)
|
||||
return 0;
|
||||
|
||||
@@ -505,7 +591,7 @@ void ModeManager::RebuildStatusModes()
|
||||
{
|
||||
ChannelMode *cm = ModeManager::GetChannelModes()[j];
|
||||
|
||||
if (cm && cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end())
|
||||
if (cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end())
|
||||
ChannelModesByStatus.push_back(anope_dynamic_static_cast<ChannelModeStatus *>(cm));
|
||||
}
|
||||
std::sort(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), statuscmp);
|
||||
|
||||
Reference in New Issue
Block a user