]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_timedbans.cpp
f75791b2c8f1e5e6342a043004f4f98092373414
[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 /* $ModDesc: Adds timed bans */
18
19 /*
20  * ToDo:
21  *   Err... not a lot really.
22  */ 
23
24 #include <stdio.h>
25 #include <vector>
26 #include "users.h"
27 #include "channels.h"
28 #include "modules.h"
29
30 Server *Srv;
31          
32 class TimedBan
33 {
34  public:
35         std::string channel;
36         std::string mask;
37         time_t expire;
38 };
39
40 typedef std::vector<TimedBan> timedbans;
41 timedbans TimedBanList;
42
43 void handle_tban(char **parameters, int pcnt, userrec *user)
44 {
45         chanrec* channel = Srv->FindChannel(parameters[0]);
46         if (channel)
47         {
48                 std::string cm = Srv->ChanMode(user,channel);
49                 if ((cm == "%") || (cm == "@"))
50                 {
51                         if (!Srv->IsValidMask(parameters[2]))
52                         {
53                                 Srv->SendServ(user->fd,"NOTICE "+std::string(user->nick)+" :Invalid ban mask");
54                                 return;
55                         }
56                         for (timedbans::iterator i = TimedBanList.begin(); i < TimedBanList.end(); i++)
57                         {
58                                 if ((!strcasecmp(i->mask.c_str(),parameters[2])) && (!strcasecmp(i->channel.c_str(),parameters[0])))
59                                 {
60                                         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]));
61                                         return;
62                                 }
63                         }
64                         TimedBan T;
65                         std::string channelname = parameters[0];
66                         unsigned long expire = Srv->CalcDuration(parameters[1]) + time(NULL);
67                         if (Srv->CalcDuration(parameters[1]) < 1)
68                         {
69                                 Srv->SendServ(user->fd,"NOTICE "+std::string(user->nick)+" :Invalid ban time");
70                                 return;
71                         }
72                         char duration[MAXBUF];
73                         snprintf(duration,MAXBUF,"%lu",Srv->CalcDuration(parameters[1]));
74                         std::string mask = parameters[2];
75                         char *setban[3];
76                         setban[0] = parameters[0];
77                         setban[1] = "+b";
78                         setban[2] = parameters[2];
79                         // use CallCommandHandler to make it so that the user sets the mode
80                         // themselves
81                         Srv->CallCommandHandler("MODE",setban,3,user);
82                         T.channel = channelname;
83                         T.mask = mask;
84                         T.expire = expire;
85                         TimedBanList.push_back(T);
86                         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.");
87                         return;
88                 }
89                 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);
90                 return;
91         }
92         WriteServ(user->fd,"401 %s %s :No such channel",user->nick, parameters[0]);
93 }
94
95 class ModuleTimedBans : public Module
96 {
97  public:
98         ModuleTimedBans()
99         {
100                 Srv = new Server;
101                 Srv->AddCommand("TBAN",handle_tban,0,3,"m_timedbans.so");
102                 TimedBanList.clear();
103         }
104         
105         virtual ~ModuleTimedBans()
106         {
107                 delete Srv;
108                 TimedBanList.clear();
109         }
110
111         virtual void OnBackgroundTimer(time_t curtime)
112         {
113                 bool again = true;
114                 while (again)
115                 {
116                         again = false;
117                         for (timedbans::iterator i = TimedBanList.begin(); i < TimedBanList.end(); i++)
118                         {
119                                 if (curtime > i->expire)
120                                 {
121                                         chanrec* cr = Srv->FindChannel(i->channel);
122                                         again = true;
123                                         if (cr)
124                                         {
125                                                 char *setban[3];
126                                                 setban[0] = (char*)i->channel.c_str();
127                                                 setban[1] = "-b";
128                                                 setban[2] = (char*)i->mask.c_str();
129                                                 // kludge alert!
130                                                 // ::SendMode expects a userrec* to send the numeric replies
131                                                 // back to, so we create it a fake user that isnt in the user
132                                                 // hash and set its descriptor to FD_MAGIC_NUMBER so the data
133                                                 // falls into the abyss :p
134                                                 userrec* temp = new userrec;
135                                                 temp->fd = FD_MAGIC_NUMBER;
136                                                 Srv->SendMode(setban,3,temp);
137                                                 delete temp;
138                                                 Srv->SendChannelServerNotice(Srv->GetServerName(),cr,"NOTICE "+std::string(cr->name)+" :Timed ban on "+i->mask+" expired.");
139                                         }
140                                         TimedBanList.erase(i);
141                                         break;
142                                 }
143                         }
144                 }
145         }
146         
147         virtual Version GetVersion()
148         {
149                 return Version(1,0,0,0,VF_VENDOR);
150         }
151 };
152
153
154 class ModuleTimedBansFactory : public ModuleFactory
155 {
156  public:
157         ModuleTimedBansFactory()
158         {
159         }
160         
161         ~ModuleTimedBansFactory()
162         {
163         }
164         
165         virtual Module * CreateModule()
166         {
167                 return new ModuleTimedBans;
168         }
169         
170 };
171
172
173 extern "C" void * init_module( void )
174 {
175         return new ModuleTimedBansFactory;
176 }