]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_redirect.cpp
Now with added ANGRY MONKEYS.
[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                                 WriteServ(source->fd,"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 ((c == channel) || (c->IsModeSet('L')))
67                                 {
68                                         WriteServ(source->fd,"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());
69                                         parameter = "";
70                                         return MODEACTION_DENY;
71                                 }
72                                 else
73                                 {
74                                         for (chan_hash::const_iterator i = chanlist.begin(); i != chanlist.end(); i++)
75                                         {
76                                                 if ((i->second != channel) && (i->second->IsModeSet('L')) && (irc::string(i->second->GetModeParameter('L').c_str()) == irc::string(channel->name)))
77                                                 {
78                                                         WriteServ(source->fd,"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);
79                                                         return MODEACTION_DENY;
80                                                 }
81                                         }
82                                 }
83                         }
84
85                         channel->SetMode('L', true);
86                         channel->SetModeParam('L', parameter.c_str(), true);
87                         return MODEACTION_ALLOW;
88                 }
89                 else
90                 {
91                         if (channel->IsModeSet('L'))
92                         {
93                                 channel->SetMode('L', false);
94                                 return MODEACTION_ALLOW;
95                         }
96                 }
97
98                 return MODEACTION_DENY;
99                 
100         }
101 };
102
103 class ModuleRedirect : public Module
104 {
105         Server *Srv;
106         Redirect* re;
107         
108  public:
109  
110         ModuleRedirect(Server* Me)
111                 : Module::Module(Me)
112         {
113                 Srv = Me;
114                 re = new Redirect(Me);
115                 Srv->AddMode(re, 'L');
116         }
117         
118         void Implements(char* List)
119         {
120                 List[I_On005Numeric] = List[I_OnUserPreJoin] = 1;
121         }
122
123         virtual void On005Numeric(std::string &output)
124         {
125                 InsertMode(output, "L", 3);
126         }
127         
128         virtual int OnUserPreJoin(userrec* user, chanrec* chan, const char* cname)
129         {
130                 if (chan)
131                 {
132                         if (chan->IsModeSet('L'))
133                         {
134                                 if (Srv->CountUsers(chan) >= chan->limit)
135                                 {
136                                         std::string channel = chan->GetModeParameter('L');
137                                         WriteServ(user->fd,"470 %s :%s has become full, so you are automatically being transferred to the linked channel %s",user->nick,cname,channel.c_str());
138                                         Srv->JoinUserToChannel(user,channel.c_str(),"");
139                                         return 1;
140                                 }
141                         }
142                 }
143                 return 0;
144         }
145
146         virtual ~ModuleRedirect()
147         {
148                 DELETE(re);
149         }
150         
151         virtual Version GetVersion()
152         {
153                 return Version(1,0,0,0,VF_STATIC|VF_VENDOR);
154         }
155 };
156
157
158 class ModuleRedirectFactory : public ModuleFactory
159 {
160  public:
161         ModuleRedirectFactory()
162         {
163         }
164         
165         ~ModuleRedirectFactory()
166         {
167         }
168         
169         virtual Module * CreateModule(Server* Me)
170         {
171                 return new ModuleRedirect(Me);
172         }
173         
174 };
175
176
177 extern "C" void * init_module( void )
178 {
179         return new ModuleRedirectFactory;
180 }
181