]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_redirect.cpp
WHEEEEE!!!!!
[user/henk/code/inspircd.git] / src / modules / m_redirect.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  *     
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 #include <stdio.h>
20 #include "users.h"
21 #include "channels.h"
22 #include "modules.h"
23 #include "helperfuncs.h"
24
25 /* $ModDesc: Provides channel mode +L (limit redirection) */
26
27 extern chan_hash chanlist;
28
29 class Redirect : public ModeHandler
30 {
31         Server* Srv;
32  public:
33         Redirect(Server* s) : ModeHandler('L', 1, 0, false, MODETYPE_CHANNEL, false), Srv(s) { }
34
35         ModePair ModeSet(userrec* source, userrec* dest, chanrec* channel, const std::string &parameter)
36         {
37                 if (channel->IsModeSet('L'))
38                         return std::make_pair(true, channel->GetModeParameter('L'));
39                 else
40                         return std::make_pair(false, parameter);
41         }
42
43         bool CheckTimeStamp(time_t theirs, time_t ours, const std::string &their_param, const std::string &our_param, chanrec* channel)
44         {
45                 /* When TS is equal, the alphabetically later one wins */
46                 return (their_param < our_param);
47         }
48         
49         ModeAction OnModeChange(userrec* source, userrec* dest, chanrec* channel, std::string &parameter, bool adding)
50         {
51                 if (adding)
52                 {
53                         chanrec* c = NULL;
54
55                         if (!IsValidChannelName(parameter.c_str()))
56                         {
57                                 source->WriteServ("403 %s %s :Invalid channel name",source->nick, parameter.c_str());
58                                 parameter = "";
59                                 return MODEACTION_DENY;
60                         }
61
62                         c = Srv->FindChannel(parameter);
63                         if (c)
64                         {
65                                 /* Fix by brain: Dont let a channel be linked to *itself* either */
66                                 if (IS_LOCAL(source))
67                                 {
68                                         if ((c == channel) || (c->IsModeSet('L')))
69                                         {
70                                                 source->WriteServ("690 %s :Circular or chained +L to %s not allowed (Channel already has +L). Pack of wild dogs has been unleashed.",source->nick,parameter.c_str());
71                                                 parameter = "";
72                                                 return MODEACTION_DENY;
73                                         }
74                                         else
75                                         {
76                                                 for (chan_hash::const_iterator i = chanlist.begin(); i != chanlist.end(); i++)
77                                                 {
78                                                         if ((i->second != channel) && (i->second->IsModeSet('L')) && (irc::string(i->second->GetModeParameter('L').c_str()) == irc::string(channel->name)))
79                                                         {
80                                                                 source->WriteServ("690 %s :Circular or chained +L to %s not allowed (Already forwarded here from %s). Angry monkeys dispatched.",source->nick,parameter.c_str(),i->second->name);
81                                                                 return MODEACTION_DENY;
82                                                         }
83                                                 }
84                                         }
85                                 }
86                         }
87
88                         channel->SetMode('L', true);
89                         channel->SetModeParam('L', parameter.c_str(), true);
90                         return MODEACTION_ALLOW;
91                 }
92                 else
93                 {
94                         if (channel->IsModeSet('L'))
95                         {
96                                 channel->SetMode('L', false);
97                                 return MODEACTION_ALLOW;
98                         }
99                 }
100
101                 return MODEACTION_DENY;
102                 
103         }
104 };
105
106 class ModuleRedirect : public Module
107 {
108         Server *Srv;
109         Redirect* re;
110         
111  public:
112  
113         ModuleRedirect(Server* Me)
114                 : Module::Module(Me)
115         {
116                 Srv = Me;
117                 re = new Redirect(Me);
118                 Srv->AddMode(re, 'L');
119         }
120         
121         void Implements(char* List)
122         {
123                 List[I_On005Numeric] = List[I_OnUserPreJoin] = 1;
124         }
125
126         virtual void On005Numeric(std::string &output)
127         {
128                 InsertMode(output, "L", 3);
129         }
130         
131         virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname)
132         {
133                 if (chan)
134                 {
135                         if (chan->IsModeSet('L'))
136                         {
137                                 if (Srv->CountUsers(chan) >= chan->limit)
138                                 {
139                                         std::string channel = chan->GetModeParameter('L');
140                                         user->WriteServ("470 %s :%s has become full, so you are automatically being transferred to the linked channel %s",user->nick,cname,channel.c_str());
141                                         chanrec::JoinUser(user, channel.c_str(), false);
142                                         return 1;
143                                 }
144                         }
145                 }
146                 return 0;
147         }
148
149         virtual ~ModuleRedirect()
150         {
151                 DELETE(re);
152         }
153         
154         virtual Version GetVersion()
155         {
156                 return Version(1,0,0,0,VF_STATIC|VF_VENDOR);
157         }
158 };
159
160
161 class ModuleRedirectFactory : public ModuleFactory
162 {
163  public:
164         ModuleRedirectFactory()
165         {
166         }
167         
168         ~ModuleRedirectFactory()
169         {
170         }
171         
172         virtual Module * CreateModule(Server* Me)
173         {
174                 return new ModuleRedirect(Me);
175         }
176         
177 };
178
179
180 extern "C" void * init_module( void )
181 {
182         return new ModuleRedirectFactory;
183 }
184