]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_censor.cpp
1c7a9999c99bba516c67285cf37bc81512ac9cdb
[user/henk/code/inspircd.git] / src / modules / m_censor.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2008 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 #define _CRT_SECURE_NO_DEPRECATE
15 #define _SCL_SECURE_NO_DEPRECATE
16
17 #include "inspircd.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(User* source, User* dest, Channel* 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(User* source, User* dest, Channel* 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) || !ServerInstance->AddMode(cc))
101                 {
102                         delete cu;
103                         delete cc;
104                         throw ModuleException("Could not add new modes!");
105                 }
106                 Implementation eventlist[] = { I_OnRehash, I_OnUserPreMessage, I_OnUserPreNotice };
107                 ServerInstance->Modules->Attach(eventlist, this, 3);
108         }
109
110
111         virtual ~ModuleCensor()
112         {
113                 ServerInstance->Modes->DelMode(cu);
114                 ServerInstance->Modes->DelMode(cc);
115                 delete cu;
116                 delete cc;
117         }
118
119         virtual void ReplaceLine(irc::string &text, irc::string pattern, irc::string replace)
120         {
121                 if ((!pattern.empty()) && (!text.empty()))
122                 {
123                         std::string::size_type pos;
124                         while ((pos = text.find(pattern)) != irc::string::npos)
125                         {
126                                 text.erase(pos,pattern.length());
127                                 text.insert(pos,replace);
128                         }
129                 }
130         }
131
132         // format of a config entry is <badword text="shit" replace="poo">
133         virtual int OnUserPreMessage(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
134         {
135                 if (!IS_LOCAL(user))
136                         return 0;
137
138                 bool active = false;
139
140                 if (target_type == TYPE_USER)
141                         active = ((User*)dest)->IsModeSet('G');
142                 else if (target_type == TYPE_CHANNEL)
143                         active = ((Channel*)dest)->IsModeSet('G');
144
145                 if (!active)
146                         return 0;
147
148                 irc::string text2 = text.c_str();
149                 for (censor_t::iterator index = censors.begin(); index != censors.end(); index++)
150                 { 
151                         if (text2.find(index->first) != irc::string::npos)
152                         {
153                                 if (index->second.empty())
154                                 {
155                                         user->WriteServ("936 %s %s %s :Your message contained a censored word, and was blocked", user->nick, ((Channel*)dest)->name, index->first.c_str());
156                                         return 1;
157                                 }
158                                 
159                                 this->ReplaceLine(text2,index->first,index->second);
160                         }
161                 }
162                 text = text2.c_str();
163                 return 0;
164         }
165         
166         virtual int OnUserPreNotice(User* user,void* dest,int target_type, std::string &text, char status, CUList &exempt_list)
167         {
168                 return OnUserPreMessage(user,dest,target_type,text,status,exempt_list);
169         }
170         
171         virtual void OnRehash(User* user, const std::string &parameter)
172         {
173                 /*
174                  * reload our config file on rehash - we must destroy and re-allocate the classes
175                  * to call the constructor again and re-read our data.
176                  */
177                 ConfigReader* MyConf = new ConfigReader(ServerInstance);
178                 censors.clear();
179
180                 for (int index = 0; index < MyConf->Enumerate("badword"); index++)
181                 {
182                         irc::string pattern = (MyConf->ReadValue("badword","text",index)).c_str();
183                         irc::string replace = (MyConf->ReadValue("badword","replace",index)).c_str();
184                         censors[pattern] = replace;
185                 }
186
187                 delete MyConf;
188         }
189         
190         virtual Version GetVersion()
191         {
192                 return Version(1,1,0,0,VF_COMMON|VF_VENDOR,API_VERSION);
193         }
194         
195 };
196
197 MODULE_INIT(ModuleCensor)