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