diff options
author | Adam <Adam@anope.org> | 2011-03-07 19:54:51 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2011-03-07 19:54:51 -0500 |
commit | 8eb23e7d489239e8af79c2d6da587cd1c3a81b5d (patch) | |
tree | 04bf54ceb46a4b18345cf4e01d8aeb11ccd52c07 | |
parent | 093b3d258e7b14d2aa057ca6113de034b5063efe (diff) |
Added support for extbans
-rw-r--r-- | docs/IRCD | 6 | ||||
-rw-r--r-- | include/modes.h | 48 | ||||
-rw-r--r-- | include/services.h | 8 | ||||
-rw-r--r-- | modules/core/cs_akick.cpp | 2 | ||||
-rw-r--r-- | modules/core/os_ignore.cpp | 2 | ||||
-rw-r--r-- | modules/protocol/bahamut.cpp | 30 | ||||
-rw-r--r-- | modules/protocol/inspircd-ts6.h | 19 | ||||
-rw-r--r-- | modules/protocol/inspircd11.cpp | 40 | ||||
-rw-r--r-- | modules/protocol/inspircd12.cpp | 73 | ||||
-rw-r--r-- | modules/protocol/inspircd20.cpp | 94 | ||||
-rw-r--r-- | modules/protocol/ngircd.cpp | 4 | ||||
-rw-r--r-- | modules/protocol/plexus.cpp | 8 | ||||
-rw-r--r-- | modules/protocol/ratbox.cpp | 8 | ||||
-rw-r--r-- | modules/protocol/unreal32.cpp | 148 | ||||
-rw-r--r-- | src/actions.cpp | 2 | ||||
-rw-r--r-- | src/bots.cpp | 2 | ||||
-rw-r--r-- | src/channels.cpp | 38 | ||||
-rw-r--r-- | src/main.cpp | 3 | ||||
-rw-r--r-- | src/modes.cpp | 63 | ||||
-rw-r--r-- | src/regchannel.cpp | 2 | ||||
-rw-r--r-- | src/users.cpp | 2 |
21 files changed, 355 insertions, 247 deletions
@@ -147,12 +147,6 @@ How To Add IRCd Support ModeManager::AddChannelMode(new ChannelModeOper('O'));
- The CMODE_FLOOD param also has its own class, but due to the wide range of
- valid parameters accepted across IRCds, your protocol module MUST have the
- IsValid function for this.
-
- bool ChannelModeFlood::IsValid(const Anope::string &value) { }
-
4) Functions and Events
A brief word about functions and events. All events are captured by creating a Message struct
diff --git a/include/modes.h b/include/modes.h index e423b370e..ae89c7ab7 100644 --- a/include/modes.h +++ b/include/modes.h @@ -222,6 +222,14 @@ class CoreExport ChannelModeList : public ChannelMode */ virtual bool IsValid(const Anope::string &mask) const { return true; } + /** Checks if mask affects user + * Should only be used for extbans or other weird ircd-specific things. + * @param u The user + * @param e The entry to match against + * @return true on match + */ + virtual bool Matches(User *u, const Entry *e) { return false; } + /** Called when a mask is added to a channel * @param chan The channel * @param mask The mask @@ -233,7 +241,6 @@ class CoreExport ChannelModeList : public ChannelMode * @param mask The mask */ virtual void OnDel(Channel *chan, const Anope::string &mask) { } - }; /** This is a mode with a paramater, eg +k/l. These modes should use/inherit from this @@ -287,38 +294,11 @@ class CoreExport ChannelModeStatus : public ChannelMode class CoreExport ChannelModeBan : public ChannelModeList { public: - ChannelModeBan(char modeChar) : ChannelModeList(CMODE_BAN, modeChar) { } + ChannelModeBan(ChannelModeName mName, char modeChar) : ChannelModeList(mName, modeChar) { } void OnAdd(Channel *chan, const Anope::string &mask); - - void OnDel(Channel *chan, const Anope::string &mask); }; -/** Channel mode +e - */ -class CoreExport ChannelModeExcept : public ChannelModeList -{ - public: - ChannelModeExcept(char modeChar) : ChannelModeList(CMODE_EXCEPT, modeChar) { } - - void OnAdd(Channel *chan, const Anope::string &mask); - - void OnDel(Channel *chan, const Anope::string &mask); -}; - -/** Channel mode +I - */ -class CoreExport ChannelModeInvex : public ChannelModeList -{ - public: - ChannelModeInvex(char modeChar) : ChannelModeList(CMODE_INVITEOVERRIDE, modeChar) { } - - void OnAdd(Channel *chan, const Anope::string &mask); - - void OnDel(Channel *chan, const Anope::string &mask); -}; - - /** Channel mode +k (key) */ class CoreExport ChannelModeKey : public ChannelModeParam @@ -329,16 +309,6 @@ class CoreExport ChannelModeKey : public ChannelModeParam bool IsValid(const Anope::string &value) const; }; -/** Channel mode +f (flood) - */ -class ChannelModeFlood : public ChannelModeParam -{ - public: - ChannelModeFlood(char modeChar, bool minusNoArg = false) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } - - bool IsValid(const Anope::string &value) const; -}; - /** This class is used for channel mode +A (Admin only) * Only opers can mlock it */ diff --git a/include/services.h b/include/services.h index cc2bdf331..a0beabf2a 100644 --- a/include/services.h +++ b/include/services.h @@ -452,7 +452,7 @@ class BotInfo; class ChannelInfo; class Channel; class Server; -struct EList; +class Entry; struct Session; #include "threadengine.h" @@ -818,16 +818,18 @@ enum EntryType class CoreExport Entry : public Flags<EntryType> { - Anope::string mask; + ChannelModeName modename; public: unsigned char cidr_len; + Anope::string mask; Anope::string nick, user, host; /** Constructor * @param _host A full nick!ident@host/cidr mask + * @param mode What mode this host is for - can be CMODE_BEGIN for unknown/no mode */ - Entry(const Anope::string &_host); + Entry(ChannelModeName mode, const Anope::string &_host); /** Get the banned mask for this entry * @return The mask diff --git a/modules/core/cs_akick.cpp b/modules/core/cs_akick.cpp index 3761e95de..fa8ebe573 100644 --- a/modules/core/cs_akick.cpp +++ b/modules/core/cs_akick.cpp @@ -219,7 +219,7 @@ class CommandCSAKick : public Command ChanAccess *u2_access = ci->GetAccess(nc), *u_access = ci->GetAccess(u); int16 u2_level = u2_access ? u2_access->level : 0, u_level = u_access ? u_access->level : 0; - Entry entry_mask(mask); + Entry entry_mask(CMODE_BEGIN, mask); if ((check_access(u2, ci, CA_FOUNDER) || u2_level >= u_level) && entry_mask.Matches(u2)) { diff --git a/modules/core/os_ignore.cpp b/modules/core/os_ignore.cpp index 5c8883cfe..88c09485a 100644 --- a/modules/core/os_ignore.cpp +++ b/modules/core/os_ignore.cpp @@ -91,7 +91,7 @@ class OSIgnoreService : public IgnoreService { for (; ign != ign_end; ++ign) { - Entry ignore_mask(ign->mask); + Entry ignore_mask(CMODE_BEGIN, ign->mask); if (ignore_mask.Matches(u)) break; } diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index aabe2c904..fa714d7b1 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -410,7 +410,7 @@ class BahamutIRCdMessage : public IRCdMessage ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); if (!cm) { - Log() << "Receeved unknown mode prefix " << buf[0] << " in SJOIN string"; + Log() << "Receeved unknown mode prefix " << cm << " in SJOIN string"; continue; } @@ -528,18 +528,24 @@ bool event_burst(const Anope::string &source, const std::vector<Anope::string> & return true; } -bool ChannelModeFlood::IsValid(const Anope::string &value) const +class ChannelModeFlood : public ChannelModeParam { - try + public: + ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } + + bool IsValid(const Anope::string &value) const { - Anope::string rest; - if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty()) - return true; - } - catch (const ConvertException &) { } + try + { + Anope::string rest; + if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty()) + return true; + } + catch (const ConvertException &) { } - return false; -} + return false; + } +}; class ProtoBahamut : public Module { @@ -562,7 +568,7 @@ class ProtoBahamut : public Module ModeManager::AddUserMode(new UserMode(UMODE_DEAF, 'd')); /* b/e/I */ - ModeManager::AddChannelMode(new ChannelModeBan('b')); + ModeManager::AddChannelMode(new ChannelModeBan(CMODE_BAN, 'b')); /* v/h/o/a/q */ ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); @@ -571,7 +577,7 @@ class ProtoBahamut : public Module /* Add channel modes */ ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, 'c')); ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, 'i')); - ModeManager::AddChannelMode(new ChannelModeFlood('f')); + ModeManager::AddChannelMode(new ChannelModeFlood('f', false)); ModeManager::AddChannelMode(new ChannelModeKey('k')); ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, 'l')); ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, 'm')); diff --git a/modules/protocol/inspircd-ts6.h b/modules/protocol/inspircd-ts6.h index 952268184..dda07f5a2 100644 --- a/modules/protocol/inspircd-ts6.h +++ b/modules/protocol/inspircd-ts6.h @@ -9,6 +9,25 @@ * Based on the original code of Services by Andy Church. */ +class ChannelModeFlood : public ChannelModeParam +{ + public: + ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } + + bool IsValid(const Anope::string &value) const + { + try + { + Anope::string rest; + if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty()) + return true; + } + catch (const ConvertException &) { } + + return false; + } +}; + class InspIRCdTS6Proto : public IRCDProto { private: diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index 9d72eef6c..e903bb2a3 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -264,6 +264,25 @@ class InspIRCdProto : public IRCDProto }; +class ChannelModeFlood : public ChannelModeParam +{ + public: + ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } + + bool IsValid(const Anope::string &value) const + { + try + { + Anope::string rest; + if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty()) + return true; + } + catch (const ConvertException &) { } + + return false; + } +}; + class InspircdIRCdMessage : public IRCdMessage { public: @@ -374,13 +393,13 @@ class InspircdIRCdMessage : public IRCdMessage switch (modebuf[t]) { case 'b': - ModeManager::AddChannelMode(new ChannelModeBan('b')); + ModeManager::AddChannelMode(new ChannelModeBan(CMODE_BAN, 'b')); continue; case 'e': - ModeManager::AddChannelMode(new ChannelModeExcept('e')); + ModeManager::AddChannelMode(new ChannelModeList(CMODE_EXCEPT, 'e')); continue; case 'I': - ModeManager::AddChannelMode(new ChannelModeInvex('I')); + ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I')); continue; default: ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, modebuf[t])); @@ -406,7 +425,7 @@ class InspircdIRCdMessage : public IRCdMessage switch (modebuf[t]) { case 'f': - ModeManager::AddChannelMode(new ChannelModeFlood('f')); + ModeManager::AddChannelMode(new ChannelModeFlood('f', false)); continue; case 'l': ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, 'l', true)); @@ -844,19 +863,6 @@ bool event_endburst(const Anope::string &source, const std::vector<Anope::string return true; } -bool ChannelModeFlood::IsValid(const Anope::string &value) const -{ - try - { - Anope::string rest; - if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty()) - return true; - } - catch (const ConvertException &) { } - - return false; -} - class ProtoInspIRCd : public Module { Message message_endburst, message_rsquit, message_svsmode, message_chghost, message_chgident, message_chgname, diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index 5bdae4b7b..27f692956 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -311,6 +311,60 @@ bool event_endburst(const Anope::string &source, const std::vector<Anope::string return true; } +template<typename T> class InspIRCdExtBan : public T +{ + public: + InspIRCdExtBan(ChannelModeName mName, char modeChar) : T(mName, modeChar) { } + + bool Matches(User *u, const Entry *e) + { + const Anope::string &mask = e->mask; + + if (mask.find("A:") == 0 || mask.find("B:") == 0 || mask.find("c:") == 0 || mask.find("C:") == 0 || + mask.find("m:") == 0 || mask.find("N:") == 0 || mask.find("p:") == 0 || mask.find("Q:") == 0 || + mask.find("N:") == 0 || mask.find("p:") == 0 || mask.find("Q:") == 0 || mask.find("S:") == 0 || + mask.find("T:") == 0) + { + Anope::string real_mask = mask.substr(2); + + Entry en(this->Name, real_mask); + if (en.Matches(u)) + return true; + } + else if (mask.find("j:") == 0) + { + Anope::string real_mask = mask.substr(2); + + Channel *c = findchan(real_mask); + if (c != NULL && c->FindUser(u) != NULL) + return true; + } + else if (mask.find("M:") == 0 || mask.find("R:") == 0) + { + Anope::string real_mask = mask.substr(2); + + if (u->IsIdentified() && real_mask.equals_ci(u->Account()->display)) + return true; + } + 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) + { + Anope::string real_mask = mask.substr(2); + + if (Anope::Match(u->server->GetName(), real_mask)) + return true; + } + + return false; + } +}; + class Inspircd12IRCdMessage : public InspircdIRCdMessage { public: @@ -388,13 +442,13 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage switch (modebuf[t]) { case 'b': - ModeManager::AddChannelMode(new ChannelModeBan('b')); + ModeManager::AddChannelMode(new InspIRCdExtBan<ChannelModeBan>(CMODE_BAN, 'b')); continue; case 'e': - ModeManager::AddChannelMode(new ChannelModeExcept('e')); + ModeManager::AddChannelMode(new InspIRCdExtBan<ChannelModeList>(CMODE_EXCEPT, 'e')); continue; case 'I': - ModeManager::AddChannelMode(new ChannelModeInvex('I')); + ModeManager::AddChannelMode(new InspIRCdExtBan<ChannelModeList>(CMODE_INVITEOVERRIDE, 'I')); continue; /* InspIRCd sends q and a here if they have no prefixes */ case 'q': @@ -675,19 +729,6 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage } }; -bool ChannelModeFlood::IsValid(const Anope::string &value) const -{ - try - { - Anope::string rest; - if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty()) - return true; - } - catch (const CoreException &) { } - - return false; -} - class ProtoInspIRCd : public Module { Message message_endburst, message_time, diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index cbe6b7e60..3bab3ef99 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -321,6 +321,81 @@ bool event_endburst(const Anope::string &source, const std::vector<Anope::string return true; } +template<typename T> class InspIRCdExtBan : public T +{ + public: + InspIRCdExtBan(ChannelModeName mName, char modeChar) : T(mName, modeChar) { } + + bool Matches(User *u, const Entry *e) + { + const Anope::string &mask = e->mask; + + if (mask.find("A:") == 0 || mask.find("B:") == 0 || mask.find("c:") == 0 || mask.find("C:") == 0 || + mask.find("m:") == 0 || mask.find("N:") == 0 || mask.find("p:") == 0 || mask.find("Q:") == 0 || + mask.find("S:") == 0 || mask.find("T:") == 0) + { + Anope::string real_mask = mask.substr(3); + + Entry en(this->Name, real_mask); + if (en.Matches(u)) + return true; + } + else if (mask.find("j:") == 0) + { + Anope::string channel = mask.substr(3); + + ChannelMode *cm = NULL; + if (channel[0] != '#') + { + char modeChar = ModeManager::GetStatusChar(channel[0]); + channel.erase(channel.begin()); + cm = ModeManager::FindChannelModeByChar(modeChar); + if (cm != NULL && cm->Type != MODE_STATUS) + cm = NULL; + } + + Channel *c = findchan(channel); + if (c != NULL) + { + UserContainer *uc = c->FindUser(u); + if (uc != NULL) + if (cm == NULL || uc->Status->HasFlag(cm->Name)) + 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; + } + 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) + { + Anope::string real_mask = mask.substr(2); + + if (Anope::Match(u->server->GetName(), real_mask)) + return true; + } + else if (mask.find("z:") == 0) + { + Anope::string real_mask = mask.substr(2); + + if (Anope::Match(u->fingerprint, real_mask)) + return true; + } + + return false; + } +}; + class Inspircd20IRCdMessage : public InspircdIRCdMessage { public: @@ -387,9 +462,9 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage else if (modename.equals_cs("auditorium")) cm = new ChannelMode(CMODE_AUDITORIUM, modechar[0]); else if (modename.equals_cs("ban")) - cm = new ChannelModeBan(modechar[0]); + cm = new InspIRCdExtBan<ChannelModeBan>(CMODE_BAN, modechar[0]); else if (modename.equals_cs("banexception")) - cm = new ChannelModeExcept(modechar[0]); + cm = new InspIRCdExtBan<ChannelModeList>(CMODE_EXCEPT, 'e'); else if (modename.equals_cs("blockcaps")) cm = new ChannelMode(CMODE_BLOCKCAPS, modechar[0]); else if (modename.equals_cs("blockcolor")) @@ -407,7 +482,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage else if (modename.equals_cs("halfop")) cm = new ChannelModeStatus(CMODE_HALFOP, modechar[1], modechar[0]); else if (modename.equals_cs("invex")) - cm = new ChannelModeInvex(modechar[0]); + cm = new InspIRCdExtBan<ChannelModeList>(CMODE_INVITEOVERRIDE, 'I'); else if (modename.equals_cs("inviteonly")) cm = new ChannelMode(CMODE_INVITE, modechar[0]); else if (modename.equals_cs("joinflood")) @@ -649,19 +724,6 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage } }; -bool ChannelModeFlood::IsValid(const Anope::string &value) const -{ - try - { - Anope::string rest; - if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty()) - return true; - } - catch (const ConvertException &) { } - - return false; -} - class ProtoInspIRCd : public Module { Message message_endburst, message_time, diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp index cffbb1a53..d67c4272f 100644 --- a/modules/protocol/ngircd.cpp +++ b/modules/protocol/ngircd.cpp @@ -425,8 +425,8 @@ class ProtongIRCd : public Module ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x')); /* b/e/I */ - ModeManager::AddChannelMode(new ChannelModeBan('b')); - ModeManager::AddChannelMode(new ChannelModeInvex('I')); + ModeManager::AddChannelMode(new ChannelModeBan(CMODE_BAN, 'b')); + ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I')); /* v/h/o/a/q */ ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index fd6525701..d1062182f 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -366,7 +366,7 @@ class PlexusIRCdMessage : public IRCdMessage ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); if (!cm) { - Log() << "Received unknown mode prefix " << buf[0] << " in SJOIN string"; + Log() << "Received unknown mode prefix " << ch << " in SJOIN string"; continue; } @@ -596,9 +596,9 @@ class ProtoPlexus : public Module ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x')); /* b/e/I */ - ModeManager::AddChannelMode(new ChannelModeBan('b')); - ModeManager::AddChannelMode(new ChannelModeExcept('e')); - ModeManager::AddChannelMode(new ChannelModeInvex('I')); + ModeManager::AddChannelMode(new ChannelModeBan(CMODE_BAN, 'b')); + ModeManager::AddChannelMode(new ChannelModeList(CMODE_EXCEPT, 'e')); + ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I')); /* l/k */ ModeManager::AddChannelMode(new ChannelModeKey('k')); diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index f0352cf63..8b6a73cd0 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -369,7 +369,7 @@ class RatboxIRCdMessage : public IRCdMessage ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); if (!cm) { - Log() << "Received unknown mode prefix " << buf[0] << " in SJOIN string"; + Log() << "Received unknown mode prefix " << ch << " in SJOIN string"; continue; } @@ -546,9 +546,9 @@ class ProtoRatbox : public Module ModeManager::AddUserMode(new UserMode(UMODE_WALLOPS, 'w')); /* b/e/I */ - ModeManager::AddChannelMode(new ChannelModeBan('b')); - ModeManager::AddChannelMode(new ChannelModeExcept('e')); - ModeManager::AddChannelMode(new ChannelModeInvex('I')); + ModeManager::AddChannelMode(new ChannelModeBan(CMODE_BAN, 'b')); + ModeManager::AddChannelMode(new ChannelModeList(CMODE_EXCEPT, 'e')); + ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I')); /* v/h/o/a/q */ ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); diff --git a/modules/protocol/unreal32.cpp b/modules/protocol/unreal32.cpp index ca5f349e8..d8351b931 100644 --- a/modules/protocol/unreal32.cpp +++ b/modules/protocol/unreal32.cpp @@ -348,6 +348,107 @@ class UnrealIRCdProto : public IRCDProto } }; +template<typename T> class UnrealExtBan : public T +{ + public: + UnrealExtBan(ChannelModeName mName, char modeChar) : T(mName, modeChar) { } + + bool Matches(User *u, const Entry *e) + { + const Anope::string &mask = e->mask; + + if (mask.find("~c:") == 0) + { + Anope::string channel = mask.substr(3); + + ChannelMode *cm = NULL; + if (channel[0] != '#') + { + char modeChar = ModeManager::GetStatusChar(channel[0]); + channel.erase(channel.begin()); + cm = ModeManager::FindChannelModeByChar(modeChar); + if (cm != NULL && cm->Type != MODE_STATUS) + cm = NULL; + } + + Channel *c = findchan(channel); + if (c != NULL) + { + UserContainer *uc = c->FindUser(u); + if (uc != NULL) + if (cm == NULL || uc->Status->HasFlag(cm->Name)) + return true; + } + } + else if (mask.find("~j:") == 0 || mask.find("~n:") == 0 || mask.find("~q:") == 0) + { + Anope::string real_mask = mask.substr(3); + + Entry en(this->Name, real_mask); + if (en.Matches(u)) + return true; + } + else if (mask.find("~r:") == 0) + { + Anope::string real_mask = mask.substr(3); + + if (Anope::Match(u->realname, real_mask)) + return true; + } + else if (mask.find("~R:") == 0) + { + if (u->HasMode(UMODE_REGISTERED) && mask.equals_ci(u->nick)) + return true; + } + + return false; + } +}; + +class ChannelModeFlood : public ChannelModeParam +{ + public: + ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } + + /* Borrowed part of this check from UnrealIRCd */ + bool IsValid(const Anope::string &value) const + { + if (value.empty()) + return false; + try + { + Anope::string rest; + if (value[0] != ':' && convertTo<unsigned>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<unsigned>(rest.substr(1), rest, false) > 0 && rest.empty()) + return true; + } + catch (const ConvertException &) { } + + /* '['<number><1 letter>[optional: '#'+1 letter],[next..]']'':'<number> */ + size_t end_bracket = value.find(']', 1); + if (end_bracket == Anope::string::npos) + return false; + Anope::string xbuf = value.substr(0, end_bracket); + if (value[end_bracket + 1] != ':') + return false; + commasepstream args(xbuf.substr(1)); + Anope::string arg; + while (args.GetToken(arg)) + { + /* <number><1 letter>[optional: '#'+1 letter] */ + size_t p = 0; + while (p < arg.length() && isdigit(arg[p])) + ++p; + if (p == arg.length() || !(arg[p] == 'c' || arg[p] == 'j' || arg[p] == 'k' || arg[p] == 'm' || arg[p] == 'n' || arg[p] == 't')) + continue; /* continue instead of break for forward compatability. */ + int v = arg.substr(0, p).is_number_only() ? convertTo<int>(arg.substr(0, p)) : 0; + if (v < 1 || v > 999) + return false; + } + + return true; + } +}; + class Unreal32IRCdMessage : public IRCdMessage { public: @@ -521,13 +622,13 @@ class Unreal32IRCdMessage : public IRCdMessage switch (modebuf[t]) { case 'b': - ModeManager::AddChannelMode(new ChannelModeBan('b')); + ModeManager::AddChannelMode(new UnrealExtBan<ChannelModeBan>(CMODE_BAN, 'b')); continue; case 'e': - ModeManager::AddChannelMode(new ChannelModeExcept('e')); + ModeManager::AddChannelMode(new UnrealExtBan<ChannelModeList>(CMODE_EXCEPT, 'e')); continue; case 'I': - ModeManager::AddChannelMode(new ChannelModeInvex('I')); + ModeManager::AddChannelMode(new UnrealExtBan<ChannelModeList>(CMODE_INVITEOVERRIDE, 'I')); continue; default: ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, modebuf[t])); @@ -543,7 +644,7 @@ class Unreal32IRCdMessage : public IRCdMessage ModeManager::AddChannelMode(new ChannelModeKey('k')); continue; case 'f': - ModeManager::AddChannelMode(new ChannelModeFlood('f')); + ModeManager::AddChannelMode(new ChannelModeFlood('f', false)); continue; case 'L': ModeManager::AddChannelMode(new ChannelModeParam(CMODE_REDIRECT, 'L')); @@ -722,7 +823,7 @@ class Unreal32IRCdMessage : public IRCdMessage ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); if (!cm) { - Log() << "Received unknown mode prefix " << buf[0] << " in SJOIN string"; + Log() << "Received unknown mode prefix " << ch << " in SJOIN string"; continue; } @@ -936,43 +1037,6 @@ bool event_sdesc(const Anope::string &source, const std::vector<Anope::string> & return true; } -/* Borrowed part of this check from UnrealIRCd */ -bool ChannelModeFlood::IsValid(const Anope::string &value) const -{ - if (value.empty()) - return false; - try - { - Anope::string rest; - if (value[0] != ':' && convertTo<unsigned>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<unsigned>(rest.substr(1), rest, false) > 0 && rest.empty()) - return true; - } - catch (const ConvertException &) { } - - /* '['<number><1 letter>[optional: '#'+1 letter],[next..]']'':'<number> */ - size_t end_bracket = value.find(']', 1); - if (end_bracket == Anope::string::npos) - return false; - Anope::string xbuf = value.substr(0, end_bracket); - if (value[end_bracket + 1] != ':') - return false; - commasepstream args(xbuf.substr(1)); - Anope::string arg; - while (args.GetToken(arg)) - { - /* <number><1 letter>[optional: '#'+1 letter] */ - size_t p = 0; - while (p < arg.length() && isdigit(arg[p])) - ++p; - if (p == arg.length() || !(arg[p] == 'c' || arg[p] == 'j' || arg[p] == 'k' || arg[p] == 'm' || arg[p] == 'n' || arg[p] == 't')) - continue; /* continue instead of break for forward compatability. */ - int v = arg.substr(0, p).is_number_only() ? convertTo<int>(arg.substr(0, p)) : 0; - if (v < 1 || v > 999) - return false; - } - return true; -} - class ProtoUnreal : public Module { Message message_away, message_join, message_kick, diff --git a/src/actions.cpp b/src/actions.cpp index 2dcd948e7..4d4dd7d0c 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -78,7 +78,7 @@ void common_unban(ChannelInfo *ci, User *u, bool full) std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = ci->c->GetModeList(CMODE_BAN); for (; bans.first != bans.second;) { - Entry ban(bans.first->second); + Entry ban(CMODE_BAN, bans.first->second); ++bans.first; if (ban.Matches(u, full)) ci->c->RemoveMode(NULL, CMODE_BAN, ban.GetMask()); diff --git a/src/bots.cpp b/src/bots.cpp index 7e895a4be..f8d692d74 100644 --- a/src/bots.cpp +++ b/src/bots.cpp @@ -179,7 +179,7 @@ void BotInfo::Join(Channel *c, ChannelStatus *status) /* We check for bans */ for (; bans.first != bans.second; ++bans.first) { - Entry ban(bans.first->second); + Entry ban(CMODE_BAN, bans.first->second); if (ban.Matches(this)) c->RemoveMode(NULL, CMODE_BAN, ban.GetMask()); } diff --git a/src/channels.cpp b/src/channels.cpp index 9a8427bf3..089b3831b 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -1234,9 +1234,10 @@ void MassChannelModes(BotInfo *bi, const Anope::string &modes) static const Anope::string EntryFlagString[] = { "ENTRYTYPE_NONE", "ENTRYTYPE_CIDR", "ENTRYTYPE_NICK_WILD", "ENTRYTYPE_NICK", "ENTRYTYPE_USER_WILD", "ENTRYTYPE_USER", "ENTRYTYPE_HOST_WILD", "ENTRYTYPE_HOST", "" }; /** Constructor + * @param mode What mode this host is for - can be CMODE_BEGIN for unknown/no mode * @param _host A full nick!ident@host/cidr mask */ -Entry::Entry(const Anope::string &_host) : Flags<EntryType>(EntryFlagString) +Entry::Entry(ChannelModeName mode, const Anope::string &_host) : Flags<EntryType>(EntryFlagString), modename(mode) { this->SetFlag(ENTRYTYPE_NONE); this->cidr_len = 0; @@ -1330,8 +1331,7 @@ const Anope::string Entry::GetMask() */ bool Entry::Matches(User *u, bool full) const { - if (!this->FlagCount()) - return false; + bool ret = true; if (this->HasFlag(ENTRYTYPE_CIDR)) { @@ -1339,39 +1339,43 @@ bool Entry::Matches(User *u, bool full) const { cidr cidr_mask(this->host, this->cidr_len); if (!u->ip() || !cidr_mask.match(u->ip)) - { - return false; - } + ret = false; /* If we're not matching fully and their displayed host isnt their IP */ else if (!full && u->ip.addr() != u->GetDisplayedHost()) - { - return false; - } + ret = false; } catch (const SocketException &) { - return false; + ret = false; } } if (this->HasFlag(ENTRYTYPE_NICK) && !this->nick.equals_ci(u->nick)) - return false; + ret = false; if (this->HasFlag(ENTRYTYPE_USER) && !this->user.equals_ci(u->GetVIdent()) && (!full || !this->user.equals_ci(u->GetIdent()))) - return false; + ret = false; if (this->HasFlag(ENTRYTYPE_HOST) && !this->host.equals_ci(u->GetDisplayedHost()) && (!full || (!this->host.equals_ci(u->host) && !this->host.equals_ci(u->chost) && !this->host.equals_ci(u->vhost) && (!u->ip() || !this->host.equals_ci(u->ip.addr()))))) - return false; + ret = false; if (this->HasFlag(ENTRYTYPE_NICK_WILD) && !Anope::Match(u->nick, this->nick)) - return false; + ret = false; if (this->HasFlag(ENTRYTYPE_USER_WILD) && !Anope::Match(u->GetVIdent(), this->user) && (!full || !Anope::Match(u->GetIdent(), this->user))) - return false; + ret = false; if (this->HasFlag(ENTRYTYPE_HOST_WILD) && !Anope::Match(u->GetDisplayedHost(), this->host) && (!full || (!Anope::Match(u->host, this->host) && !Anope::Match(u->chost, this->host) && !Anope::Match(u->vhost, this->host) && (!u->ip() || !Anope::Match(u->ip.addr(), this->host))))) - return false; + ret = false; + + ChannelMode *cm = ModeManager::FindChannelModeByName(this->modename); + if (cm != NULL && cm->Type == MODE_LIST) + { + ChannelModeList *cml = debug_cast<ChannelModeList *>(cm); + if (cml->Matches(u, this)) + ret = true; + } - return true; + return ret; } diff --git a/src/main.cpp b/src/main.cpp index 563262195..eea96dee9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -491,7 +491,8 @@ int main(int ac, char **av, char **envp) threadEngine.Process(); /* Process any modes that need to be (un)set */ - ModeManager::ProcessModes(); + if (Me != NULL && Me->IsSynced()) + ModeManager::ProcessModes(); /* Process the socket engine */ SocketEngine->Process(); diff --git a/src/modes.cpp b/src/modes.cpp index 76b05422a..dd147118c 100644 --- a/src/modes.cpp +++ b/src/modes.cpp @@ -294,7 +294,7 @@ void ChannelModeBan::OnAdd(Channel *chan, const Anope::string &mask) { BotInfo *bi = chan->ci->bi; - Entry ban(mask); + Entry ban(CMODE_BAN, mask); if (ban.Matches(bi)) chan->RemoveMode(NULL, CMODE_BAN, mask); } @@ -302,67 +302,6 @@ void ChannelModeBan::OnAdd(Channel *chan, const Anope::string &mask) Log(LOG_DEBUG) << "Added ban " << mask << " to channel " << chan->name; } -/** Remove a ban from the channel - * @param chan The channel - * @param mask The ban - */ -void ChannelModeBan::OnDel(Channel *chan, const Anope::string &mask) -{ - if (!chan || mask.empty()) - return; - - Log(LOG_DEBUG) << "Deleted ban " << mask << " from channel " << chan->name; -} - -/** Add an except to the channel - * @param chan The channel - * @param mask The except - */ -void ChannelModeExcept::OnAdd(Channel *chan, const Anope::string &mask) -{ - if (!chan || mask.empty()) - return; - - Log(LOG_DEBUG) << "Added except " << mask << " to channel " << chan->name; -} - -/** Remove an except from the channel - * @param chan The channel - * @param mask The except - */ -void ChannelModeExcept::OnDel(Channel *chan, const Anope::string &mask) -{ - if (!chan || mask.empty()) - return; - - Log(LOG_DEBUG) << "Deleted except " << mask << " to channel " << chan->name; -} - -/** Add an invex to the channel - * @param chan The channel - * @param mask The invex - */ -void ChannelModeInvex::OnAdd(Channel *chan, const Anope::string &mask) -{ - if (!chan || mask.empty()) - return; - - Log(LOG_DEBUG) << "Added invite " << mask << " to channel " << chan->name; - -} - -/** Remove an invex from the channel - * @param chan The channel - * @param mask The index - */ -void ChannelModeInvex::OnDel(Channel *chan, const Anope::string &mask) -{ - if (!chan || mask.empty()) - return; - - Log(LOG_DEBUG) << "Deleted invite " << mask << " to channel " << chan->name; -} - void StackerInfo::AddMode(Mode *mode, bool Set, const Anope::string &Param) { ChannelMode *cm = NULL; diff --git a/src/regchannel.cpp b/src/regchannel.cpp index 1da17530f..20cfc7aed 100644 --- a/src/regchannel.cpp +++ b/src/regchannel.cpp @@ -762,7 +762,7 @@ bool ChannelInfo::CheckKick(User *user) } else { - Entry akick_mask(autokick->mask); + Entry akick_mask(CMODE_BEGIN, autokick->mask); if (akick_mask.Matches(user)) do_kick = true; } diff --git a/src/users.cpp b/src/users.cpp index a11e1b5ce..e343e3ad2 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -870,7 +870,7 @@ bool matches_list(Channel *c, User *user, ChannelModeName mode) std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> modes = c->GetModeList(mode); for (; modes.first != modes.second; ++modes.first) { - Entry e(modes.first->second); + Entry e(mode, modes.first->second); if (e.Matches(user)) return true; } |