]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_cban.cpp
Fixes and removal of Server::GetServerName()
[user/henk/code/inspircd.git] / src / modules / m_cban.cpp
1 /*      +------------------------------------+
2  *      | Inspire Internet Relay Chat Daemon |
3  *      +------------------------------------+
4  *
5  * InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                    E-mail:
7  *              <brain@chatspike.net>
8  *              <Craig@chatspike.net>
9  *                <omster@gmail.com>
10  * 
11  * Written by Craig Edwards, Craig McLure, and others.
12  * This program is free but copyrighted software; see
13  * the file COPYING for details.
14  *
15  * ---------------------------------------------------
16  */
17
18 #include <algorithm>
19 #include <vector>
20 #include <string>
21 #include <sstream>
22 #include "users.h"
23 #include "channels.h"
24 #include "modules.h"
25 #include "helperfuncs.h"
26 #include "hashcomp.h"
27 #include "configreader.h"
28 #include "inspircd.h"
29
30 /* $ModDesc: Gives /cban, aka C:lines. Think Q:lines, for channels. */
31
32 extern InspIRCd* ServerInstance;
33
34 class CBan : public classbase
35 {
36 public:
37         irc::string chname;
38         std::string set_by;
39         time_t set_on;
40         long length;
41         std::string reason;
42
43         CBan()
44         {
45         }
46
47         CBan(irc::string cn, std::string sb, time_t so, long ln, std::string rs) : chname(cn), set_by(sb), set_on(so), length(ln), reason(rs)
48         {
49         }
50 };
51
52 std::string EncodeCBan(const CBan &ban);
53 CBan DecodeCBan(const std::string &data);
54 bool CBanComp(const CBan &ban1, const CBan &ban2);
55 void ExpireBans();
56
57 extern time_t TIME;
58 typedef std::vector<CBan> cbanlist;
59
60 /* cbans is declared here, as our type is right above. Don't try move it. */
61 cbanlist cbans;
62
63 class cmd_cban : public command_t
64 {
65  private:
66         Server *Srv;
67
68  public:
69         cmd_cban(Server* Me) : command_t("CBAN", 'o', 1)
70         {
71                 this->source = "m_cban.so";
72                 this->Srv = Me;
73                 syntax = "<channel> [<duration> :<reason>]";
74         }
75
76         void Handle(const char** parameters, int pcnt, userrec *user)
77         {
78                 /* syntax: CBAN #channel time :reason goes here */
79                 /* 'time' is a human-readable timestring, like 2d3h2s. */
80                 
81                 ExpireBans();
82
83                 if(pcnt == 1)
84                 {
85                         /* form: CBAN #channel removes a CBAN */
86                         for (cbanlist::iterator iter = cbans.begin(); iter != cbans.end(); iter++)
87                         {
88                                 if (parameters[0] == iter->chname)
89                                 {
90                                         unsigned long remaining = (iter->set_on + iter->length) - TIME;
91                                         user->WriteServ( "386 %s %s :Removed CBAN with %lu seconds left before expiry (%s)", user->nick, iter->chname.c_str(), remaining, iter->reason.c_str());
92                                         cbans.erase(iter);
93                                         break;
94                                 }
95                         }
96                 }
97                 else if (pcnt >= 2)
98                 {
99                         /* full form to add a CBAN */
100                         if (IsValidChannelName(parameters[0]))
101                         {
102                                 // parameters[0] = #channel
103                                 // parameters[1] = 1h3m2s
104                                 // parameters[2] = Tortoise abuser
105                                 long length = Srv->CalcDuration(parameters[1]);
106                                 std::string reason = (pcnt > 2) ? parameters[2] : "No reason supplied";
107                                 
108                                 cbans.push_back(CBan(parameters[0], user->nick, TIME, length, reason));
109                                         
110                                 std::sort(cbans.begin(), cbans.end(), CBanComp);
111                                 
112                                 if(length > 0)
113                                 {
114                                         user->WriteServ( "385 %s %s :Added %lu second channel ban (%s)", user->nick, parameters[0], length, reason.c_str());
115                                         ServerInstance->WriteOpers("*** %s added %lu second channel ban on %s (%s)", user->nick, length, parameters[0], reason.c_str());
116                                 }
117                                 else
118                                 {
119                                         user->WriteServ( "385 %s %s :Added permenant channel ban (%s)", user->nick, parameters[0], reason.c_str());
120                                         ServerInstance->WriteOpers("*** %s added permenant channel ban on %s (%s)", user->nick, parameters[0], reason.c_str());
121                                 }
122                         }
123                         else
124                         {
125                                 user->WriteServ( "403 %s %s :Invalid channel name", user->nick, parameters[0]);
126                         }
127                 }
128         }
129 };
130
131 class ModuleCBan : public Module
132 {
133         cmd_cban* mycommand;
134         Server* Srv;
135
136  public:
137         ModuleCBan(Server* Me) : Module::Module(Me)
138         {
139                 Srv = Me;
140                 mycommand = new cmd_cban(Srv);
141                 Srv->AddCommand(mycommand);
142         }
143
144         void Implements(char* List)
145         {
146                 List[I_OnUserPreJoin] = List[I_OnSyncOtherMetaData] = List[I_OnDecodeMetaData] = List[I_OnStats] = 1;
147         }
148         
149         virtual int OnStats(char symbol, userrec* user, string_list &results)
150         {
151                 ExpireBans();
152         
153                 if(symbol == 'C')
154                 {
155                         for(cbanlist::iterator iter = cbans.begin(); iter != cbans.end(); iter++)
156                         {
157                                 unsigned long remaining = (iter->set_on + iter->length) - TIME;
158                                 results.push_back(std::string(ServerInstance->Config->ServerName)+" 210 "+user->nick+" "+iter->chname.c_str()+" "+iter->set_by+" "+ConvToStr(iter->set_on)+" "+ConvToStr(iter->length)+" "+ConvToStr(remaining)+" :"+iter->reason);
159                         }
160                 }
161                 
162                 return 0;
163         }
164
165         virtual int OnUserPreJoin(userrec *user, chanrec *chan, const char *cname)
166         {
167                 ExpireBans();
168         
169                 /* check cbans in here, and apply as necessary. */
170                 for(cbanlist::iterator iter = cbans.begin(); iter != cbans.end(); iter++)
171                 {
172                         if(iter->chname == cname && !user->modes[UM_OPERATOR])
173                         {
174                                 // Channel is banned.
175                                 user->WriteServ( "384 %s %s :Cannot join channel, CBANed (%s)", user->nick, cname, iter->reason.c_str());
176                                 ServerInstance->WriteOpers("*** %s tried to join %s which is CBANed (%s)", user->nick, cname, iter->reason.c_str());
177                                 return 1;
178                         }
179                 }
180                 return 0;
181         }
182         
183         virtual void OnSyncOtherMetaData(Module* proto, void* opaque)
184         {
185                 for(cbanlist::iterator iter = cbans.begin(); iter != cbans.end(); iter++)
186                 {
187                         proto->ProtoSendMetaData(opaque, TYPE_OTHER, NULL, "cban", EncodeCBan(*iter));
188                 }
189         }
190         
191         virtual void OnDecodeMetaData(int target_type, void* target, const std::string &extname, const std::string &extdata)
192         {
193                 if((target_type == TYPE_OTHER) && (extname == "cban"))
194                 {
195                         cbans.push_back(DecodeCBan(extdata));
196                         std::sort(cbans.begin(), cbans.end(), CBanComp);
197                 }
198         }
199
200         virtual ~ModuleCBan()
201         {
202         }
203         
204         virtual Version GetVersion()
205         {
206                 return Version(1,0,0,1,VF_VENDOR);
207         }
208 };
209
210 std::string EncodeCBan(const CBan &ban)
211 {
212         std::ostringstream stream;      
213         stream << ban.chname << " " << ban.set_by << " " << ban.set_on << " " << ban.length << " " << ban.reason;
214         return stream.str();    
215 }
216
217 CBan DecodeCBan(const std::string &data)
218 {
219         CBan res;
220         std::istringstream stream(data);
221         stream >> res.chname;
222         stream >> res.set_by;
223         stream >> res.set_on;
224         stream >> res.length;
225         res.reason = stream.str();
226         
227         return res;
228 }
229
230 bool CBanComp(const CBan &ban1, const CBan &ban2)
231 {
232         return ((ban1.set_on + ban1.length) < (ban2.set_on + ban2.length));
233 }
234
235 void ExpireBans()
236 {
237         bool go_again = true;
238
239         while (go_again)
240         {
241                 go_again = false;
242
243                 for (cbanlist::iterator iter = cbans.begin(); iter != cbans.end(); iter++)
244                 {
245                         /* 0 == permanent, don't mess with them! -- w00t */
246                         if (iter->length != 0)
247                         {
248                                 if (iter->set_on + iter->length <= TIME)
249                                 {
250                                         log(DEBUG, "m_cban.so: Ban on %s expired, removing...", iter->chname.c_str());
251                                         ServerInstance->WriteOpers("*** %li second CBAN on %s (%s) set %u seconds ago expired", iter->length, iter->chname.c_str(), iter->reason.c_str(), TIME - iter->set_on);
252                                         cbans.erase(iter);
253                                         go_again = true;
254                                 }
255                         }
256
257                         if (go_again == true)
258                                 break;
259                 }
260         }
261 }
262
263 class ModuleCBanFactory : public ModuleFactory
264 {
265  public:
266         ModuleCBanFactory()
267         {
268         }
269         
270         ~ModuleCBanFactory()
271         {
272         }
273         
274         virtual Module * CreateModule(Server* Me)
275         {
276                 return new ModuleCBan(Me);
277         }
278         
279 };
280
281
282 extern "C" void * init_module( void )
283 {
284         return new ModuleCBanFactory;
285 }