]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_denychans.cpp
0b82d0750aae870bf8b336f4f3d5b2c35edb2785
[user/henk/code/inspircd.git] / src / modules / m_denychans.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
5  *   Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net>
6  *   Copyright (C) 2007 Dennis Friis <peavey@inspircd.org>
7  *   Copyright (C) 2005 Craig Edwards <craigedwards@brainbox.cc>
8  *
9  * This file is part of InspIRCd.  InspIRCd is free software: you can
10  * redistribute it and/or modify it under the terms of the GNU General Public
11  * License as published by the Free Software Foundation, version 2.
12  *
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22
23 #include "inspircd.h"
24
25 class ModuleDenyChannels : public Module
26 {
27  public:
28         void init() CXX11_OVERRIDE
29         {
30                 Implementation eventlist[] = { I_OnUserPreJoin, I_OnRehash };
31                 ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
32         }
33
34         void OnRehash(User* user) CXX11_OVERRIDE
35         {
36                 /* check for redirect validity and loops/chains */
37                 ConfigTagList tags = ServerInstance->Config->ConfTags("badchan");
38                 for (ConfigIter i = tags.first; i != tags.second; ++i)
39                 {
40                         std::string name = i->second->getString("name");
41                         std::string redirect = i->second->getString("redirect");
42
43                         if (!redirect.empty())
44                         {
45
46                                 if (!ServerInstance->IsChannel(redirect))
47                                 {
48                                         if (user)
49                                                 user->WriteNotice("Invalid badchan redirect '" + redirect + "'");
50                                         throw ModuleException("Invalid badchan redirect, not a channel");
51                                 }
52
53                                 for (ConfigIter j = tags.first; j != tags.second; ++j)
54                                 {
55                                         if (InspIRCd::Match(redirect, j->second->getString("name")))
56                                         {
57                                                 bool goodchan = false;
58                                                 ConfigTagList goodchans = ServerInstance->Config->ConfTags("badchan");
59                                                 for (ConfigIter k = goodchans.first; k != goodchans.second; ++k)
60                                                 {
61                                                         if (InspIRCd::Match(redirect, k->second->getString("name")))
62                                                                 goodchan = true;
63                                                 }
64
65                                                 if (!goodchan)
66                                                 {
67                                                         /* <badchan:redirect> is a badchan */
68                                                         if (user)
69                                                                 user->WriteNotice("Badchan " + name + " redirects to badchan " + redirect);
70                                                         throw ModuleException("Badchan redirect loop");
71                                                 }
72                                         }
73                                 }
74                         }
75                 }
76         }
77
78         Version GetVersion() CXX11_OVERRIDE
79         {
80                 return Version("Implements config tags which allow blocking of joins to channels", VF_VENDOR);
81         }
82
83
84         ModResult OnUserPreJoin(LocalUser* user, Channel* chan, const std::string& cname, std::string& privs, const std::string& keygiven) CXX11_OVERRIDE
85         {
86                 ConfigTagList tags = ServerInstance->Config->ConfTags("badchan");
87                 for (ConfigIter j = tags.first; j != tags.second; ++j)
88                 {
89                         if (InspIRCd::Match(cname, j->second->getString("name")))
90                         {
91                                 if (user->IsOper() && j->second->getBool("allowopers"))
92                                 {
93                                         return MOD_RES_PASSTHRU;
94                                 }
95                                 else
96                                 {
97                                         std::string reason = j->second->getString("reason");
98                                         std::string redirect = j->second->getString("redirect");
99
100                                         ConfigTagList goodchans = ServerInstance->Config->ConfTags("goodchan");
101                                         for (ConfigIter i = goodchans.first; i != goodchans.second; ++i)
102                                         {
103                                                 if (InspIRCd::Match(cname, i->second->getString("name")))
104                                                 {
105                                                         return MOD_RES_PASSTHRU;
106                                                 }
107                                         }
108
109                                         if (ServerInstance->IsChannel(redirect))
110                                         {
111                                                 /* simple way to avoid potential loops: don't redirect to +L channels */
112                                                 Channel *newchan = ServerInstance->FindChan(redirect);
113                                                 if ((!newchan) || (!(newchan->IsModeSet('L'))))
114                                                 {
115                                                         user->WriteNumeric(926, "%s %s :Channel %s is forbidden, redirecting to %s: %s",user->nick.c_str(),cname.c_str(),cname.c_str(),redirect.c_str(), reason.c_str());
116                                                         Channel::JoinUser(user, redirect);
117                                                         return MOD_RES_DENY;
118                                                 }
119                                         }
120
121                                         user->WriteNumeric(926, "%s %s :Channel %s is forbidden: %s",user->nick.c_str(),cname.c_str(),cname.c_str(),reason.c_str());
122                                         return MOD_RES_DENY;
123                                 }
124                         }
125                 }
126                 return MOD_RES_PASSTHRU;
127         }
128 };
129
130 MODULE_INIT(ModuleDenyChannels)