]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_censor.cpp
fc2c55a96a0e307b9614e0e7e007ea9f142b5f36
[user/henk/code/inspircd.git] / src / modules / m_censor.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
6  * See: http://www.inspircd.org/wiki/index.php/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15 #include "users.h"
16 #include "channels.h"
17 #include "modules.h"
18
19 typedef std::map<irc::string,irc::string> censor_t;
20
21 /* $ModDesc: Provides user and channel +G mode */
22
23 /** Handles usermode +G
24  */
25 class CensorUser : public ModeHandler
26 {
27  public:
28         CensorUser(InspIRCd* Instance) : ModeHandler(Instance, 'G', 0, 0, false, MODETYPE_USER, false) { }
29
30         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
31         {
32                 if (adding)
33                 {
34                         if (!dest->IsModeSet('G'))
35                         {
36                                 dest->SetMode('G',true);
37                                 return MODEACTION_ALLOW;
38                         }
39                 }
40                 else
41                 {
42                         if (dest->IsModeSet('G'))
43                         {
44                                 dest->SetMode('G',false);
45                                 return MODEACTION_ALLOW;
46                         }
47                 }
48
49                 return MODEACTION_DENY;
50         }
51 };
52
53 /** Handles channel mode +G
54  */
55 class CensorChannel : public ModeHandler
56 {
57  public:
58         CensorChannel(InspIRCd* Instance) : ModeHandler(Instance, 'G', 0, 0, false, MODETYPE_CHANNEL, false) { }
59
60         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
61         {
62                 if (adding)
63                 {
64                         if (!channel->IsModeSet('G'))
65                         {
66                                 channel->SetMode('G',true);
67                                 return MODEACTION_ALLOW;
68                         }
69                 }
70                 else
71                 {
72                         if (channel->IsModeSet('G'))
73                         {
74                                 channel->SetMode('G',false);
75                                 return MODEACTION_ALLOW;
76                         }
77                 }
78
79                 return MODEACTION_ALLOW;
80         }
81 };
82
83 class ModuleCensor : public Module
84 {
85
86         
87         censor_t censors;
88         CensorUser *cu;
89         CensorChannel *cc;
90  
91  public:
92         ModuleCensor(InspIRCd* Me)
93                 : Module(Me)
94         {
95                 /* Read the configuration file on startup.
96                  */
97                 OnRehash(NULL,"");
98                 cu = new CensorUser(ServerInstance);
99                 cc = new CensorChannel(ServerInstance);
100                 if (!ServerInstance->AddMode(cu, 'G') || !ServerInstance->AddMode(cc, 'G'))
101                         throw ModuleException("Could not add new modes!");
102         }
103
104         void Implements(char* List)
105         {
106                 List[I_OnRehash] = List[I_OnUserPreMessage] = List[I_OnUserPreNotice] = 1;
107         }
108
109         virtual ~ModuleCensor()
110         {
111                 ServerInstance->Modes->DelMode(cu);
112                 ServerInstance->Modes->DelMode(cc);
113                 DELETE(cu);
114                 DELETE(cc);
115         }
116
117         virtual void ReplaceLine(irc::string &text, irc::string pattern, irc::string replace)
118         {
119                 if ((!pattern.empty()) && (!text.empty()))
120                 {
121                         std::string::size_type pos;
122                         while ((pos = text.find(pattern)) != irc::string::npos)
123                         {
124                                 text.erase(pos,pattern.length());
125                                 text.insert(pos,replace);
126                         }
127                 }
128         }
129
130         // format of a config entry is <badword text="shit" replace="poo">
131         virtual int OnUserPreMessage(userrec* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
132         {
133                 if (!IS_LOCAL(user))
134                         return 0;
135
136                 bool active = false;
137
138                 if (target_type == TYPE_USER)
139                         active = ((userrec*)dest)->IsModeSet('G');
140                 else if (target_type == TYPE_CHANNEL)
141                         active = ((chanrec*)dest)->IsModeSet('G');
142
143                 if (!active)
144                         return 0;
145
146                 irc::string text2 = text.c_str();
147                 for (censor_t::iterator index = censors.begin(); index != censors.end(); index++)
148                 { 
149                         if (text2.find(index->first) != irc::string::npos)
150                         {
151                                 if (index->second.empty())
152                                 {
153                                         user->WriteServ("936 %s %s %s :Your message contained a censored word, and was blocked", user->nick, ((chanrec*)dest)->name, index->first.c_str());
154                                         return 1;
155                                 }
156                                 
157                                 this->ReplaceLine(text2,index->first,index->second);
158                         }
159                 }
160                 text = text2.c_str();
161                 return 0;
162         }
163         
164         virtual int OnUserPreNotice(userrec* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
165         {
166                 return OnUserPreMessage(user,dest,target_type,text,status,exempt_list);
167         }
168         
169         virtual void OnRehash(userrec* user, const std::string &parameter)
170         {
171                 /*
172                  * reload our config file on rehash - we must destroy and re-allocate the classes
173                  * to call the constructor again and re-read our data.
174                  */
175                 ConfigReader* MyConf = new ConfigReader(ServerInstance);
176                 censors.clear();
177                 for (int index = 0; index < MyConf->Enumerate("badword"); index++)
178                 {
179                         irc::string pattern = (MyConf->ReadValue("badword","text",index)).c_str();
180                         irc::string replace = (MyConf->ReadValue("badword","replace",index)).c_str();
181                         censors[pattern] = replace;
182                 }
183                 DELETE(MyConf);
184         }
185         
186         virtual Version GetVersion()
187         {
188                 return Version(1,1,0,0,VF_COMMON|VF_VENDOR,API_VERSION);
189         }
190         
191 };
192
193 // stuff down here is the module-factory stuff. For basic modules you can ignore this.
194
195 class ModuleCensorFactory : public ModuleFactory
196 {
197  public:
198         ModuleCensorFactory()
199         {
200         }
201         
202         ~ModuleCensorFactory()
203         {
204         }
205         
206         virtual Module * CreateModule(InspIRCd* Me)
207         {
208                 return new ModuleCensor(Me);
209         }
210         
211 };
212
213
214 extern "C" DllExport void * init_module( void )
215 {
216         return new ModuleCensorFactory;
217 }