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