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