+class ImplFilter : public FilterResult
+{
+ public:
+ Regex* regex;
+
+ ImplFilter(Module* 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 (!rxengine)
+ throw ModuleException("Regex module implementing '"+RegexEngine+"' is not loaded!");
+
+ regex = RegexFactoryRequest(mymodule, rxengine, pat).Create();
+ }
+
+ ImplFilter()
+ {
+ }
+};
+
+class ModuleFilter : public FilterBase
+{
+ std::vector<ImplFilter> filters;
+ const char *error;
+ int erroffset;
+ ImplFilter fr;
+
+ public:
+ ModuleFilter(InspIRCd* Me)
+ : FilterBase(Me, "m_filter.so")
+ {
+ OnRehash(NULL,"");
+ }
+
+ virtual ~ModuleFilter()
+ {
+ }
+
+ virtual FilterResult* 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 (!FilterBase::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))
+ {
+ //ServerInstance->Logs->Log("m_filter", DEBUG, "MATCH");
+ fr = *index;
+ if (index != filters.begin())
+ {
+ /* Move to head of list for efficiency */
+ filters.erase(index);
+ filters.insert(filters.begin(), fr);
+ }
+ return &fr;
+ }
+ //ServerInstance->Logs->Log("m_filter", DEBUG, "NO MATCH");
+ }
+ return NULL;
+ }
+
+ virtual bool DeleteFilter(const std::string &freeform)
+ {
+ for (std::vector<ImplFilter>::iterator i = filters.begin(); i != filters.end(); i++)
+ {
+ if (i->freeform == freeform)
+ {
+ delete i->regex;
+ filters.erase(i);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ virtual void SyncFilters(Module* proto, void* opaque)
+ {
+ for (std::vector<ImplFilter>::iterator i = filters.begin(); i != filters.end(); i++)
+ {
+ this->SendFilter(proto, opaque, &(*i));
+ }
+ }
+
+ virtual std::pair<bool, std::string> AddFilter(const std::string &freeform, const std::string &type, const std::string &reason, long duration, const std::string &flgs)
+ {
+ for (std::vector<ImplFilter>::iterator i = filters.begin(); i != filters.end(); i++)
+ {
+ if (i->freeform == freeform)
+ {
+ return std::make_pair(false, "Filter already exists");
+ }
+ }
+
+ try
+ {
+ filters.push_back(ImplFilter(this, reason, type, duration, freeform, flgs));
+ }
+ catch (ModuleException &e)
+ {
+ ServerInstance->Logs->Log("m_filter", DEFAULT, "Error in regular expression '%s': %s", freeform.c_str(), e.GetReason());
+ return std::make_pair(false, e.GetReason());
+ }
+ return std::make_pair(true, "");
+ }
+
+ virtual void OnRehash(User* user, const std::string ¶meter)
+ {
+ ConfigReader MyConf(ServerInstance);
+ FilterBase::OnRehash(user, parameter);
+ ReadFilters(MyConf);
+ }
+
+ void ReadFilters(ConfigReader &MyConf)
+ {
+ for (int index = 0; index < MyConf.Enumerate("keyword"); index++)
+ {
+ this->DeleteFilter(MyConf.ReadValue("keyword", "pattern", index));
+
+ 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));
+ if (action.empty())
+ action = "none";
+ if (flgs.empty())
+ flgs = "*";
+
+ try
+ {
+ filters.push_back(ImplFilter(this, reason, action, gline_time, pattern, flgs));
+ ServerInstance->Logs->Log("m_filter", 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());
+ }
+ }
+ }
+
+ virtual int OnStats(char symbol, User* user, string_list &results)
+ {
+ if (symbol == 's')
+ {
+ std::string sn = ServerInstance->Config->ServerName;
+ for (std::vector<ImplFilter>::iterator i = filters.begin(); i != filters.end(); i++)
+ {
+ results.push_back(sn+" 223 "+user->nick+" :"+RegexEngine+":"+i->freeform+" "+i->flags+" "+i->action+" "+ConvToStr(i->gline_time)+" :"+i->reason);
+ }
+ for (std::vector<std::string>::iterator i = exemptfromfilter.begin(); i != exemptfromfilter.end(); ++i)
+ {
+ results.push_back(sn+" 223 "+user->nick+" :EXEMPT "+(*i));
+ }
+ }
+ return 0;
+ }
+};
+
+MODULE_INIT(ModuleFilter)