From f36915790674275627cf8eb68024e17539ee04fa Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 11 Apr 2014 16:10:30 -0400 Subject: Use OnChanRegistered instead of OnCreateChan to set default mlocks. Because OnCreateChan is called from ChannelInfo's constructor, during DB loading it could cause mode locks to be unserialized without having all channels loaded, which breaks things. --- modules/commands/cs_mode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index a13610d23..941a6d183 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -951,7 +951,7 @@ class CSMode : public Module } } - void OnCreateChan(ChannelInfo *ci) anope_override + void OnChanRegistered(ChannelInfo *ci) anope_override { ModeLocks *ml = modelocks.Require(ci); Anope::string mlock; -- cgit From 72b26043b2f1729a2d183b01310747303fe385fd Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 18 Apr 2014 02:21:06 -0400 Subject: Remove unused event. Mark some oper only usermodes as oper only. Fix reading SID in TS6_SID_Retrieve --- include/modules.h | 7 +------ modules/protocol/hybrid.cpp | 2 +- modules/protocol/plexus.cpp | 4 ++-- modules/protocol/ratbox.cpp | 2 +- src/servers.cpp | 2 +- 5 files changed, 6 insertions(+), 11 deletions(-) diff --git a/include/modules.h b/include/modules.h index 0d121089a..90dd23807 100644 --- a/include/modules.h +++ b/include/modules.h @@ -719,11 +719,6 @@ class CoreExport Module : public Extensible */ virtual void OnNickDrop(CommandSource &source, NickAlias *na) { throw NotImplementedException(); } - /** Called when a nick is forbidden - * @param na The nick alias of the forbidden nick - */ - virtual void OnNickForbidden(NickAlias *na) { throw NotImplementedException(); } - /** Called when a user groups their nick * @param u The user grouping * @param target The target they're grouping to @@ -1094,7 +1089,7 @@ enum Implementation I_OnPreUserLogoff, I_OnPostUserLogoff, I_OnBotCreate, I_OnBotChange, I_OnBotDelete, I_OnAccessDel, I_OnAccessAdd, I_OnAccessClear, I_OnLevelChange, I_OnChanDrop, I_OnChanRegistered, I_OnChanSuspend, I_OnChanUnsuspend, I_OnCreateChan, I_OnDelChan, I_OnChannelCreate, I_OnChannelDelete, I_OnAkickAdd, I_OnAkickDel, I_OnCheckKick, - I_OnChanInfo, I_OnCheckPriv, I_OnGroupCheckPriv, I_OnNickDrop, I_OnNickForbidden, I_OnNickGroup, I_OnNickIdentify, + I_OnChanInfo, I_OnCheckPriv, I_OnGroupCheckPriv, I_OnNickDrop, I_OnNickGroup, I_OnNickIdentify, I_OnUserLogin, I_OnNickLogout, I_OnNickRegister, I_OnNickSuspend, I_OnNickUnsuspended, I_OnDelNick, I_OnNickCoreCreate, I_OnDelCore, I_OnChangeCoreDisplay, I_OnNickClearAccess, I_OnNickAddAccess, I_OnNickEraseAccess, I_OnNickClearCert, I_OnNickAddCert, I_OnNickEraseCert, I_OnNickInfo, I_OnBotInfo, I_OnCheckAuthentication, I_OnNickUpdate, diff --git a/modules/protocol/hybrid.cpp b/modules/protocol/hybrid.cpp index 9d928a106..84f7db001 100644 --- a/modules/protocol/hybrid.cpp +++ b/modules/protocol/hybrid.cpp @@ -610,7 +610,7 @@ class ProtoHybrid : public Module ModeManager::AddUserMode(new UserModeOperOnly("CALLERID", 'g')); ModeManager::AddUserMode(new UserMode("INVIS", 'i')); ModeManager::AddUserMode(new UserModeOperOnly("LOCOPS", 'l')); - ModeManager::AddUserMode(new UserMode("OPER", 'o')); + ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o')); ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'r')); ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's')); ModeManager::AddUserMode(new UserMode("WALLOPS", 'w')); diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index 0770d20a4..04d90be7e 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -333,10 +333,10 @@ class ProtoPlexus : public Module ModeManager::AddUserMode(new UserMode("CALLERID", 'g')); ModeManager::AddUserMode(new UserMode("INVIS", 'i')); ModeManager::AddUserMode(new UserModeOperOnly("LOCOPS", 'l')); - ModeManager::AddUserMode(new UserMode("OPER", 'o')); + ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o')); ModeManager::AddUserMode(new UserModeOperOnly("NETADMIN", 'N')); ModeManager::AddUserMode(new UserMode("PRIV", 'p')); - ModeManager::AddUserMode(new UserMode("ROUTING", 'q')); + ModeManager::AddUserMode(new UserModeOperOnly("ROUTING", 'q')); ModeManager::AddUserMode(new UserModeNoone("REGISTERED", 'r')); ModeManager::AddUserMode(new UserMode("REGPRIV", 'R')); ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's')); diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index 89e0f0176..8fd9a30cf 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -253,7 +253,7 @@ class ProtoRatbox : public Module // k = skill? ModeManager::AddUserMode(new UserModeOperOnly("LOCOPS", 'l')); // n = nchange - ModeManager::AddUserMode(new UserMode("OPER", 'o')); + ModeManager::AddUserMode(new UserModeOperOnly("OPER", 'o')); // r = rej ModeManager::AddUserMode(new UserModeOperOnly("SNOMASK", 's')); ModeManager::AddUserMode(new UserModeNoone("PROTECTED", 'S')); diff --git a/src/servers.cpp b/src/servers.cpp index 3f698815c..e1b66baa8 100644 --- a/src/servers.cpp +++ b/src/servers.cpp @@ -385,7 +385,7 @@ const Anope::string Servers::TS6_SID_Retrieve() if (!IRCD || !IRCD->RequiresID) return ""; - static Anope::string current_sid = Config->GetBlock("options")->Get("id"); + static Anope::string current_sid = Config->GetBlock("serverinfo")->Get("id"); if (current_sid.empty()) current_sid = "00A"; -- cgit From e36f8143e3bdf136dd6b6d43d1187500c3db6c43 Mon Sep 17 00:00:00 2001 From: Attila Molnar Date: Sat, 19 Apr 2014 14:35:50 +0200 Subject: Fix SVSNICK target being a nick even when UIDs are available --- src/protocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol.cpp b/src/protocol.cpp index b90c44400..89e4a3c86 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -276,7 +276,7 @@ void IRCDProto::SendNickChange(User *u, const Anope::string &newnick) void IRCDProto::SendForceNickChange(User *u, const Anope::string &newnick, time_t when) { - UplinkSocket::Message() << "SVSNICK " << u->nick << " " << newnick << " " << when; + UplinkSocket::Message() << "SVSNICK " << u->GetUID() << " " << newnick << " " << when; } void IRCDProto::SendCTCP(const MessageSource &source, const Anope::string &dest, const char *fmt, ...) -- cgit From d52cc7bcbcf9b99a58eedc823418a91f85e8cab9 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 24 Apr 2014 01:24:05 -0400 Subject: Bug #1587 - fix bot change not properly reintroducing clients --- modules/commands/bs_bot.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/modules/commands/bs_bot.cpp b/modules/commands/bs_bot.cpp index e25ba8ff0..69fa7f8fe 100644 --- a/modules/commands/bs_bot.cpp +++ b/modules/commands/bs_bot.cpp @@ -189,7 +189,10 @@ class CommandBSBot : public Command } if (!user.empty()) + { IRCD->SendQuit(bi, "Quit: Be right back"); + bi->introduced = false; + } else IRCD->SendNickChange(bi, nick); @@ -204,18 +207,7 @@ class CommandBSBot : public Command bi->realname = real; if (!user.empty()) - { - IRCD->SendClientIntroduction(bi); - unsigned minusers = Config->GetBlock("botserv")->Get("minusers"); - const std::set &channels = bi->GetChannels(); - for (std::set::const_iterator it = channels.begin(), it_end = channels.end(); it != it_end; ++it) - { - const ChannelInfo *ci = *it; - - if (ci->c && ci->c->users.size() >= minusers) - bi->Join(ci->c); - } - } + bi->OnKill(); source.Reply(_("Bot \002%s\002 has been changed to %s!%s@%s (%s)."), oldnick.c_str(), bi->nick.c_str(), bi->GetIdent().c_str(), bi->host.c_str(), bi->realname.c_str()); Log(LOG_ADMIN, source, this) << "CHANGE " << oldnick << " to " << bi->GetMask() << " " << bi->realname; -- cgit From 00b2cc9ce6b9e4d4869d986ada1cf64d22b95455 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 24 Apr 2014 01:38:45 -0400 Subject: Require at least user@host format for akills. Fix XLine::GetHost() not returning anything if an xline only has a host --- modules/commands/os_akill.cpp | 5 +++++ src/xline.cpp | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/commands/os_akill.cpp b/modules/commands/os_akill.cpp index c81a6b515..af8573752 100644 --- a/modules/commands/os_akill.cpp +++ b/modules/commands/os_akill.cpp @@ -160,6 +160,11 @@ class CommandOSAKill : public Command source.Reply(USERHOST_MASK_TOO_WIDE, mask.c_str()); return; } + else if (mask.find('@') == Anope::string::npos) + { + source.Reply(BAD_USERHOST_MASK); + return; + } if (Config->GetModule("operserv")->Get("addakiller", "yes") && !source.GetNick().empty()) reason = "[" + source.GetNick() + "] " + reason; diff --git a/src/xline.cpp b/src/xline.cpp index ea74ba8c7..6b3ba90f4 100644 --- a/src/xline.cpp +++ b/src/xline.cpp @@ -103,7 +103,12 @@ Anope::string XLine::GetHost() const return this->mask.substr(host_t + 1); } else - return ""; + { + if (real_t != Anope::string::npos) + return this->mask.substr(0, real_t); + else + return this->mask; + } } Anope::string XLine::GetReal() const -- cgit From f010ab7dbf020ae218dbd7390af4bcff4bac6fbe Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 24 Apr 2014 01:40:56 -0400 Subject: Resend ircd login name on /ns set display --- modules/commands/ns_set.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/commands/ns_set.cpp b/modules/commands/ns_set.cpp index 063b7c4dd..e8abf762f 100644 --- a/modules/commands/ns_set.cpp +++ b/modules/commands/ns_set.cpp @@ -330,7 +330,7 @@ class CommandNSSetDisplay : public Command return; } - const NickAlias *user_na = NickAlias::Find(user), *na = NickAlias::Find(param); + NickAlias *user_na = NickAlias::Find(user), *na = NickAlias::Find(param); if (Config->GetModule("nickserv")->Get("nonicknameownership")) { @@ -356,6 +356,8 @@ class CommandNSSetDisplay : public Command Log(user_na->nc == source.GetAccount() ? LOG_COMMAND : LOG_ADMIN, source, this) << "to change the display of " << user_na->nc->display << " to " << na->nick; user_na->nc->SetDisplay(na); + if (source.GetUser()) + IRCD->SendLogin(source.GetUser(), na); source.Reply(NICK_SET_DISPLAY_CHANGED, user_na->nc->display.c_str()); } -- cgit From 75ed5a9b59dd29b2e63d502eb3425696d93765fd Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 24 Apr 2014 01:50:50 -0400 Subject: Fix os_stats counters not saving with db_sql_live. Bleh. --- modules/commands/os_stats.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/commands/os_stats.cpp b/modules/commands/os_stats.cpp index 85088f385..bd868b903 100644 --- a/modules/commands/os_stats.cpp +++ b/modules/commands/os_stats.cpp @@ -258,6 +258,12 @@ class OSStats : public Module { } + + void OnUserConnect(User *u, bool &exempt) anope_override + { + if (UserListByNick.size() == MaxUserCount && Anope::CurTime == MaxUserTime) + stats_saver.QueueUpdate(); + } }; MODULE_INIT(OSStats) -- cgit From c9473bcc67e0259b0aa79c95424e6fc044777ccc Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 24 Apr 2014 17:10:06 -0400 Subject: Fix botserv/kick/bolds desc --- modules/commands/bs_kick.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/commands/bs_kick.cpp b/modules/commands/bs_kick.cpp index c08376e3c..f3f000474 100644 --- a/modules/commands/bs_kick.cpp +++ b/modules/commands/bs_kick.cpp @@ -325,7 +325,7 @@ class CommandBSKickBolds : public CommandBSKickBase public: CommandBSKickBolds(Module *creator) : CommandBSKickBase(creator, "botserv/kick/bolds", 2, 3) { - this->SetDesc(_("Configures badwords kicker")); + this->SetDesc(_("Configures bolds kicker")); this->SetSyntax(_("\037channel\037 {\037ON|OFF\037} [\037ttb\037]")); } -- cgit From 2ab4f175a8ff96355bbb58302eee87138577a3c5 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Apr 2014 16:20:23 -0400 Subject: Don't allow users to join channels they are already in --- src/messages.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/messages.cpp b/src/messages.cpp index bb699a18e..97f0dd968 100644 --- a/src/messages.cpp +++ b/src/messages.cpp @@ -128,6 +128,9 @@ void Join::SJoin(MessageSource &source, const Anope::string &chan, time_t ts, co User *u = it->second; keep_their_modes = ts <= c->creation_time; // OnJoinChannel can call modules which can modify this channel's ts + if (c->FindUser(u)) + continue; + /* Add the user to the channel */ c->JoinUser(u, keep_their_modes ? &status : NULL); -- cgit From 82008d507cccbf24c73502bc97bc492d21305549 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Apr 2014 16:46:37 -0400 Subject: Fix Stas::Unserialize to return the instance --- modules/commands/os_stats.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/commands/os_stats.cpp b/modules/commands/os_stats.cpp index bd868b903..baa349db4 100644 --- a/modules/commands/os_stats.cpp +++ b/modules/commands/os_stats.cpp @@ -14,7 +14,12 @@ struct Stats : Serializable { - Stats() : Serializable("Stats") { } + static Stats *me; + + Stats() : Serializable("Stats") + { + me = this; + } void Serialize(Serialize::Data &data) const anope_override { @@ -26,7 +31,7 @@ struct Stats : Serializable { data["maxusercnt"] >> MaxUserCount; data["maxusertime"] >> MaxUserTime; - return NULL; + return me; } }; -- cgit From 4fa2a00bd595eb120e6acde5eb167759c2018e33 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Apr 2014 16:47:10 -0400 Subject: Close timed out proxyscan sockets better --- modules/m_proxyscan.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/m_proxyscan.cpp b/modules/m_proxyscan.cpp index 98178260c..0fe4ade27 100644 --- a/modules/m_proxyscan.cpp +++ b/modules/m_proxyscan.cpp @@ -206,12 +206,13 @@ class ModuleProxyScan : public Module void Tick(time_t) anope_override { - for (std::set::iterator it = ProxyConnect::proxies.begin(), it_end = ProxyConnect::proxies.end(); it != it_end; ++it) + for (std::set::iterator it = ProxyConnect::proxies.begin(), it_end = ProxyConnect::proxies.end(); it != it_end;) { ProxyConnect *p = *it; + ++it; if (p->created + this->GetSecs() < Anope::CurTime) - p->flags[SF_DEAD] = true; + delete p; } } } connectionTimeout; -- cgit From 6a03eb69ebbe773f1d4139ff88d74ecdb2b0af4b Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 25 Apr 2014 16:51:06 -0400 Subject: 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 --- data/botserv.example.conf | 1 + data/chanserv.example.conf | 6 + include/channels.h | 3 +- include/config.h | 2 + include/modes.h | 41 ++++-- modules/commands/cs_ban.cpp | 47 ++++--- modules/commands/cs_mode.cpp | 3 +- modules/commands/cs_unban.cpp | 15 ++- modules/protocol/inspircd20.cpp | 195 +++++++++++++++++++++++------ modules/protocol/unreal.cpp | 124 ++++++++++++++---- modules/webcpanel/pages/chanserv/modes.cpp | 2 +- src/channels.cpp | 38 ++++-- src/config.cpp | 15 +++ src/modes.cpp | 160 +++++++++++++++++------ 14 files changed, 507 insertions(+), 145 deletions(-) diff --git a/data/botserv.example.conf b/data/botserv.example.conf index c341eceb3..6cb44afc3 100644 --- a/data/botserv.example.conf +++ b/data/botserv.example.conf @@ -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"; } diff --git a/data/chanserv.example.conf b/data/chanserv.example.conf index dba4466eb..d4a2f841c 100644 --- a/data/chanserv.example.conf +++ b/data/chanserv.example.conf @@ -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" } diff --git a/include/channels.h b/include/channels.h index 27119adf4..cc30d2030 100644 --- a/include/channels.h +++ b/include/channels.h @@ -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 diff --git a/include/config.h b/include/config.h index 86a7dce78..019564680 100644 --- a/include/config.h +++ b/include/config.h @@ -138,6 +138,8 @@ namespace Configuration Block *GetModule(const Anope::string &name); BotInfo *GetClient(const Anope::string &name); + + Block *GetCommand(CommandSource &); }; struct Uplink diff --git a/include/modes.h b/include/modes.h index 8f67959e8..3ba54c439 100644 --- a/include/modes.h +++ b/include/modes.h @@ -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 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 +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 ChannelModes; - static std::vector UserModes; - public: /* Number of generic channel and user modes we are tracking */ diff --git a/modules/commands/cs_ban.cpp b/modules/commands/cs_ban.cpp index 0395ddd92..648e379e3 100644 --- a/modules/commands/cs_ban.cpp +++ b/modules/commands/cs_ban.cpp @@ -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 ¶ms) anope_override { const Anope::string &chan = params[0]; + Configuration::Block *block = Config->GetCommand(source); + const Anope::string &mode = block->Get("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("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("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()); + } } } diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index 941a6d183..2943c64a3 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -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)) diff --git a/modules/commands/cs_unban.cpp b/modules/commands/cs_unban.cpp index 56a482985..9fd6400a8 100644 --- a/modules/commands/cs_unban.cpp +++ b/modules/commands/cs_unban.cpp @@ -22,6 +22,13 @@ class CommandCSUnban : public Command void Execute(CommandSource &source, const std::vector ¶ms) anope_override { + ChannelMode *cm = ModeManager::FindChannelModeByName("BAN"); + if (!cm) + return; + + std::vector 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 diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index 4e88d01a8..1e439da30 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -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 { + char ext; + public: - InspIRCdExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { } + InspIRCdExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual(mname, basename) + , ext(extban) + { + } + + ChannelMode *Wrap(Anope::string ¶m) anope_override + { + param = Anope::string(ext) + ":" + param; + return ChannelModeVirtual::Wrap(param); + } - bool Matches(User *u, const Entry *e) anope_override + ChannelMode *Unwrap(ChannelMode *cm, Anope::string ¶m) anope_override { - const Anope::string &mask = e->GetMask(); + if (cm->type != MODE_LIST || param.length() < 3 || param[0] != ext || param[1] != ':') + return cm; - if (mask.find("m:") == 0 || mask.find("N:") == 0) + 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); + } + }; + + class ChannelMatcher : public InspIRCdExtBan + { + public: + ChannelMatcher(const Anope::string &mname, const Anope::string &mbase, char c) : InspIRCdExtBan(mname, mbase, c) + { } - else if (mask.find("j:") == 0) + + 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; } - } - else if (mask.find("R:") == 0) - { - Anope::string real_mask = mask.substr(2); - if (u->IsIdentified() && real_mask.equals_ci(u->Account()->display)) - return true; + return false; } - else if (mask.find("r:") == 0) - { - Anope::string real_mask = mask.substr(2); + }; - if (Anope::Match(u->realname, real_mask)) - return true; - } - else if (mask.find("s:") == 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 (Anope::Match(u->server->GetName(), real_mask)) - return true; + return u->IsIdentified() && real_mask.equals_ci(u->Account()->display); } - 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; + 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) + { } - return false; - } -}; + bool Matches(User *u, const Entry *e) anope_override + { + const Anope::string &mask = e->GetMask(); + Anope::string real_mask = mask.substr(2); + return !u->Account() && Entry("BAN", real_mask).Matches(u); + } + }; +} 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) diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp index d7bc8fa14..f444947f6 100644 --- a/modules/protocol/unreal.cpp +++ b/modules/protocol/unreal.cpp @@ -415,17 +415,44 @@ class UnrealIRCdProto : public IRCDProto } }; -class UnrealExtBan : public ChannelModeList +class UnrealExtBan : public ChannelModeVirtual { + char ext; + public: - UnrealExtBan(const Anope::string &mname, char modeChar) : ChannelModeList(mname, modeChar) { } + UnrealExtBan(const Anope::string &mname, const Anope::string &basename, char extban) : ChannelModeVirtual(mname, basename) + , ext(extban) + { + } + + ChannelMode *Wrap(Anope::string ¶m) anope_override + { + param = "~" + Anope::string(ext) + ":" + param; + return ChannelModeVirtual::Wrap(param); + } - bool Matches(User *u, const Entry *e) anope_override + ChannelMode *Unwrap(ChannelMode *cm, Anope::string ¶m) anope_override { - const Anope::string &mask = e->GetMask(); + if (cm->type != MODE_LIST || param.length() < 4 || param[0] != '~' || param[1] != ext || param[2] != ':') + return cm; - if (mask.find("~c:") == 0) + 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])); diff --git a/modules/webcpanel/pages/chanserv/modes.cpp b/modules/webcpanel/pages/chanserv/modes.cpp index f087b86a9..a11d42fd9 100644 --- a/modules/webcpanel/pages/chanserv/modes.cpp +++ b/modules/webcpanel/pages/chanserv/modes.cpp @@ -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; } diff --git a/src/channels.cpp b/src/channels.cpp index 37d04c44e..b705c8584 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -248,11 +248,14 @@ std::pair 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 bans = this->GetModeList("BAN"); + std::pair 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; } } diff --git a/src/config.cpp b/src/config.cpp index e402080db..110045786 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -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 iters = blocks.equal_range(block_name); iters.first != iters.second; ++iters.first) + { + Block *b = &iters.first->second; + + if (b->Get("name") == source.command) + return b; + } + + return NULL; +} + File::File(const Anope::string &n, bool e) : name(n), executable(e), fp(NULL) { } diff --git a/src/modes.cpp b/src/modes.cpp index 13cda797f..891dcf6a8 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -21,9 +21,15 @@ struct StackerInfo; static std::map UserStackerObjects; static std::map ChannelStackerObjects; -/* List of all modes Anope knows about */ -std::vector ModeManager::ChannelModes; -std::vector ModeManager::UserModes; +/* Array of all modes Anope knows about.*/ +static std::vector ChannelModes; +static std::vector UserModes; + +/* Modes are in this array are at position + * modechar. Additionally, status modes are in this array (again) at statuschar. + */ +static std::vector ChannelModesIdx; +static std::vector UserModesIdx; static std::map ChannelModesByName; static std::map 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 +ChannelModeVirtual::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 +ChannelModeVirtual::~ChannelModeVirtual() +{ + if (basech) + { + std::vector::iterator it = std::find(basech->listeners.begin(), basech->listeners.end(), this); + if (it != basech->listeners.end()) + basech->listeners.erase(it); + } +} + +template +ChannelMode *ChannelModeVirtual::Wrap(Anope::string ¶m) +{ + if (basech == NULL) + { + basech = ModeManager::FindChannelModeByName(base); + if (basech) + basech->listeners.push_back(this); + } + + return basech; +} + +template class ChannelModeVirtual; +template class ChannelModeVirtual; + 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(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::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 (ModeManager::ChannelModes[want] != cm) - return; + if (ChannelModesIdx[want] != cm) + return; - ModeManager::ChannelModes[want] = NULL; + ChannelModesIdx[want] = NULL; + } if (cm->type == MODE_STATUS) { ChannelModeStatus *cms = anope_dynamic_static_cast(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::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(cm)); } std::sort(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), statuscmp); -- cgit From 4eb0a3bdb73874aa87095f566677166764ef1ccc Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 26 Apr 2014 15:24:19 -0400 Subject: Fix ModeManager::RebuildStatusModes, not all modes are in GetChannelModes() at the time this is called --- src/modes.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modes.cpp b/src/modes.cpp index 891dcf6a8..668f7c150 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -587,11 +587,11 @@ static struct StatusSort void ModeManager::RebuildStatusModes() { ChannelModesByStatus.clear(); - for (unsigned j = 0; j < ModeManager::GetChannelModes().size(); ++j) + for (unsigned j = 0; j < ChannelModesIdx.size(); ++j) { - ChannelMode *cm = ModeManager::GetChannelModes()[j]; + ChannelMode *cm = ChannelModesIdx[j]; - if (cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end()) + if (cm && cm->type == MODE_STATUS && std::find(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), cm) == ChannelModesByStatus.end()) ChannelModesByStatus.push_back(anope_dynamic_static_cast(cm)); } std::sort(ChannelModesByStatus.begin(), ChannelModesByStatus.end(), statuscmp); -- cgit From 3abb18721bf969157110ad4bb8e4b3ea26dde8e8 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 26 Apr 2014 17:21:33 -0400 Subject: Accept non server sources for SQUIT --- include/messages.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/messages.h b/include/messages.h index e805903b3..3bf096d7c 100644 --- a/include/messages.h +++ b/include/messages.h @@ -131,7 +131,7 @@ namespace Message struct CoreExport SQuit : IRCDMessage { - SQuit(Module *creator, const Anope::string &mname = "SQUIT") : IRCDMessage(creator, mname, 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + SQuit(Module *creator, const Anope::string &mname = "SQUIT") : IRCDMessage(creator, mname, 2) { } void Run(MessageSource &source, const std::vector ¶ms) anope_override; }; -- cgit From 2ee496b8ac2aff980103237331514f31b7fdc039 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 26 Apr 2014 17:30:58 -0400 Subject: Change the "does not expire" string in ns_group to NO_EXPIRE which is translatable --- modules/commands/ns_group.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/commands/ns_group.cpp b/modules/commands/ns_group.cpp index 04842b3e3..9b3f425e9 100644 --- a/modules/commands/ns_group.cpp +++ b/modules/commands/ns_group.cpp @@ -321,7 +321,7 @@ class CommandNSGList : public Command Anope::string expires; if (na2->HasExt("NS_NO_EXPIRE")) - expires = "Does not expire"; + expires = NO_EXPIRE; else if (!nickserv_expire || Anope::NoExpire) ; else if (na2->nc->HasExt("UNCONFIRMED") && unconfirmed_expire) -- cgit From 0663f5e41296df36c196425f72516e7dad7c8f2d Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 26 Apr 2014 17:45:16 -0400 Subject: Fire the on user quit event when bots are deleted too --- src/bots.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bots.cpp b/src/bots.cpp index 77b7d1c35..9ce918a91 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -55,6 +55,7 @@ BotInfo::~BotInfo() if (Me && Me->IsSynced()) { IRCD->SendQuit(this, ""); + FOREACH_MOD(OnUserQuit, (this, "")); this->introduced = false; XLine x(this->nick); IRCD->SendSQLineDel(&x); -- cgit From 8021a53ac47d95f874cc50bd2a0a73715164fae3 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 26 Apr 2014 18:30:54 -0400 Subject: Fix misc help output to not be case sensitive --- modules/commands/cs_set_misc.cpp | 2 +- modules/commands/ns_set_misc.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/commands/cs_set_misc.cpp b/modules/commands/cs_set_misc.cpp index 481b54cb9..81b8c72fa 100644 --- a/modules/commands/cs_set_misc.cpp +++ b/modules/commands/cs_set_misc.cpp @@ -13,7 +13,7 @@ static Module *me; -static std::map descriptions; +static Anope::map descriptions; struct CSMiscData; static Anope::map *> items; diff --git a/modules/commands/ns_set_misc.cpp b/modules/commands/ns_set_misc.cpp index 496e3a4e2..455a651fb 100644 --- a/modules/commands/ns_set_misc.cpp +++ b/modules/commands/ns_set_misc.cpp @@ -14,7 +14,7 @@ static Module *me; -static std::map descriptions; +static Anope::map descriptions; struct NSMiscData; static Anope::map *> items; -- cgit From 0afd666f22f1f6a593c2cb9b63de60e4ce4e7113 Mon Sep 17 00:00:00 2001 From: Attila Molnar Date: Tue, 29 Apr 2014 22:55:10 +0200 Subject: InspIRCd 2.0: Recognize GLOBOPS in CAPAB CAPABILITIES --- modules/protocol/inspircd20.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index 1e439da30..07c25972c 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -702,6 +702,8 @@ struct IRCDMessageCapab : Message::Capab ModeManager::RebuildStatusModes(); } + else if (capab == "GLOBOPS=1") + Servers::Capab.insert("GLOBOPS"); } } else if (params[0].equals_cs("END")) -- cgit From 3049916ade0c31c2edf2fca98456bccc14d06270 Mon Sep 17 00:00:00 2001 From: Attila Molnar Date: Wed, 30 Apr 2014 01:15:10 +0200 Subject: Fix undefined symbol error when loading os_stats, caused by 82008d507cccbf24c73502bc97bc492d21305549 --- modules/commands/os_stats.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/commands/os_stats.cpp b/modules/commands/os_stats.cpp index baa349db4..e5cae1dcc 100644 --- a/modules/commands/os_stats.cpp +++ b/modules/commands/os_stats.cpp @@ -35,6 +35,8 @@ struct Stats : Serializable } }; +Stats *Stats::me; + /** * Count servers connected to server s * @param s The server to start counting from -- cgit From d79dd0b7d705e8f18ae0d6494a8bc65c2b0c2819 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 1 May 2014 18:38:17 -0400 Subject: Pass password to nick register event so modules like m_ldap_authentication can create the respective account using the decrypted password which might not always be available --- include/modules.h | 3 ++- modules/commands/ns_access.cpp | 2 +- modules/commands/ns_register.cpp | 2 +- modules/extra/m_ldap_authentication.cpp | 6 +++--- modules/extra/m_sql_authentication.cpp | 2 +- modules/extra/stats/m_chanstats.cpp | 2 +- 6 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/modules.h b/include/modules.h index 90dd23807..6f7803cff 100644 --- a/include/modules.h +++ b/include/modules.h @@ -743,8 +743,9 @@ class CoreExport Module : public Extensible /** Called when a nick is registered * @param user The user registering the nick, of any * @param The nick + * @param pass The password of the newly registered nick */ - virtual void OnNickRegister(User *user, NickAlias *na) { throw NotImplementedException(); } + virtual void OnNickRegister(User *user, NickAlias *na, const Anope::string &pass) { throw NotImplementedException(); } /** Called when a nick is suspended * @param na The nick alias diff --git a/modules/commands/ns_access.cpp b/modules/commands/ns_access.cpp index dfafdb37f..d01f6dc9b 100644 --- a/modules/commands/ns_access.cpp +++ b/modules/commands/ns_access.cpp @@ -196,7 +196,7 @@ class NSAccess : public Module { } - void OnNickRegister(User *u, NickAlias *na) anope_override + void OnNickRegister(User *u, NickAlias *na, const Anope::string &) anope_override { if (u && Config->GetModule(this)->Get("addaccessonreg")) na->nc->AddAccess(u->Mask()); diff --git a/modules/commands/ns_register.cpp b/modules/commands/ns_register.cpp index c3d678cf1..8e916c4d7 100644 --- a/modules/commands/ns_register.cpp +++ b/modules/commands/ns_register.cpp @@ -198,7 +198,7 @@ class CommandNSRegister : public Command Log(LOG_COMMAND, source, this) << "to register " << na->nick << " (email: " << (!na->nc->email.empty() ? na->nc->email : "none") << ")"; - FOREACH_MOD(OnNickRegister, (source.GetUser(), na)); + FOREACH_MOD(OnNickRegister, (source.GetUser(), na, pass)); if (na->nc->GetAccessCount()) source.Reply(_("Nickname \002%s\002 registered under your user@host-mask: %s"), u_nick.c_str(), na->nc->GetAccess(0).c_str()); diff --git a/modules/extra/m_ldap_authentication.cpp b/modules/extra/m_ldap_authentication.cpp index 7c9593dff..115faa73e 100644 --- a/modules/extra/m_ldap_authentica