1 /* +------------------------------------+
2 * | Inspire Internet Relay Chat Daemon |
3 * +------------------------------------+
5 * InspIRCd is copyright (C) 2002-2004 ChatSpike-Dev.
7 * <brain@chatspike.net>
8 * <Craig@chatspike.net>
10 * Written by Craig Edwards, Craig McLure, and others.
11 * This program is free but copyrighted software; see
12 * the file COPYING for details.
14 * ---------------------------------------------------
19 // Message and notice filtering using regex patterns
20 // a module based on the original work done by Craig Edwards in 2003
21 // for the chatspike network.
29 #include "helperfuncs.h"
31 class FilterPCREException : public ModuleException
34 virtual const char* GetReason()
36 return "Could not find <filter file=\"\"> definition in your config file!";
40 /* $ModDesc: m_filter with regexps */
41 /* $CompileFlags: -I/usr/local/include */
42 /* $LinkerFlags: -L/usr/local/lib -lpcre */
44 class ModuleFilterPCRE : public Module
47 ConfigReader *Conf, *MyConf;
48 std::vector<pcre*> filters;
54 ModuleFilterPCRE(Server* Me)
57 // read the configuration file on startup.
58 // it is perfectly valid to set <filter file> to the value of the
59 // main config file, then append your <keyword> tags to the bottom
60 // of the main config... but rather messy. That's why the capability
61 // of using a seperate config file is provided.
63 Conf = new ConfigReader;
64 std::string filterfile = Conf->ReadValue("filter","file",0);
65 MyConf = new ConfigReader(filterfile);
66 if ((filterfile == "") || (!MyConf->Verify()))
68 FilterPCREException e;
71 Srv->Log(DEFAULT,std::string("m_filter_pcre: read configuration from ")+filterfile);
74 for (int index = 0; index < MyConf->Enumerate("keyword"); index++)
76 std::string pattern = MyConf->ReadValue("keyword","pattern",index);
77 re = pcre_compile(pattern.c_str(),0,&error,&erroffset,NULL);
80 log(DEFAULT,"Error in regular expression: %s at offset %d: %s\n", pattern.c_str(), erroffset, error);
81 log(DEFAULT,"Regular expression %s not loaded.", pattern.c_str());
85 filters.push_back(re);
86 log(DEFAULT,"Regular expression %s loaded.", pattern.c_str());
92 virtual ~ModuleFilterPCRE()
98 void Implements(char* List)
100 List[I_OnUserPreMessage] = List[I_OnUserPreNotice] = List[I_OnRehash] = 1;
103 // format of a config entry is <keyword pattern="^regexp$" reason="Some reason here" action="kill/block">
105 virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text, char status)
107 return OnUserPreNotice(user,dest,target_type,text,status);
110 virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text, char status)
112 for (unsigned int index = 0; index < filters.size(); index++)
114 if (pcre_exec(filters[index],NULL,text.c_str(),text.length(),0,0,NULL,0) > -1)
116 std::string target = "";
117 std::string reason = MyConf->ReadValue("keyword","reason",index);
118 std::string do_action = MyConf->ReadValue("keyword","action",index);
123 if (target_type == TYPE_USER)
125 userrec* t = (userrec*)dest;
126 target = std::string(t->nick);
128 else if (target_type == TYPE_CHANNEL)
130 chanrec* t = (chanrec*)dest;
131 target = std::string(t->name);
133 if (do_action == "block")
135 Srv->SendOpers(std::string("Filter: ")+std::string(user->nick)+
136 std::string(" had their notice filtered, target was ")+
138 Srv->SendTo(NULL,user,"NOTICE "+std::string(user->nick)+
139 " :Your notice has been filtered and opers notified: "+reason);
141 Srv->Log(DEFAULT,std::string("Filter: ")+std::string(user->nick)+
142 std::string(" had their notice filtered, target was ")+
143 target+": "+reason+" Action: "+do_action);
145 if (do_action == "kill")
147 Srv->QuitUser(user,reason);
155 virtual void OnRehash(const std::string ¶meter)
157 // reload our config file on rehash - we must destroy and re-allocate the classes
158 // to call the constructor again and re-read our data.
161 Conf = new ConfigReader;
162 std::string filterfile = Conf->ReadValue("filter","file",0);
163 // this automatically re-reads the configuration file into the class
164 MyConf = new ConfigReader(filterfile);
165 if ((filterfile == "") || (!MyConf->Verify()))
167 FilterPCREException e;
168 // bail if the user forgot to create a config file
171 Srv->Log(DEFAULT,std::string("m_filter_pcre: read configuration from ")+filterfile);
174 for (int index = 0; index < MyConf->Enumerate("keyword"); index++)
176 std::string pattern = MyConf->ReadValue("keyword","pattern",index);
177 re = pcre_compile(pattern.c_str(),0,&error,&erroffset,NULL);
180 log(DEFAULT,"Error in regular expression: %s at offset %d: %s\n", pattern.c_str(), erroffset, error);
181 log(DEFAULT,"Regular expression %s not loaded.", pattern.c_str());
185 filters.push_back(re);
186 log(DEFAULT,"Regular expression %s loaded.", pattern.c_str());
192 virtual Version GetVersion()
194 // This is version 2 because version 1.x is the unreleased unrealircd module
195 return Version(3,0,0,0,VF_VENDOR);
200 // stuff down here is the module-factory stuff. For basic modules you can ignore this.
202 class ModuleFilterPCREFactory : public ModuleFactory
205 ModuleFilterPCREFactory()
209 ~ModuleFilterPCREFactory()
213 virtual Module * CreateModule(Server* Me)
215 return new ModuleFilterPCRE(Me);
221 extern "C" void * init_module( void )
223 return new ModuleFilterPCREFactory;