]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_redirect.cpp
Remove InspIRCd* parameters and fields
[user/henk/code/inspircd.git] / src / modules / m_redirect.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/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
16 /* $ModDesc: Provides channel mode +L (limit redirection) */
17
18 /** Handle channel mode +L
19  */
20 class Redirect : public ModeHandler
21 {
22  public:
23         Redirect(Module* Creator) : ModeHandler(Creator, 'L', PARAM_SETONLY, MODETYPE_CHANNEL) { }
24
25         ModePair ModeSet(User* source, User* dest, Channel* channel, const std::string &parameter)
26         {
27                 if (channel->IsModeSet('L'))
28                         return std::make_pair(true, channel->GetModeParameter('L'));
29                 else
30                         return std::make_pair(false, parameter);
31         }
32
33         ModeAction OnModeChange(User* source, User* dest, Channel* channel, std::string &parameter, bool adding)
34         {
35                 if (adding)
36                 {
37                         if (IS_LOCAL(source))
38                         {
39                                 if (!ServerInstance->IsChannel(parameter.c_str(), ServerInstance->Config->Limits.ChanMax))
40                                 {
41                                         source->WriteNumeric(403, "%s %s :Invalid channel name", source->nick.c_str(), parameter.c_str());
42                                         parameter.clear();
43                                         return MODEACTION_DENY;
44                                 }
45                         }
46
47                         if (IS_LOCAL(source) && !IS_OPER(source))
48                         {
49                                 Channel* c = ServerInstance->FindChan(parameter);
50                                 if (!c)
51                                 {
52                                         source->WriteNumeric(690, "%s :Target channel %s must exist to be set as a redirect.",source->nick.c_str(),parameter.c_str());
53                                         parameter.clear();
54                                         return MODEACTION_DENY;
55                                 }
56                                 else if (c->GetPrefixValue(source) < OP_VALUE)
57                                 {
58                                         source->WriteNumeric(690, "%s :You must be opped on %s to set it as a redirect.",source->nick.c_str(),parameter.c_str());
59                                         parameter.clear();
60                                         return MODEACTION_DENY;
61                                 }
62                         }
63
64                         /*
65                          * We used to do some checking for circular +L here, but there is no real need for this any more especially as we
66                          * now catch +L looping in PreJoin. Remove it, since O(n) logic makes me sad, and we catch it anyway. :) -- w00t
67                          */
68                         channel->SetModeParam('L', parameter);
69                         return MODEACTION_ALLOW;
70                 }
71                 else
72                 {
73                         if (channel->IsModeSet('L'))
74                         {
75                                 channel->SetModeParam('L', "");
76                                 return MODEACTION_ALLOW;
77                         }
78                 }
79
80                 return MODEACTION_DENY;
81
82         }
83 };
84
85 class ModuleRedirect : public Module
86 {
87
88         Redirect re;
89
90  public:
91
92         ModuleRedirect()
93                 : re(this)
94         {
95
96                 if (!ServerInstance->Modes->AddMode(&re))
97                         throw ModuleException("Could not add new modes!");
98                 Implementation eventlist[] = { I_OnUserPreJoin };
99                 ServerInstance->Modules->Attach(eventlist, this, 1);
100         }
101
102
103         virtual ModResult OnUserPreJoin(User* user, Channel* chan, const char* cname, std::string &privs, const std::string &keygiven)
104         {
105                 if (chan)
106                 {
107                         if (chan->IsModeSet('L') && chan->modes[CM_LIMIT])
108                         {
109                                 if (chan->GetUserCounter() >= atoi(chan->GetModeParameter('l').c_str()))
110                                 {
111                                         std::string channel = chan->GetModeParameter('L');
112
113                                         /* sometimes broken ulines can make circular or chained +L, avoid this */
114                                         Channel* destchan = NULL;
115                                         destchan = ServerInstance->FindChan(channel);
116                                         if (destchan && destchan->IsModeSet('L'))
117                                         {
118                                                 user->WriteNumeric(470, "%s %s * :You may not join this channel. A redirect is set, but you may not be redirected as it is a circular loop.", user->nick.c_str(), cname);
119                                                 return MOD_RES_DENY;
120                                         }
121
122                                         user->WriteNumeric(470, "%s %s %s :You may not join this channel, so you are automatically being transferred to the redirect channel.", user->nick.c_str(), cname, channel.c_str());
123                                         Channel::JoinUser(user, channel.c_str(), false, "", false, ServerInstance->Time());
124                                         return MOD_RES_DENY;
125                                 }
126                         }
127                 }
128                 return MOD_RES_PASSTHRU;
129         }
130
131         virtual ~ModuleRedirect()
132         {
133                 ServerInstance->Modes->DelMode(&re);
134         }
135
136         virtual Version GetVersion()
137         {
138                 return Version("Provides channel mode +L (limit redirection)", VF_COMMON | VF_VENDOR, API_VERSION);
139         }
140 };
141
142 MODULE_INIT(ModuleRedirect)