]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_kicknorejoin.cpp
790e8f680e186d01db6617c883c2e2a1b874aae4
[user/henk/code/inspircd.git] / src / modules / m_kicknorejoin.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2007 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 #include "inspircd.h"
15 #include <sstream>
16 #include "users.h"
17 #include "channels.h"
18 #include "modules.h"
19
20 /* $ModDesc: Provides channel mode +J (delay rejoin after kick) */
21
22 inline int strtoint(const std::string &str)
23 {
24         std::istringstream ss(str);
25         int result;
26         ss >> result;
27         return result;
28 }
29
30 typedef std::map<userrec*, time_t> delaylist;
31
32 /** Handles channel mode +J
33  */
34 class KickRejoin : public ModeHandler
35 {
36  public:
37         KickRejoin(InspIRCd* Instance) : ModeHandler(Instance, 'J', 1, 0, false, MODETYPE_CHANNEL, false) { }
38
39         ModePair ModeSet(userrec* source, userrec* dest, chanrec* channel, const std::string &parameter)
40         {
41                 if (channel->IsModeSet('J'))
42                         return std::make_pair(true, channel->GetModeParameter('J'));
43                 else
44                         return std::make_pair(false, parameter);
45         } 
46
47         bool CheckTimeStamp(time_t theirs, time_t ours, const std::string &their_param, const std::string &our_param, chanrec* channel)
48         {
49                 /* When TS is equal, the alphabetically later one wins */
50                 return (their_param < our_param);
51         }
52         
53         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
54         {
55                 if (!adding)
56                 {
57                         // Taking the mode off, we need to clean up.
58                         delaylist* dl;
59                         
60                         if (channel->GetExt("norejoinusers", dl))
61                         {
62                                 DELETE(dl);
63                                 channel->Shrink("norejoinusers");
64                         }
65                         
66                         if (!channel->IsModeSet('J'))
67                         {
68                                 return MODEACTION_DENY;
69                         }
70                         else
71                         {
72                                 channel->SetMode('J', false);
73                                 return MODEACTION_ALLOW;
74                         }
75                 }
76                 else if (atoi(parameter.c_str()) > 0)
77                 {
78                         if (!channel->IsModeSet('J'))
79                         {
80                                 parameter = ConvToStr(atoi(parameter.c_str()));
81                                 channel->SetModeParam('J', parameter.c_str(), adding);
82                                 channel->SetMode('J', adding);
83                                 return MODEACTION_ALLOW;
84                         }
85                         else
86                         {
87                                 std::string cur_param = channel->GetModeParameter('J');
88                                 if (cur_param == parameter)
89                                 {
90                                         // mode params match, don't change mode
91                                         return MODEACTION_DENY;
92                                 }
93                                 else
94                                 {
95                                         // new mode param, replace old with new
96                                         parameter = ConvToStr(atoi(parameter.c_str()));
97                                         cur_param = ConvToStr(atoi(cur_param.c_str()));
98                                         if (parameter != "0")
99                                         {
100                                                 channel->SetModeParam('J', cur_param.c_str(), false);
101                                                 channel->SetModeParam('J', parameter.c_str(), adding);
102                                                 return MODEACTION_ALLOW;
103                                         }
104                                         else
105                                         {
106                                                 /* Fix to jamie's fix, dont allow +J 0 on the new value! */
107                                                 return MODEACTION_DENY;
108                                         }
109                                 }
110                         }
111                 }
112                 else
113                 {
114                         return MODEACTION_DENY;
115                 }
116         }
117 };
118
119 class ModuleKickNoRejoin : public Module
120 {
121         
122         KickRejoin* kr;
123         
124 public:
125  
126         ModuleKickNoRejoin(InspIRCd* Me)
127                 : Module(Me)
128         {
129                 
130                 kr = new KickRejoin(ServerInstance);
131                 if (!ServerInstance->AddMode(kr, 'J'))
132                         throw ModuleException("Could not add new modes!");
133         }
134
135         virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname, std::string &privs)
136         {
137                 if (chan)
138                 {
139                         delaylist* dl;
140                         if (chan->GetExt("norejoinusers", dl))
141                         {
142                                 std::vector<userrec*> itemstoremove;
143                         
144                                 for (delaylist::iterator iter = dl->begin(); iter != dl->end(); iter++)
145                                 {
146                                         if (iter->second > time(NULL))
147                                         {
148                                                 if (iter->first == user)                                        
149                                                 {
150                                                         user->WriteServ( "495 %s %s :You cannot rejoin this channel yet after being kicked (+J)", user->nick, chan->name);
151                                                         return 1;
152                                                 }
153                                         }
154                                         else
155                                         {
156                                                 // Expired record, remove.
157                                                 itemstoremove.push_back(iter->first);
158                                         }
159                                 }
160                                 
161                                 for (unsigned int i = 0; i < itemstoremove.size(); i++)
162                                         dl->erase(itemstoremove[i]);
163                                                                                                                                         
164                                 if (!dl->size())
165                                 {
166                                         // Now it's empty..
167                                         DELETE(dl);
168                                         chan->Shrink("norejoinusers");
169                                 }
170                         }
171                 }
172                 return 0;
173         }
174                 
175         virtual void OnUserKick(userrec* source, userrec* user, chanrec* chan, const std::string &reason, bool &silent)
176         {
177                 if (chan->IsModeSet('J') && (source != user))
178                 {
179                         delaylist* dl;
180                         if (!chan->GetExt("norejoinusers", dl))
181                         {
182                                 dl = new delaylist;
183                                 chan->Extend("norejoinusers", dl);
184                         }
185                         (*dl)[user] = time(NULL) + strtoint(chan->GetModeParameter('J'));
186                 }
187         }
188         
189         virtual void OnChannelDelete(chanrec* chan)
190         {
191                 delaylist* dl;
192                         
193                 if (chan->GetExt("norejoinusers", dl))
194                 {
195                         DELETE(dl);
196                         chan->Shrink("norejoinusers");
197                 }
198         }
199         
200         virtual void OnCleanup(int target_type, void* item)
201         {
202                 if(target_type == TYPE_CHANNEL)
203                         OnChannelDelete((chanrec*)item);
204         }
205
206         virtual void Implements(char* List)
207         {
208                 List[I_OnCleanup] = List[I_OnChannelDelete] = List[I_OnUserPreJoin] = List[I_OnUserKick] = 1;
209         }
210
211         virtual ~ModuleKickNoRejoin()
212         {
213                 ServerInstance->Modes->DelMode(kr);
214                 DELETE(kr);
215         }
216         
217         virtual Version GetVersion()
218         {
219                 return Version(1, 1, 0, 0, VF_COMMON | VF_VENDOR, API_VERSION);
220         }
221 };
222
223
224 MODULE_INIT(ModuleKickNoRejoin);