]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_filter.cpp
Merge insp20
[user/henk/code/inspircd.git] / src / modules / m_filter.cpp
index 6105fe02438927621ddcd37b2ca7a77c7fb62baa..8bfefd6eb412559f9a17149add53ef22ad11f703 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "inspircd.h"
 #include "xline.h"
-#include "m_regex.h"
+#include "modules/regex.h"
 
 /* $ModDesc: Text (spam) filtering */
 
@@ -165,19 +165,22 @@ class ImplFilter : public FilterResult
 
 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);
@@ -191,8 +194,9 @@ class ModuleFilter : public Module
        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> &parameters, 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);
 };
@@ -236,7 +240,7 @@ CmdResult CommandFilter::Handle(const std::vector<std::string> &parameters, User
                        {
                                if (parameters.size() >= 5)
                                {
-                                       duration = ServerInstance->Duration(parameters[3]);
+                                       duration = InspIRCd::Duration(parameters[3]);
                                        reasonindex = 4;
                                }
                                else
@@ -279,7 +283,7 @@ CmdResult CommandFilter::Handle(const std::vector<std::string> &parameters, User
 
 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;
@@ -292,18 +296,33 @@ bool ModuleFilter::AppliesToMe(User* user, FilterResult* filter, int iflags)
        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))
@@ -369,7 +388,7 @@ ModResult ModuleFilter::OnUserPreNotice(User* user,void* dest,int target_type, s
                                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;
@@ -449,29 +468,44 @@ ModResult ModuleFilter::OnPreCommand(std::string &command, std::vector<std::stri
 
 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()
@@ -539,7 +573,7 @@ void ModuleFilter::OnDecodeMetaData(Extensible* target, const std::string &extna
                }
                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()));
                }
        }
 }
@@ -571,13 +605,13 @@ FilterResult* ModuleFilter::FilterMatch(User* user, const std::string &text, int
                        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;
 }
@@ -612,7 +646,7 @@ std::pair<bool, std::string> ModuleFilter::AddFilter(const std::string &freeform
        }
        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, "");
@@ -650,17 +684,18 @@ std::string ModuleFilter::FilterActionToString(FilterAction fa)
        }
 }
 
-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 = "*";
 
@@ -671,11 +706,11 @@ void ModuleFilter::ReadFilters(ConfigReader &MyConf)
                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());
                }
        }
 }
@@ -696,4 +731,18 @@ ModResult ModuleFilter::OnStats(char symbol, User* user, string_list &results)
        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)