/*
* InspIRCd -- Internet Relay Chat Daemon
*
- * Copyright (C) 2019 Peter Powell <petpow@saberuk.com>
+ * Copyright (C) 2019 linuxdaemon <linuxdaemon.irc@gmail.com>
+ * Copyright (C) 2019 iwalkalone <iwalkalone69@gmail.com>
+ * Copyright (C) 2019 Sadie Powell <sadie@witchery.services>
+ * Copyright (C) 2019 Robby <robby@chatbelgie.be>
*
* This file is part of InspIRCd. InspIRCd is free software: you can
* redistribute it and/or modify it under the terms of the GNU General Public
typedef insp::flat_set<SilenceEntry> SilenceList;
+class SilenceExtItem : public SimpleExtItem<SilenceList>
+{
+ public:
+ unsigned int maxsilence;
+
+ SilenceExtItem(Module* Creator)
+ : SimpleExtItem<SilenceList>("silence_list", ExtensionItem::EXT_USER, Creator)
+ {
+ }
+
+ void FromInternal(Extensible* container, const std::string& value) CXX11_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 CXX11_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:
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;
}
public:
- SimpleExtItem<SilenceList> ext;
- unsigned int maxsilence;
+ SilenceExtItem ext;
CommandSilence(Module* Creator)
: SplitCommand(Creator, "SILENCE")
, msgprov(Creator, "SILENCE")
- , ext("silence_list", ExtensionItem::EXT_USER, Creator)
+ , ext(Creator)
{
allow_empty_last_param = false;
syntax = "[(+|-)<mask> [CcdiNnPpTtx]]";
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);
{
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) CXX11_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) CXX11_OVERRIDE
bool is_ctcp = details.IsCTCP(ctcpname) && !irc::equals(ctcpname, "ACTION");
SilenceEntry::SilenceFlags flag = SilenceEntry::SF_NONE;
- if (target.type == MessageTarget::TYPE_CHANNEL)
+ switch (target.type)
{
- if (is_ctcp)
- flag = SilenceEntry::SF_CTCP_CHANNEL;
- else if (details.type == MSG_NOTICE)
- flag = SilenceEntry::SF_NOTICE_CHANNEL;
- else if (details.type == MSG_PRIVMSG)
- flag = SilenceEntry::SF_PRIVMSG_CHANNEL;
-
- return BuildChannelExempts(user, target.Get<Channel>(), flag, details.exemptions);
- }
-
- if (target.type == MessageTarget::TYPE_USER)
- {
- if (is_ctcp)
- flag = SilenceEntry::SF_CTCP_USER;
- else if (details.type == MSG_NOTICE)
- flag = SilenceEntry::SF_NOTICE_USER;
- else if (details.type == MSG_PRIVMSG)
- flag = SilenceEntry::SF_PRIVMSG_USER;
-
- if (!CanReceiveMessage(user, target.Get<User>(), flag))
+ case MessageTarget::TYPE_CHANNEL:
+ {
+ if (is_ctcp)
+ flag = SilenceEntry::SF_CTCP_CHANNEL;
+ else if (details.type == MSG_NOTICE)
+ flag = SilenceEntry::SF_NOTICE_CHANNEL;
+ else if (details.type == MSG_PRIVMSG)
+ flag = SilenceEntry::SF_PRIVMSG_CHANNEL;
+
+ return BuildChannelExempts(user, target.Get<Channel>(), flag, details.exemptions);
+ }
+ case MessageTarget::TYPE_USER:
{
- details.echo_original = true;
- return MOD_RES_DENY;
+ if (is_ctcp)
+ flag = SilenceEntry::SF_CTCP_USER;
+ else if (details.type == MSG_NOTICE)
+ flag = SilenceEntry::SF_NOTICE_USER;
+ else if (details.type == MSG_PRIVMSG)
+ flag = SilenceEntry::SF_PRIVMSG_USER;
+
+ if (!CanReceiveMessage(user, target.Get<User>(), flag))
+ {
+ details.echo_original = true;
+ return MOD_RES_DENY;
+ }
+ break;
}
+ case MessageTarget::TYPE_SERVER:
+ break;
}
return MOD_RES_PASSTHRU;
Version GetVersion() CXX11_OVERRIDE
{
- return Version("Provides support for blocking users with the SILENCE command", VF_OPTCOMMON | VF_VENDOR);
+ return Version("Adds the /SILENCE command which allows users to ignore other users on server-side.", VF_OPTCOMMON | VF_VENDOR);
}
};