1
0
mirror of https://github.com/anope/anope.git synced 2026-07-02 16:13:12 +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
-6
View File
@@ -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
+9 -39
View File
@@ -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
*/
+5 -3
View File
@@ -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
+1 -1
View File
@@ -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))
{
+1 -1
View File
@@ -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;
}
+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,
+1 -1
View File
@@ -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());
+1 -1
View File
@@ -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());
}
+21 -17
View File
@@ -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;
}
+2 -1
View File
@@ -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();
+1 -62
View File
@@ -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;
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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;
}