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