class ModuleFilter : public Module
{
- typedef std::set<std::string, irc::insensitive_swo> ExemptTargetSet;
+ typedef insp::flat_set<std::string, irc::insensitive_swo> ExemptTargetSet;
bool initing;
RegexFactory* factory;
// List of channel names excluded from filtering.
ExemptTargetSet exemptedchans;
+ // List of target nicknames excluded from filtering.
+ ExemptTargetSet exemptednicks;
+
ModuleFilter();
CullResult cull();
ModResult OnUserPreMessage(User* user, void* dest, int target_type, std::string& text, char status, CUList& exempt_list, MessageType msgtype) CXX11_OVERRIDE;
FilterResult DecodeFilter(const std::string &data);
void OnSyncNetwork(ProtocolInterface::Server& server) CXX11_OVERRIDE;
void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata) CXX11_OVERRIDE;
- ModResult OnStats(char symbol, User* user, string_list &results) CXX11_OVERRIDE;
+ ModResult OnStats(Stats::Context& stats) CXX11_OVERRIDE;
ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line) CXX11_OVERRIDE;
void OnUnloadModule(Module* mod) CXX11_OVERRIDE;
bool AppliesToMe(User* user, FilterResult* filter, int flags);
if (target_type == TYPE_USER)
{
User* t = (User*)dest;
+ // Check if the target nick is exempted, if yes, ignore this message
+ if (exemptednicks.count(t->nick))
+ return MOD_RES_PASSTHRU;
+
target = t->nick;
}
else if (target_type == TYPE_CHANNEL)
{
ServerInstance->SNO->WriteGlobalSno('a', "FILTER: "+user->nick+" had their message filtered, target was "+target+": "+f->reason);
if (target_type == TYPE_CHANNEL)
- user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Message to channel blocked and opers notified (%s)", target.c_str(), f->reason.c_str());
+ user->WriteNumeric(ERR_CANNOTSENDTOCHAN, target, InspIRCd::Format("Message to channel blocked and opers notified (%s)", f->reason.c_str()));
else
user->WriteNotice("Your message to "+target+" was blocked and opers notified: "+f->reason);
}
else if (f->action == FA_SILENT)
{
if (target_type == TYPE_CHANNEL)
- user->WriteNumeric(ERR_CANNOTSENDTOCHAN, "%s :Message to channel blocked (%s)", target.c_str(), f->reason.c_str());
+ user->WriteNumeric(ERR_CANNOTSENDTOCHAN, target, InspIRCd::Format("Message to channel blocked (%s)", f->reason.c_str()));
else
user->WriteNotice("Your message to "+target+" was blocked: "+f->reason);
}
ModResult ModuleFilter::OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line)
{
- if (validated && IS_LOCAL(user))
+ if (validated)
{
flags = 0;
bool parting;
{
ConfigTagList tags = ServerInstance->Config->ConfTags("exemptfromfilter");
exemptedchans.clear();
+ exemptednicks.clear();
+
for (ConfigIter i = tags.first; i != tags.second; ++i)
{
- std::string chan = i->second->getString("channel");
- if (!chan.empty())
- exemptedchans.insert(chan);
+ ConfigTag* tag = i->second;
+
+ // If "target" is not found, try the old "channel" key to keep compatibility with 2.0 configs
+ const std::string target = tag->getString("target", tag->getString("channel"));
+ if (!target.empty())
+ {
+ if (target[0] == '#')
+ exemptedchans.insert(target);
+ else
+ exemptednicks.insert(target);
+ }
}
std::string newrxengine = ServerInstance->Config->ConfValue("filteropts")->getString("engine");
bool ModuleFilter::StringToFilterAction(const std::string& str, FilterAction& fa)
{
- irc::string s(str.c_str());
-
- if (s == "gline")
+ if (stdalgo::string::equalsci(str, "gline"))
fa = FA_GLINE;
- else if (s == "block")
+ else if (stdalgo::string::equalsci(str, "block"))
fa = FA_BLOCK;
- else if (s == "silent")
+ else if (stdalgo::string::equalsci(str, "silent"))
fa = FA_SILENT;
- else if (s == "kill")
+ else if (stdalgo::string::equalsci(str, "kill"))
fa = FA_KILL;
- else if (s == "none")
+ else if (stdalgo::string::equalsci(str, "none"))
fa = FA_NONE;
else
return false;
}
}
-ModResult ModuleFilter::OnStats(char symbol, User* user, string_list &results)
+ModResult ModuleFilter::OnStats(Stats::Context& stats)
{
- if (symbol == 's')
+ if (stats.GetSymbol() == 's')
{
for (std::vector<FilterResult>::iterator i = filters.begin(); i != filters.end(); i++)
{
- results.push_back("223 "+user->nick+" :"+RegexEngine.GetProvider()+":"+i->freeform+" "+i->GetFlags()+" "+FilterActionToString(i->action)+" "+ConvToStr(i->gline_time)+" :"+i->reason);
+ stats.AddRow(223, RegexEngine.GetProvider()+":"+i->freeform+" "+i->GetFlags()+" "+FilterActionToString(i->action)+" "+ConvToStr(i->gline_time)+" :"+i->reason);
}
for (ExemptTargetSet::const_iterator i = exemptedchans.begin(); i != exemptedchans.end(); ++i)
{
- results.push_back("223 "+user->nick+" :EXEMPT "+(*i));
+ stats.AddRow(223, "EXEMPT "+(*i));
+ }
+ for (ExemptTargetSet::const_iterator i = exemptednicks.begin(); i != exemptednicks.end(); ++i)
+ {
+ stats.AddRow(223, "EXEMPT "+(*i));
}
}
return MOD_RES_PASSTHRU;