aboutsummaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorGravatar Sadie Powell2019-09-23 00:37:33 +0100
committerGravatar Sadie Powell2019-09-23 00:37:33 +0100
commit8848169e8b42b5ed85837efd3b3f9e36ffbada1b (patch)
tree04babb46ea381f254589b12288f121d53338cb67 /src/modules
parentInstall libc++abi-dev on Travis. (diff)
parentLower the acceptable drift for clocks on link. (diff)
Merge branch 'insp3' into master.
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/extra/m_mysql.cpp58
-rw-r--r--src/modules/extra/m_pgsql.cpp2
-rw-r--r--src/modules/m_alias.cpp10
-rw-r--r--src/modules/m_chanfilter.cpp89
-rw-r--r--src/modules/m_cloaking.cpp24
-rw-r--r--src/modules/m_dccallow.cpp83
-rw-r--r--src/modules/m_delaymsg.cpp2
-rw-r--r--src/modules/m_haproxy.cpp27
-rw-r--r--src/modules/m_ircv3_servertime.cpp2
-rw-r--r--src/modules/m_noctcp.cpp8
-rw-r--r--src/modules/m_silence.cpp91
-rw-r--r--src/modules/m_spanningtree/treesocket2.cpp10
-rw-r--r--src/modules/m_xline_db.cpp4
13 files changed, 321 insertions, 89 deletions
diff --git a/src/modules/extra/m_mysql.cpp b/src/modules/extra/m_mysql.cpp
index 90ed1a82c..d3df58833 100644
--- a/src/modules/extra/m_mysql.cpp
+++ b/src/modules/extra/m_mysql.cpp
@@ -246,6 +246,31 @@ class MySQLresult : public SQL::Result
*/
class SQLConnection : public SQL::Provider
{
+ private:
+ bool EscapeString(SQL::Query* query, const std::string& in, std::string& out)
+ {
+ // In the worst case each character may need to be encoded as using two bytes and one
+ // byte is the NUL terminator.
+ std::vector<char> buffer(in.length() * 2 + 1);
+
+ // The return value of mysql_escape_string() is either an error or the length of the
+ // encoded string not including the NUL terminator.
+ //
+ // Unfortunately, someone genius decided that mysql_escape_string should return an
+ // unsigned type even though -1 is returned on error so checking whether an error
+ // happened is a bit cursed.
+ unsigned long escapedsize = mysql_escape_string(&buffer[0], in.c_str(), in.length());
+ if (escapedsize == static_cast<unsigned long>(-1))
+ {
+ SQL::Error err(SQL::QSEND_FAIL, InspIRCd::Format("%u: %s", mysql_errno(connection), mysql_error(connection)));
+ query->OnError(err);
+ return false;
+ }
+
+ out.append(&buffer[0], escapedsize);
+ return true;
+ }
+
public:
reference<ConfigTag> config;
MYSQL *connection;
@@ -349,21 +374,8 @@ class SQLConnection : public SQL::Provider
{
if (q[i] != '?')
res.push_back(q[i]);
- else
- {
- if (param < p.size())
- {
- std::string parm = p[param++];
- // In the worst case, each character may need to be encoded as using two bytes,
- // and one byte is the terminating null
- std::vector<char> buffer(parm.length() * 2 + 1);
-
- // The return value of mysql_real_escape_string() is the length of the encoded string,
- // not including the terminating null
- unsigned long escapedsize = mysql_real_escape_string(connection, &buffer[0], parm.c_str(), parm.length());
- res.append(&buffer[0], escapedsize);
- }
- }
+ else if (param < p.size() && !EscapeString(call, p[param++], res))
+ return;
}
Submit(call, res);
}
@@ -384,14 +396,8 @@ class SQLConnection : public SQL::Provider
i--;
SQL::ParamMap::const_iterator it = p.find(field);
- if (it != p.end())
- {
- std::string parm = it->second;
- // NOTE: See above
- std::vector<char> buffer(parm.length() * 2 + 1);
- unsigned long escapedsize = mysql_escape_string(&buffer[0], parm.c_str(), parm.length());
- res.append(&buffer[0], escapedsize);
- }
+ if (it != p.end() && !EscapeString(call, it->second, res))
+ return;
}
}
Submit(call, res);
@@ -405,6 +411,9 @@ ModuleSQL::ModuleSQL()
void ModuleSQL::init()
{
+ if (mysql_library_init(0, NULL, NULL))
+ throw ModuleException("Unable to initialise the MySQL library!");
+
Dispatcher = new DispatcherThread(this);
Dispatcher->Start();
}
@@ -417,10 +426,13 @@ ModuleSQL::~ModuleSQL()
Dispatcher->OnNotify();
delete Dispatcher;
}
+
for(ConnMap::iterator i = connections.begin(); i != connections.end(); i++)
{
delete i->second;
}
+
+ mysql_library_end();
}
void ModuleSQL::ReadConfig(ConfigStatus& status)
diff --git a/src/modules/extra/m_pgsql.cpp b/src/modules/extra/m_pgsql.cpp
index 10ad2b968..ac285a8aa 100644
--- a/src/modules/extra/m_pgsql.cpp
+++ b/src/modules/extra/m_pgsql.cpp
@@ -103,7 +103,7 @@ class PgSQLresult : public SQL::Result
{
rows = PQntuples(res);
if (!rows)
- rows = atoi(PQcmdTuples(res));
+ rows = ConvToNum<int>(PQcmdTuples(res));
}
~PgSQLresult()
diff --git a/src/modules/m_alias.cpp b/src/modules/m_alias.cpp
index 1904af549..e3308b027 100644
--- a/src/modules/m_alias.cpp
+++ b/src/modules/m_alias.cpp
@@ -50,6 +50,9 @@ class Alias
/** Format that must be matched for use */
std::string format;
+
+ /** Strip color codes before match? */
+ bool StripColor;
};
class ModuleAlias : public Module
@@ -94,6 +97,7 @@ class ModuleAlias : public Module
a.UserCommand = tag->getBool("usercommand", true);
a.OperOnly = tag->getBool("operonly");
a.format = tag->getString("format");
+ a.StripColor = tag->getBool("stripcolor");
std::transform(a.AliasedCommand.begin(), a.AliasedCommand.end(), a.AliasedCommand.begin(), ::toupper);
newAliases.insert(std::make_pair(a.AliasedCommand, a));
@@ -261,10 +265,14 @@ class ModuleAlias : public Module
int DoAlias(User *user, Channel *c, Alias *a, const std::string& compare, const std::string& safe)
{
+ std::string stripped(compare);
+ if (a->StripColor)
+ InspIRCd::StripColor(stripped);
+
/* Does it match the pattern? */
if (!a->format.empty())
{
- if (!InspIRCd::Match(compare, a->format))
+ if (!InspIRCd::Match(stripped, a->format))
return 0;
}
diff --git a/src/modules/m_chanfilter.cpp b/src/modules/m_chanfilter.cpp
index 4b3721b12..da36c58cc 100644
--- a/src/modules/m_chanfilter.cpp
+++ b/src/modules/m_chanfilter.cpp
@@ -59,6 +59,25 @@ class ModuleChanFilter : public Module
bool hidemask;
bool notifyuser;
+ ChanFilter::ListItem* Match(User* user, Channel* chan, const std::string& text)
+ {
+ ModResult res = CheckExemption::Call(exemptionprov, user, chan, "filter");
+ if (!IS_LOCAL(user) || res == MOD_RES_ALLOW)
+ return NULL;
+
+ ListModeBase::ModeList* list = cf.GetList(chan);
+ if (!list)
+ return NULL;
+
+ for (ListModeBase::ModeList::iterator i = list->begin(); i != list->end(); i++)
+ {
+ if (InspIRCd::Match(text, i->mask))
+ return &*i;
+ }
+
+ return NULL;
+ }
+
public:
ModuleChanFilter()
@@ -76,40 +95,62 @@ class ModuleChanFilter : public Module
cf.DoRehash();
}
+ void OnUserPart(Membership* memb, std::string& partmessage, CUList& except_list) override
+ {
+ if (!memb)
+ return;
+
+ User* user = memb->user;
+ Channel* chan = memb->chan;
+ ChanFilter::ListItem* match = Match(user, chan, partmessage);
+ if (!match)
+ return;
+
+ // Match() checks the user is local, we can assume from here
+ LocalUser* luser = IS_LOCAL(user);
+
+ std::string oldreason(partmessage);
+ partmessage = "Reason filtered";
+ if (!notifyuser)
+ {
+ // Send fake part
+ ClientProtocol::Messages::Part partmsg(memb, oldreason);
+ ClientProtocol::Event ev(ServerInstance->GetRFCEvents().part, partmsg);
+ luser->Send(ev);
+
+ // Don't send the user the changed message
+ except_list.insert(user);
+ return;
+ }
+
+ if (hidemask)
+ user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your part message contained a censored word)");
+ else
+ user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your part message contained a censored word: " + match->mask + ")");
+ }
+
ModResult OnUserPreMessage(User* user, const MessageTarget& target, MessageDetails& details) override
{
if (target.type != MessageTarget::TYPE_CHANNEL)
return MOD_RES_PASSTHRU;
Channel* chan = target.Get<Channel>();
- ModResult res = CheckExemption::Call(exemptionprov, user, chan, "filter");
-
- if (!IS_LOCAL(user) || res == MOD_RES_ALLOW)
- return MOD_RES_PASSTHRU;
-
- ListModeBase::ModeList* list = cf.GetList(chan);
-
- if (list)
+ ChanFilter::ListItem* match = Match(user, chan, details.text);
+ if (match)
{
- for (ListModeBase::ModeList::iterator i = list->begin(); i != list->end(); i++)
+ if (!notifyuser)
{
- if (InspIRCd::Match(details.text, i->mask))
- {
- if (!notifyuser)
- {
- details.echo_original = true;
- return MOD_RES_DENY;
- }
-
- if (hidemask)
- user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your message contained a censored word)");
- else
- user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your message contained a censored word: " + i->mask + ")");
- return MOD_RES_DENY;
- }
+ details.echo_original = true;
+ return MOD_RES_DENY;
}
- }
+ if (hidemask)
+ user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your message contained a censored word)");
+ else
+ user->WriteNumeric(ERR_CANNOTSENDTOCHAN, chan->name, "Cannot send to channel (your message contained a censored word: " + match->mask + ")");
+
+ return MOD_RES_DENY;
+ }
return MOD_RES_PASSTHRU;
}
diff --git a/src/modules/m_cloaking.cpp b/src/modules/m_cloaking.cpp
index 7c8260174..64b3936b2 100644
--- a/src/modules/m_cloaking.cpp
+++ b/src/modules/m_cloaking.cpp
@@ -49,6 +49,9 @@ struct CloakInfo
// The number of parts of the hostname shown when using half cloaking.
unsigned int domainparts;
+ // Whether to ignore the case of a hostname when cloaking it.
+ bool ignorecase;
+
// The secret used for generating cloaks.
std::string key;
@@ -58,9 +61,10 @@ struct CloakInfo
// The suffix for IP cloaks (e.g. .IP).
std::string suffix;
- CloakInfo(CloakMode Mode, const std::string& Key, const std::string& Prefix, const std::string& Suffix, unsigned int DomainParts = 0)
+ CloakInfo(CloakMode Mode, const std::string& Key, const std::string& Prefix, const std::string& Suffix, bool IgnoreCase, unsigned int DomainParts = 0)
: mode(Mode)
, domainparts(DomainParts)
+ , ignorecase(IgnoreCase)
, key(Key)
, prefix(Prefix)
, suffix(Suffix)
@@ -248,7 +252,10 @@ class ModuleCloaking : public Module
input.append(1, id);
input.append(info.key);
input.append(1, '\0'); // null does not terminate a C++ string
- input.append(item);
+ if (info.ignorecase)
+ std::transform(item.begin(), item.end(), std::back_inserter(input), ::tolower);
+ else
+ input.append(item);
std::string rv = Hash->GenerateRaw(input).substr(0,len);
for(size_t i = 0; i < len; i++)
@@ -388,17 +395,17 @@ class ModuleCloaking : public Module
{
case MODE_HALF_CLOAK:
// Use old cloaking verification to stay compatible with 2.0
- // But verify domainparts when use 3.0-only features
- if (info.domainparts == 3)
+ // But verify domainparts and ignorecase when use 3.0-only features
+ if (info.domainparts == 3 && !info.ignorecase)
testcloak = info.prefix + SegmentCloak(info, "*", 3, 8) + info.suffix;
else
{
irc::sockets::sockaddrs sa;
- testcloak = GenCloak(info, sa, "", testcloak + ConvToStr(info.domainparts));
+ testcloak = GenCloak(info, sa, "", testcloak + ConvToStr(info.domainparts)) + (info.ignorecase ? "-ci" : "");
}
break;
case MODE_OPAQUE:
- testcloak = info.prefix + SegmentCloak(info, "*", 4, 8) + info.suffix;
+ testcloak = info.prefix + SegmentCloak(info, "*", 4, 8) + info.suffix + (info.ignorecase ? "-ci" : "");
}
}
return Version("Provides masking of user hostnames", VF_COMMON|VF_VENDOR, testcloak);
@@ -424,16 +431,17 @@ class ModuleCloaking : public Module
if (i == tags.first && key.length() < minkeylen)
throw ModuleException("Your cloaking key is not secure. It should be at least " + ConvToStr(minkeylen) + " characters long, at " + tag->getTagLocation());
+ const bool ignorecase = tag->getBool("ignorecase");
const std::string mode = tag->getString("mode");
const std::string prefix = tag->getString("prefix");
const std::string suffix = tag->getString("suffix", ".IP");
if (stdalgo::string::equalsci(mode, "half"))
{
unsigned int domainparts = tag->getUInt("domainparts", 3, 1, 10);
- newcloaks.push_back(CloakInfo(MODE_HALF_CLOAK, key, prefix, suffix, domainparts));
+ newcloaks.push_back(CloakInfo(MODE_HALF_CLOAK, key, prefix, suffix, ignorecase, domainparts));
}
else if (stdalgo::string::equalsci(mode, "full"))
- newcloaks.push_back(CloakInfo(MODE_OPAQUE, key, prefix, suffix));
+ newcloaks.push_back(CloakInfo(MODE_OPAQUE, key, prefix, suffix, ignorecase));
else
throw ModuleException(mode + " is an invalid value for <cloak:mode>; acceptable values are 'half' and 'full', at " + tag->getTagLocation());
}
diff --git a/src/modules/m_dccallow.cpp b/src/modules/m_dccallow.cpp
index 13963fc0b..60d880cb6 100644
--- a/src/modules/m_dccallow.cpp
+++ b/src/modules/m_dccallow.cpp
@@ -98,14 +98,83 @@ typedef std::vector<DCCAllow> dccallowlist;
dccallowlist* dl;
typedef std::vector<BannedFileList> bannedfilelist;
bannedfilelist bfl;
-typedef SimpleExtItem<dccallowlist> DCCAllowExt;
-class CommandDccallow : public Command
+class DCCAllowExt : public SimpleExtItem<dccallowlist>
{
- DCCAllowExt& ext;
-
public:
unsigned int maxentries;
+
+ DCCAllowExt(Module* Creator)
+ : SimpleExtItem<dccallowlist>(Creator, "dccallow", ExtensionItem::EXT_USER)
+ {
+ }
+
+ void FromInternal(Extensible* container, const std::string& value) override
+ {
+ LocalUser* user = IS_LOCAL(static_cast<User*>(container));
+ if (!user)
+ return;
+
+ // Remove the old list and create a new one.
+ unset(user);
+ dccallowlist* list = new dccallowlist();
+
+ irc::spacesepstream ts(value);
+ while (!ts.StreamEnd())
+ {
+ // Check we have space for another entry.
+ if (list->size() >= maxentries)
+ {
+ ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Oversized DCC allow list received for %s: %s",
+ user->uuid.c_str(), value.c_str());
+ delete list;
+ return;
+ }
+
+ // Extract the fields.
+ DCCAllow dccallow;
+ if (!ts.GetToken(dccallow.nickname) ||
+ !ts.GetToken(dccallow.hostmask) ||
+ !ts.GetNumericToken(dccallow.set_on) ||
+ !ts.GetNumericToken(dccallow.length))
+ {
+ ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Malformed DCC allow list received for %s: %s",
+ user->uuid.c_str(), value.c_str());
+ delete list;
+ return;
+ }
+
+ // Store the DCC allow entry.
+ list->push_back(dccallow);
+ }
+
+ }
+
+ std::string ToInternal(const Extensible* container, void* item) const override
+ {
+ dccallowlist* list = static_cast<dccallowlist*>(item);
+ std::string buf;
+ for (dccallowlist::const_iterator iter = list->begin(); iter != list->end(); ++iter)
+ {
+ if (iter != list->begin())
+ buf.push_back(' ');
+
+ buf.append(iter->nickname);
+ buf.push_back(' ');
+ buf.append(iter->hostmask);
+ buf.push_back(' ');
+ buf.append(ConvToStr(iter->set_on));
+ buf.push_back(' ');
+ buf.append(ConvToStr(iter->length));
+ }
+ return buf;
+ }
+};
+
+class CommandDccallow : public Command
+{
+ public:
+ DCCAllowExt& ext;
unsigned long defaultlength;
CommandDccallow(Module* parent, DCCAllowExt& Ext)
: Command(parent, "DCCALLOW", 0)
@@ -191,7 +260,7 @@ class CommandDccallow : public Command
ul.push_back(user);
}
- if (dl->size() >= maxentries)
+ if (dl->size() >= ext.maxentries)
{
user->WriteNumeric(ERR_DCCALLOWINVALID, user->nick, "Too many nicks on DCCALLOW list");
return CMD_FAILURE;
@@ -301,7 +370,7 @@ class ModuleDCCAllow : public Module
public:
ModuleDCCAllow()
- : ext(this, "dccallow", ExtensionItem::EXT_USER)
+ : ext(this)
, cmd(this, ext)
, blockchat(false)
{
@@ -521,7 +590,7 @@ class ModuleDCCAllow : public Module
bfl.swap(newbfl);
ConfigTag* tag = ServerInstance->Config->ConfValue("dccallow");
- cmd.maxentries = tag->getUInt("maxentries", 20);
+ cmd.ext.maxentries = tag->getUInt("maxentries", 20);
cmd.defaultlength = tag->getDuration("length", 0);
blockchat = tag->getBool("blockchat");
defaultaction = tag->getString("action");
diff --git a/src/modules/m_delaymsg.cpp b/src/modules/m_delaymsg.cpp
index 3206d9b08..b99c3f6de 100644
--- a/src/modules/m_delaymsg.cpp
+++ b/src/modules/m_delaymsg.cpp
@@ -34,7 +34,7 @@ class DelayMsgMode : public ParamMode<DelayMsgMode, IntExtItem>
bool ResolveModeConflict(std::string& their_param, const std::string& our_param, Channel*) override
{
- return (atoi(their_param.c_str()) < atoi(our_param.c_str()));
+ return ConvToNum<intptr_t>(their_param) < ConvToNum<intptr_t>(our_param);
}
ModeAction OnSet(User* source, Channel* chan, std::string& parameter) override;
diff --git a/src/modules/m_haproxy.cpp b/src/modules/m_haproxy.cpp
index 4f2d6cdbf..fcdb3ce9f 100644
--- a/src/modules/m_haproxy.cpp
+++ b/src/modules/m_haproxy.cpp
@@ -219,7 +219,16 @@ class HAProxyHook : public IOHookMiddle
return true;
}
- int ReadProxyAddress(StreamSocket* sock)
+ int ReadData(std::string& destrecvq)
+ {
+ // Once connected we handle no special data.
+ std::string& recvq = GetRecvQ();
+ destrecvq.append(recvq);
+ recvq.clear();
+ return 1;
+ }
+
+ int ReadProxyAddress(StreamSocket* sock, std::string& destrecvq)
{
// Block until we have the entire address.
std::string& recvq = GetRecvQ();
@@ -276,14 +285,15 @@ class HAProxyHook : public IOHookMiddle
// Erase the processed proxy information from the receive queue.
recvq.erase(0, address_length);
+ break;
}
// We're done!
state = HPS_CONNECTED;
- return 1;
+ return ReadData(destrecvq);
}
- int ReadProxyHeader(StreamSocket* sock)
+ int ReadProxyHeader(StreamSocket* sock, std::string& destrecvq)
{
// Block until we have a header.
std::string& recvq = GetRecvQ();
@@ -359,7 +369,7 @@ class HAProxyHook : public IOHookMiddle
}
state = HPS_WAITING_FOR_ADDRESS;
- return ReadProxyAddress(sock);
+ return ReadProxyAddress(sock, destrecvq);
}
public:
@@ -384,16 +394,13 @@ class HAProxyHook : public IOHookMiddle
switch (state)
{
case HPS_WAITING_FOR_HEADER:
- return ReadProxyHeader(sock);
+ return ReadProxyHeader(sock, destrecvq);
case HPS_WAITING_FOR_ADDRESS:
- return ReadProxyAddress(sock);
+ return ReadProxyAddress(sock, destrecvq);
case HPS_CONNECTED:
- std::string& recvq = GetRecvQ();
- destrecvq.append(recvq);
- recvq.clear();
- return 1;
+ return ReadData(destrecvq);
}
// We should never reach this point.
diff --git a/src/modules/m_ircv3_servertime.cpp b/src/modules/m_ircv3_servertime.cpp
index 5fa099ece..943afb278 100644
--- a/src/modules/m_ircv3_servertime.cpp
+++ b/src/modules/m_ircv3_servertime.cpp
@@ -46,6 +46,8 @@ class ServerTimeTag
}
public:
+ using ServerProtocol::MessageEventListener::OnBuildMessage;
+
ServerTimeTag(Module* mod)
: IRCv3::ServerTime::Manager(mod)
, IRCv3::CapTag<ServerTimeTag>(mod, "server-time", "time")
diff --git a/src/modules/m_noctcp.cpp b/src/modules/m_noctcp.cpp
index 500c31dbc..ca1bffb10 100644
--- a/src/modules/m_noctcp.cpp
+++ b/src/modules/m_noctcp.cpp
@@ -67,6 +67,14 @@ class ModuleNoCTCP : public Module
user->WriteNumeric(ERR_CANNOTSENDTOCHAN, c->name, "Can't send CTCP to channel (+C is set)");
return MOD_RES_DENY;
}
+
+ const Channel::MemberMap& members = c->GetUsers();
+ for (Channel::MemberMap::const_iterator member = members.begin(); member != members.end(); ++member)
+ {
+ User* u = member->first;
+ if (u->IsModeSet(ncu))
+ details.exemptions.insert(u);
+ }
break;
}
case MessageTarget::TYPE_USER:
diff --git a/src/modules/m_silence.cpp b/src/modules/m_silence.cpp
index b7c24b5e9..90212ef2b 100644
--- a/src/modules/m_silence.cpp
+++ b/src/modules/m_silence.cpp
@@ -180,6 +180,84 @@ class SilenceEntry
typedef insp::flat_set<SilenceEntry> SilenceList;
+class SilenceExtItem : public SimpleExtItem<SilenceList>
+{
+ public:
+ unsigned int maxsilence;
+
+ SilenceExtItem(Module* Creator)
+ : SimpleExtItem<SilenceList>(Creator, "silence_list", ExtensionItem::EXT_USER)
+ {
+ }
+
+ void FromInternal(Extensible* container, const std::string& value) override
+ {
+ LocalUser* user = IS_LOCAL(static_cast<User*>(container));
+ if (!user)
+ return;
+
+ // Remove the old list and create a new one.
+ unset(user);
+ SilenceList* list = new SilenceList();
+
+ irc::spacesepstream ts(value);
+ while (!ts.StreamEnd())
+ {
+ // Check we have space for another entry.
+ if (list->size() >= maxsilence)
+ {
+ ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Oversized silence list received for %s: %s",
+ user->uuid.c_str(), value.c_str());
+ delete list;
+ return;
+ }
+
+ // Extract the mask and the flags.
+ std::string mask;
+ std::string flagstr;
+ if (!ts.GetToken(mask) || !ts.GetToken(flagstr))
+ {
+ ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Malformed silence list received for %s: %s",
+ user->uuid.c_str(), value.c_str());
+ delete list;
+ return;
+ }
+
+ // Try to parse the flags.
+ uint32_t flags;
+ if (!SilenceEntry::FlagsToBits(flagstr, flags))
+ {
+ ServerInstance->Logs.Log(MODNAME, LOG_DEBUG, "Malformed silence flags received for %s: %s",
+ user->uuid.c_str(), flagstr.c_str());
+ delete list;
+ return;
+ }
+
+ // Store the silence entry.
+ list->insert(SilenceEntry(flags, mask));
+ }
+
+ // The value was well formed.
+ set(user, list);
+ }
+
+ std::string ToInternal(const Extensible* container, void* item) const override
+ {
+ SilenceList* list = static_cast<SilenceList*>(item);
+ std::string buf;
+ for (SilenceList::const_iterator iter = list->begin(); iter != list->end(); ++iter)
+ {
+ if (iter != list->begin())
+ buf.push_back(' ');
+
+ buf.append(iter->mask);
+ buf.push_back(' ');
+ buf.append(SilenceEntry::BitsToFlags(iter->flags));
+ }
+ return buf;
+ }
+};
+
class SilenceMessage : public ClientProtocol::Message
{
public:
@@ -199,7 +277,7 @@ class CommandSilence : public SplitCommand
CmdResult AddSilence(LocalUser* user, const std::string& mask, uint32_t flags)
{
SilenceList* list = ext.get(user);
- if (list && list->size() > maxsilence)
+ if (list && list->size() > ext.maxsilence)
{
user->WriteNumeric(ERR_SILELISTFULL, mask, SilenceEntry::BitsToFlags(flags), "Your SILENCE list is full");
return CMD_FAILURE;
@@ -258,13 +336,12 @@ class CommandSilence : public SplitCommand
}
public:
- SimpleExtItem<SilenceList> ext;
- unsigned int maxsilence;
+ SilenceExtItem ext;
CommandSilence(Module* Creator)
: SplitCommand(Creator, "SILENCE")
, msgprov(Creator, "SILENCE")
- , ext(Creator, "silence_list", ExtensionItem::EXT_USER)
+ , ext(Creator)
{
allow_empty_last_param = false;
syntax = "[(+|-)<mask> [CcdiNnPpTtx]]";
@@ -282,7 +359,7 @@ class CommandSilence : public SplitCommand
std::string mask = parameters[0];
if (mask[0] == '-' || mask[0] == '+')
{
- mask.erase(0);
+ mask.erase(0, 1);
if (mask.empty())
mask.assign("*");
ModeParser::CleanMask(mask);
@@ -364,13 +441,13 @@ class ModuleSilence
{
ConfigTag* tag = ServerInstance->Config->ConfValue("silence");
exemptuline = tag->getBool("exemptuline", true);
- cmd.maxsilence = tag->getUInt("maxentries", 32, 1);
+ cmd.ext.maxsilence = tag->getUInt("maxentries", 32, 1);
}
void On005Numeric(std::map<std::string, std::string>& tokens) override
{
tokens["ESILENCE"] = "CcdiNnPpTtx";
- tokens["SILENCE"] = ConvToStr(cmd.maxsilence);
+ tokens["SILENCE"] = ConvToStr(cmd.ext.maxsilence);
}
ModResult OnUserPreInvite(User* source, User* dest, Channel* channel, time_t timeout) override
diff --git a/src/modules/m_spanningtree/treesocket2.cpp b/src/modules/m_spanningtree/treesocket2.cpp
index db16ad121..faa4af2c0 100644
--- a/src/modules/m_spanningtree/treesocket2.cpp
+++ b/src/modules/m_spanningtree/treesocket2.cpp
@@ -155,17 +155,17 @@ void TreeSocket::ProcessLine(std::string &line)
}
else if (command == "BURST")
{
- if (params.size())
+ if (!params.empty())
{
time_t them = ConvToNum<time_t>(params[0]);
time_t delta = them - ServerInstance->Time();
- if ((delta < -600) || (delta > 600))
+ if ((delta < -60) || (delta > 60))
{
- ServerInstance->SNO.WriteGlobalSno('l', "\002ERROR\002: Your clocks are off by %ld seconds (this is more than five minutes). Link aborted, \002PLEASE SYNC YOUR CLOCKS!\002", labs((long)delta));
- SendError("Your clocks are out by "+ConvToStr(labs((long)delta))+" seconds (this is more than five minutes). Link aborted, PLEASE SYNC YOUR CLOCKS!");
+ ServerInstance->SNO.WriteGlobalSno('l', "\002ERROR\002: Your clocks are off by %ld seconds (this is more than one minute). Link aborted, \002PLEASE SYNC YOUR CLOCKS!\002", labs((long)delta));
+ SendError("Your clocks are out by "+ConvToStr(labs((long)delta))+" seconds (this is more than one minute). Link aborted, PLEASE SYNC YOUR CLOCKS!");
return;
}
- else if ((delta < -30) || (delta > 30))
+ else if ((delta < -15) || (delta > 15))
{
ServerInstance->SNO.WriteGlobalSno('l', "\002WARNING\002: Your clocks are off by %ld seconds. Please consider syncing your clocks.", labs((long)delta));
}
diff --git a/src/modules/m_xline_db.cpp b/src/modules/m_xline_db.cpp
index b72eebb07..8e20e8f42 100644
--- a/src/modules/m_xline_db.cpp
+++ b/src/modules/m_xline_db.cpp
@@ -211,8 +211,8 @@ class ModuleXLineDB
continue;
}
- XLine* xl = xlf->Generate(ServerInstance->Time(), atoi(command_p[5].c_str()), command_p[3], command_p[6], command_p[2]);
- xl->SetCreateTime(atoi(command_p[4].c_str()));
+ XLine* xl = xlf->Generate(ServerInstance->Time(), ConvToNum<unsigned long>(command_p[5]), command_p[3], command_p[6], command_p[2]);
+ xl->SetCreateTime(ConvToNum<time_t>(command_p[4]));
if (ServerInstance->XLines->AddLine(xl, NULL))
{