+ std::string chan = MyConf.ReadValue("exemptfromfilter", "channel", index);
+ if (!chan.empty()) {
+ exemptfromfilter.push_back(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");
+
+ 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());
+ }
+ ReadFilters(MyConf);
+}
+
+Version ModuleFilter::GetVersion()
+{
+ return Version("Text (spam) filtering", VF_VENDOR | VF_COMMON, RegexEngine ? RegexEngine->name : "");
+}
+
+
+std::string ModuleFilter::EncodeFilter(FilterResult* filter)
+{
+ std::ostringstream stream;
+ std::string x = filter->freeform;
+
+ /* Hax to allow spaces in the freeform without changing the design of the irc protocol */
+ for (std::string::iterator n = x.begin(); n != x.end(); n++)
+ if (*n == ' ')
+ *n = '\7';
+
+ stream << x << " " << filter->action << " " << (filter->flags.empty() ? "-" : filter->flags) << " " << filter->gline_time << " :" << filter->reason;
+ return stream.str();
+}
+
+FilterResult ModuleFilter::DecodeFilter(const std::string &data)
+{
+ FilterResult res;
+ irc::tokenstream tokens(data);
+ tokens.GetToken(res.freeform);
+ tokens.GetToken(res.action);
+ tokens.GetToken(res.flags);
+ if (res.flags == "-")
+ res.flags = "";
+ res.FillFlags(res.flags);
+ tokens.GetToken(res.gline_time);
+ tokens.GetToken(res.reason);
+
+ /* Hax to allow spaces in the freeform without changing the design of the irc protocol */
+ for (std::string::iterator n = res.freeform.begin(); n != res.freeform.end(); n++)
+ if (*n == '\7')
+ *n = ' ';
+
+ return res;
+}
+
+void ModuleFilter::OnSyncNetwork(Module* proto, void* opaque)
+{
+ this->SyncFilters(proto, opaque);
+}
+
+void ModuleFilter::SendFilter(Module* proto, void* opaque, FilterResult* iter)
+{
+ proto->ProtoSendMetaData(opaque, NULL, "filter", EncodeFilter(iter));
+}
+
+void ModuleFilter::OnDecodeMetaData(Extensible* target, const std::string &extname, const std::string &extdata)
+{
+ if ((target == NULL) && (extname == "filter"))
+ {
+ FilterResult data = DecodeFilter(extdata);
+ this->AddFilter(data.freeform, data.action, data.reason, data.gline_time, data.flags);
+ }
+}
+
+ImplFilter::ImplFilter(ModuleFilter* mymodule, const std::string &rea, const std::string &act, long glinetime, const std::string &pat, const std::string &flgs)
+ : FilterResult(pat, rea, act, glinetime, flgs)
+{
+ if (!mymodule->RegexEngine)
+ throw ModuleException("Regex module implementing '"+mymodule->RegexEngine.GetProvider()+"' is not loaded!");
+ regex = mymodule->RegexEngine->Create(pat);
+}
+
+FilterResult* ModuleFilter::FilterMatch(User* user, const std::string &text, int flgs)
+{
+ for (std::vector<ImplFilter>::iterator index = filters.begin(); index != filters.end(); index++)
+ {
+ /* Skip ones that dont apply to us */
+ if (!AppliesToMe(user, dynamic_cast<FilterResult*>(&(*index)), flgs))
+ continue;
+
+ //ServerInstance->Logs->Log("m_filter", DEBUG, "Match '%s' against '%s'", text.c_str(), index->freeform.c_str());
+ if (index->regex->Matches(text))