1
0
mirror of https://github.com/anope/anope.git synced 2026-07-10 11:43:15 +02:00

Added support for extbans

This commit is contained in:
Adam
2011-03-07 19:54:51 -05:00
parent 093b3d258e
commit 8eb23e7d48
21 changed files with 356 additions and 248 deletions
+19 -13
View File
@@ -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
{
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 &) { }
public:
ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { }
return false;
}
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 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'));
+19
View File
@@ -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:
+23 -17
View File
@@ -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,
+57 -16
View File
@@ -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,
+78 -16
View File
@@ -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,
+2 -2
View File
@@ -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', '+'));
+4 -4
View File
@@ -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'));
+4 -4
View File
@@ -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', '+'));
+106 -42
View File
@@ -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,