#include "inspircd.h"
#include "xline.h"
-#include "m_regex.h"
+#include "modules/regex.h"
/* $ModDesc: Text (spam) filtering */
class ModuleFilter : public Module
{
+ bool initing;
+ RegexFactory* factory;
+ void FreeFilters();
+
public:
CommandFilter filtcommand;
dynamic_reference<RegexFactory> RegexEngine;
std::vector<ImplFilter> filters;
- const char *error;
- int erroffset;
int flags;
std::set<std::string> exemptfromfilter; // List of channel names excluded from filtering.
ModuleFilter();
void init();
+ CullResult cull();
ModResult OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list);
FilterResult* FilterMatch(User* user, const std::string &text, int flags);
bool DeleteFilter(const std::string &freeform);
void OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata);
ModResult OnStats(char symbol, User* user, string_list &results);
ModResult OnPreCommand(std::string &command, std::vector<std::string> ¶meters, LocalUser *user, bool validated, const std::string &original_line);
+ void OnUnloadModule(Module* mod);
bool AppliesToMe(User* user, FilterResult* filter, int flags);
- void ReadFilters(ConfigReader &MyConf);
+ void ReadFilters();
static bool StringToFilterAction(const std::string& str, FilterAction& fa);
static std::string FilterActionToString(FilterAction fa);
};
{
if (parameters.size() >= 5)
{
- duration = ServerInstance->Duration(parameters[3]);
+ duration = InspIRCd::Duration(parameters[3]);
reasonindex = 4;
}
else
bool ModuleFilter::AppliesToMe(User* user, FilterResult* filter, int iflags)
{
- if ((filter->flag_no_opers) && IS_OPER(user))
+ if ((filter->flag_no_opers) && user->IsOper())
return false;
if ((iflags & FLAG_PRIVMSG) && (!filter->flag_privmsg))
return false;
return true;
}
-ModuleFilter::ModuleFilter() : filtcommand(this), RegexEngine(this, "regex")
+ModuleFilter::ModuleFilter()
+ : initing(true), filtcommand(this), RegexEngine(this, "regex")
{
}
void ModuleFilter::init()
{
- ServerInstance->AddCommand(&filtcommand);
- Implementation eventlist[] = { I_OnPreCommand, I_OnStats, I_OnSyncNetwork, I_OnDecodeMetaData, I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash };
- ServerInstance->Modules->Attach(eventlist, this, 7);
+ ServerInstance->Modules->AddService(filtcommand);
+ Implementation eventlist[] = { I_OnPreCommand, I_OnStats, I_OnSyncNetwork, I_OnDecodeMetaData, I_OnUserPreMessage, I_OnUserPreNotice, I_OnRehash, I_OnUnloadModule };
+ ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
OnRehash(NULL);
}
+CullResult ModuleFilter::cull()
+{
+ FreeFilters();
+ return Module::cull();
+}
+
+void ModuleFilter::FreeFilters()
+{
+ for (std::vector<ImplFilter>::const_iterator i = filters.begin(); i != filters.end(); ++i)
+ delete i->regex;
+
+ filters.clear();
+}
+
ModResult ModuleFilter::OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
{
if (!IS_LOCAL(user))
delete gl;
}
- ServerInstance->Logs->Log("FILTER",DEFAULT,"FILTER: "+ user->nick + " had their message filtered, target was " + target + ": " + f->reason + " Action: " + ModuleFilter::FilterActionToString(f->action));
+ ServerInstance->Logs->Log("FILTER",LOG_DEFAULT,"FILTER: "+ user->nick + " had their message filtered, target was " + target + ": " + f->reason + " Action: " + ModuleFilter::FilterActionToString(f->action));
return MOD_RES_DENY;
}
return MOD_RES_PASSTHRU;
void ModuleFilter::OnRehash(User* user)
{
- ConfigReader MyConf;
+ ConfigTagList tags = ServerInstance->Config->ConfTags("exemptfromfilter");
exemptfromfilter.clear();
- for (int index = 0; index < MyConf.Enumerate("exemptfromfilter"); ++index)
+ for (ConfigIter i = tags.first; i != tags.second; ++i)
{
- std::string chan = MyConf.ReadValue("exemptfromfilter", "channel", index);
+ std::string chan = i->second->getString("channel");
if (!chan.empty())
exemptfromfilter.insert(chan);
}
- std::string newrxengine = "regex/" + MyConf.ReadValue("filteropts", "engine", 0);
- if (newrxengine == "regex/")
- newrxengine = "regex";
- if (RegexEngine.GetProvider() == newrxengine)
- return;
- //ServerInstance->SNO->WriteGlobalSno('a', "Dumping all filters due to regex engine change (was '%s', now '%s')", RegexEngine.GetProvider().c_str(), newrxengine.c_str());
- //ServerInstance->XLines->DelAll("R");
+ std::string newrxengine = ServerInstance->Config->ConfValue("filteropts")->getString("engine");
+
+ factory = RegexEngine ? (RegexEngine.operator->()) : NULL;
+
+ if (newrxengine.empty())
+ RegexEngine.SetProvider("regex");
+ else
+ RegexEngine.SetProvider("regex/" + newrxengine);
- RegexEngine.SetProvider(newrxengine);
if (!RegexEngine)
{
- ServerInstance->SNO->WriteGlobalSno('a', "WARNING: Regex engine '%s' is not loaded - Filter functionality disabled until this is corrected.", newrxengine.c_str());
+ if (newrxengine.empty())
+ ServerInstance->SNO->WriteGlobalSno('a', "WARNING: No regex engine loaded - Filter functionality disabled until this is corrected.");
+ else
+ ServerInstance->SNO->WriteGlobalSno('a', "WARNING: Regex engine '%s' is not loaded - Filter functionality disabled until this is corrected.", newrxengine.c_str());
+
+ initing = false;
+ FreeFilters();
+ return;
+ }
+
+ if ((!initing) && (RegexEngine.operator->() != factory))
+ {
+ ServerInstance->SNO->WriteGlobalSno('a', "Dumping all filters due to regex engine change");
+ FreeFilters();
}
- ReadFilters(MyConf);
+
+ initing = false;
+ ReadFilters();
}
Version ModuleFilter::GetVersion()
}
catch (ModuleException& e)
{
- ServerInstance->Logs->Log("m_filter", DEBUG, "Error when unserializing filter: " + std::string(e.GetReason()));
+ ServerInstance->Logs->Log("m_filter", LOG_DEBUG, "Error when unserializing filter: " + std::string(e.GetReason()));
}
}
}
InspIRCd::StripColor(stripped_text);
}
- //ServerInstance->Logs->Log("m_filter", DEBUG, "Match '%s' against '%s'", text.c_str(), index->freeform.c_str());
+ //ServerInstance->Logs->Log("m_filter", LOG_DEBUG, "Match '%s' against '%s'", text.c_str(), index->freeform.c_str());
if (index->regex->Matches(filter->flag_strip_color ? stripped_text : text))
{
- //ServerInstance->Logs->Log("m_filter", DEBUG, "MATCH");
+ //ServerInstance->Logs->Log("m_filter", LOG_DEBUG, "MATCH");
return &*index;
}
- //ServerInstance->Logs->Log("m_filter", DEBUG, "NO MATCH");
+ //ServerInstance->Logs->Log("m_filter", LOG_DEBUG, "NO MATCH");
}
return NULL;
}
}
catch (ModuleException &e)
{
- ServerInstance->Logs->Log("m_filter", DEFAULT, "Error in regular expression '%s': %s", freeform.c_str(), e.GetReason());
+ ServerInstance->Logs->Log("m_filter", LOG_DEFAULT, "Error in regular expression '%s': %s", freeform.c_str(), e.GetReason());
return std::make_pair(false, e.GetReason());
}
return std::make_pair(true, "");
}
}
-void ModuleFilter::ReadFilters(ConfigReader &MyConf)
+void ModuleFilter::ReadFilters()
{
- for (int index = 0; index < MyConf.Enumerate("keyword"); index++)
+ ConfigTagList tags = ServerInstance->Config->ConfTags("keyword");
+ for (ConfigIter i = tags.first; i != tags.second; ++i)
{
- this->DeleteFilter(MyConf.ReadValue("keyword", "pattern", index));
+ std::string pattern = i->second->getString("pattern");
+ this->DeleteFilter(pattern);
- std::string pattern = MyConf.ReadValue("keyword", "pattern", index);
- std::string reason = MyConf.ReadValue("keyword", "reason", index);
- std::string action = MyConf.ReadValue("keyword", "action", index);
- std::string flgs = MyConf.ReadValue("keyword", "flags", index);
- long gline_time = ServerInstance->Duration(MyConf.ReadValue("keyword", "duration", index));
+ std::string reason = i->second->getString("reason");
+ std::string action = i->second->getString("action");
+ std::string flgs = i->second->getString("flags");
+ unsigned long gline_time = InspIRCd::Duration(i->second->getString("duration"));
if (flgs.empty())
flgs = "*";
try
{
filters.push_back(ImplFilter(this, reason, fa, gline_time, pattern, flgs));
- ServerInstance->Logs->Log("m_filter", DEFAULT, "Regular expression %s loaded.", pattern.c_str());
+ ServerInstance->Logs->Log("m_filter", LOG_DEFAULT, "Regular expression %s loaded.", pattern.c_str());
}
catch (ModuleException &e)
{
- ServerInstance->Logs->Log("m_filter", DEFAULT, "Error in regular expression '%s': %s", pattern.c_str(), e.GetReason());
+ ServerInstance->Logs->Log("m_filter", LOG_DEFAULT, "Error in regular expression '%s': %s", pattern.c_str(), e.GetReason());
}
}
}
return MOD_RES_PASSTHRU;
}
+void ModuleFilter::OnUnloadModule(Module* mod)
+{
+ // If the regex engine became unavailable or has changed, remove all filters
+ if (!RegexEngine)
+ {
+ FreeFilters();
+ }
+ else if (RegexEngine.operator->() != factory)
+ {
+ factory = RegexEngine.operator->();
+ FreeFilters();
+ }
+}
+
MODULE_INIT(ModuleFilter)