]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_redirect.cpp
Textual improvements and fixes such as typos, casing, etc. (#1612)
[user/henk/code/inspircd.git] / src / modules / m_redirect.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2012 Shawn Smith <ShawnSmith0828@gmail.com>
5  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
6  *   Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net>
7  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
8  *   Copyright (C) 2004, 2006 Craig Edwards <craigedwards@brainbox.cc>
9  *   Copyright (C) 2006 Oliver Lupton <oliverlupton@gmail.com>
10  *
11  * This file is part of InspIRCd.  InspIRCd is free software: you can
12  * redistribute it and/or modify it under the terms of the GNU General Public
13  * License as published by the Free Software Foundation, version 2.
14  *
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  */
23
24
25 #include "inspircd.h"
26
27 /** Handle channel mode +L
28  */
29 class Redirect : public ParamMode<Redirect, LocalStringExt>
30 {
31  public:
32         Redirect(Module* Creator)
33                 : ParamMode<Redirect, LocalStringExt>(Creator, "redirect", 'L') { }
34
35         ModeAction OnSet(User* source, Channel* channel, std::string& parameter) CXX11_OVERRIDE
36         {
37                 if (IS_LOCAL(source))
38                 {
39                         if (!ServerInstance->IsChannel(parameter))
40                         {
41                                 source->WriteNumeric(Numerics::NoSuchChannel(parameter));
42                                 return MODEACTION_DENY;
43                         }
44                 }
45
46                 if (IS_LOCAL(source) && !source->IsOper())
47                 {
48                         Channel* c = ServerInstance->FindChan(parameter);
49                         if (!c)
50                         {
51                                 source->WriteNumeric(690, InspIRCd::Format("Target channel %s must exist to be set as a redirect.", parameter.c_str()));
52                                 return MODEACTION_DENY;
53                         }
54                         else if (c->GetPrefixValue(source) < OP_VALUE)
55                         {
56                                 source->WriteNumeric(690, InspIRCd::Format("You must be opped on %s to set it as a redirect.", parameter.c_str()));
57                                 return MODEACTION_DENY;
58                         }
59                 }
60
61                 /*
62                  * We used to do some checking for circular +L here, but there is no real need for this any more especially as we
63                  * now catch +L looping in PreJoin. Remove it, since O(n) logic makes me sad, and we catch it anyway. :) -- w00t
64                  */
65                 ext.set(channel, parameter);
66                 return MODEACTION_ALLOW;
67         }
68
69         void SerializeParam(Channel* chan, const std::string* str, std::string& out)
70         {
71                 out += *str;
72         }
73 };
74
75 class ModuleRedirect : public Module
76 {
77         Redirect re;
78         SimpleUserModeHandler antiredirectmode;
79         ChanModeReference limitmode;
80
81  public:
82         ModuleRedirect()
83                 : re(this)
84                 , antiredirectmode(this, "antiredirect", 'L')
85                 , limitmode(this, "limit")
86         {
87         }
88
89         ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
90         {
91                 if (chan)
92                 {
93                         if (chan->IsModeSet(re) && chan->IsModeSet(limitmode))
94                         {
95                                 if (chan->GetUserCounter() >= ConvToNum<size_t>(chan->GetModeParameter(limitmode)))
96                                 {
97                                         const std::string& channel = *re.ext.get(chan);
98
99                                         /* sometimes broken ulines can make circular or chained +L, avoid this */
100                                         Channel* destchan = ServerInstance->FindChan(channel);
101                                         if (destchan && destchan->IsModeSet(re))
102                                         {
103                                                 user->WriteNumeric(470, cname, '*', "You may not join this channel. A redirect is set, but you may not be redirected as it is a circular loop.");
104                                                 return MOD_RES_DENY;
105                                         }
106
107                                         if (user->IsModeSet(antiredirectmode))
108                                         {
109                                                 user->WriteNumeric(470, cname, channel, "Force redirection stopped.");
110                                                 return MOD_RES_DENY;
111                                         }
112                                         else
113                                         {
114                                                 user->WriteNumeric(470, cname, channel, "You may not join this channel, so you are automatically being transferred to the redirected channel.");
115                                                 Channel::JoinUser(user, channel);
116                                                 return MOD_RES_DENY;
117                                         }
118                                 }
119                         }
120                 }
121                 return MOD_RES_PASSTHRU;
122         }
123
124         Version GetVersion() CXX11_OVERRIDE
125         {
126                 return Version("Provides channel mode +L (limit redirection) and user mode +L (no forced redirection)", VF_VENDOR);
127         }
128 };
129
130 MODULE_INIT(ModuleRedirect)