]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_timedbans.cpp
Changed to use __single_client_alloc, faster on most systems in a single thread
[user/henk/code/inspircd.git] / src / modules / m_timedbans.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  Inspire is copyright (C) 2002-2004 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 using namespace std;
18
19 /* $ModDesc: Adds timed bans */
20
21 #include <stdio.h>
22 #include <vector>
23 #include "users.h"
24 #include "channels.h"
25 #include "modules.h"
26 #include "helperfuncs.h"
27 #include "hashcomp.h"
28
29 Server *Srv;
30          
31 class TimedBan
32 {
33  public:
34         std::string channel;
35         std::string mask;
36         time_t expire;
37 };
38
39 typedef std::vector<TimedBan> timedbans;
40 timedbans TimedBanList;
41
42 void handle_tban(char **parameters, int pcnt, userrec *user)
43 {
44         chanrec* channel = Srv->FindChannel(parameters[0]);
45         if (channel)
46         {
47                 std::string cm = Srv->ChanMode(user,channel);
48                 if ((cm == "%") || (cm == "@"))
49                 {
50                         if (!Srv->IsValidMask(parameters[2]))
51                         {
52                                 Srv->SendServ(user->fd,"NOTICE "+std::string(user->nick)+" :Invalid ban mask");
53                                 return;
54                         }
55                         for (timedbans::iterator i = TimedBanList.begin(); i < TimedBanList.end(); i++)
56                         {
57                                 irc::string listitem = i->mask.c_str();
58                                 irc::string target = parameters[2];
59                                 irc::string listchan = i->channel.c_str();
60                                 irc::string targetchan = parameters[0];
61                                 if ((listitem == target) && (listchan == targetchan))
62                                 {
63                                         Srv->SendServ(user->fd,"NOTICE "+std::string(user->nick)+" :The ban "+std::string(parameters[2])+" is already on the banlist of "+std::string(parameters[0]));
64                                         return;
65                                 }
66                         }
67                         TimedBan T;
68                         std::string channelname = parameters[0];
69                         unsigned long expire = Srv->CalcDuration(parameters[1]) + time(NULL);
70                         if (Srv->CalcDuration(parameters[1]) < 1)
71                         {
72                                 Srv->SendServ(user->fd,"NOTICE "+std::string(user->nick)+" :Invalid ban time");
73                                 return;
74                         }
75                         char duration[MAXBUF];
76                         snprintf(duration,MAXBUF,"%lu",Srv->CalcDuration(parameters[1]));
77                         std::string mask = parameters[2];
78                         char *setban[3];
79                         setban[0] = parameters[0];
80                         setban[1] = "+b";
81                         setban[2] = parameters[2];
82                         // use CallCommandHandler to make it so that the user sets the mode
83                         // themselves
84                         Srv->CallCommandHandler("MODE",setban,3,user);
85                         T.channel = channelname;
86                         T.mask = mask;
87                         T.expire = expire;
88                         TimedBanList.push_back(T);
89                         Srv->SendChannelServerNotice(Srv->GetServerName(),channel,"NOTICE "+std::string(channel->name)+" :"+std::string(user->nick)+" added a timed ban on "+mask+" lasting for "+std::string(duration)+" seconds.");
90                         return;
91                 }
92                 else WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, channel->name);
93                 return;
94         }
95         WriteServ(user->fd,"401 %s %s :No such channel",user->nick, parameters[0]);
96 }
97
98 class ModuleTimedBans : public Module
99 {
100  public:
101         ModuleTimedBans()
102         {
103                 Srv = new Server;
104                 Srv->AddCommand("TBAN",handle_tban,0,3,"m_timedbans.so");
105                 TimedBanList.clear();
106         }
107         
108         virtual ~ModuleTimedBans()
109         {
110                 delete Srv;
111                 TimedBanList.clear();
112         }
113
114         virtual int OnDelBan(userrec* source, chanrec* chan, std::string banmask)
115         {
116                 for (timedbans::iterator i = TimedBanList.begin(); i < TimedBanList.end(); i++)
117                 {
118                         irc::string listitem = banmask.c_str();
119                         irc::string target = i->mask.c_str();
120                         if (listitem == target)
121                         {
122                                 TimedBanList.erase(i);
123                                 break;
124                         }
125                 }
126                 return 0;
127         }
128
129         virtual void OnBackgroundTimer(time_t curtime)
130         {
131                 bool again = true;
132                 while (again)
133                 {
134                         again = false;
135                         for (timedbans::iterator i = TimedBanList.begin(); i < TimedBanList.end(); i++)
136                         {
137                                 if (curtime > i->expire)
138                                 {
139                                         chanrec* cr = Srv->FindChannel(i->channel);
140                                         again = true;
141                                         if (cr)
142                                         {
143                                                 Srv->SendChannelServerNotice(Srv->GetServerName(),cr,"NOTICE "+std::string(cr->name)+" :Timed ban on "+i->mask+" expired.");
144                                                 char *setban[3];
145                                                 setban[0] = (char*)i->channel.c_str();
146                                                 setban[1] = "-b";
147                                                 setban[2] = (char*)i->mask.c_str();
148                                                 // kludge alert!
149                                                 // ::SendMode expects a userrec* to send the numeric replies
150                                                 // back to, so we create it a fake user that isnt in the user
151                                                 // hash and set its descriptor to FD_MAGIC_NUMBER so the data
152                                                 // falls into the abyss :p
153                                                 userrec* temp = new userrec;
154                                                 temp->fd = FD_MAGIC_NUMBER;
155                                                 Srv->SendMode(setban,3,temp);
156                                                 delete temp;
157                                         }
158                                         // we used to delete the item here, but we dont need to as the servermode above does it for us,
159                                         break;
160                                 }
161                         }
162                 }
163         }
164         
165         virtual Version GetVersion()
166         {
167                 return Version(1,0,0,0,VF_VENDOR);
168         }
169 };
170
171
172 class ModuleTimedBansFactory : public ModuleFactory
173 {
174  public:
175         ModuleTimedBansFactory()
176         {
177         }
178         
179         ~ModuleTimedBansFactory()
180         {
181         }
182         
183         virtual Module * CreateModule()
184         {
185                 return new ModuleTimedBans;
186         }
187         
188 };
189
190
191 extern "C" void * init_module( void )
192 {
193         return new ModuleTimedBansFactory;
194 }