]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_exemptchanops.cpp
7a40063fc824014e6cfc225bebec88f50df267a5
[user/henk/code/inspircd.git] / src / modules / m_exemptchanops.cpp
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org>
5  *
6  * This file is part of InspIRCd.  InspIRCd is free software: you can
7  * redistribute it and/or modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation, version 2.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 #include "inspircd.h"
21 #include "listmode.h"
22 #include "modules/exemption.h"
23
24 /** Handles channel mode +X
25  */
26 class ExemptChanOps : public ListModeBase
27 {
28  public:
29         ExemptChanOps(Module* Creator)
30                 : ListModeBase(Creator, "exemptchanops", 'X', "End of channel exemptchanops list", 954, 953, false)
31         {
32         }
33
34         static PrefixMode* FindMode(const std::string& mode)
35         {
36                 if (mode.length() == 1)
37                         return ServerInstance->Modes->FindPrefixMode(mode[0]);
38
39                 ModeHandler* mh = ServerInstance->Modes->FindMode(mode, MODETYPE_CHANNEL);
40                 return mh ? mh->IsPrefixMode() : NULL;
41         }
42
43         static bool ParseEntry(const std::string& entry, std::string& restriction, std::string& prefix)
44         {
45                 // The entry must be in the format <restriction>:<prefix>.
46                 std::string::size_type colon = entry.find(':');
47                 if (colon == std::string::npos || colon == entry.length()-1)
48                         return false;
49
50                 restriction.assign(entry, 0, colon);
51                 prefix.assign(entry, colon + 1);
52                 return true;
53         }
54
55         ModResult AccessCheck(User* source, Channel* channel, std::string& parameter, bool adding) CXX11_OVERRIDE
56         {
57                 std::string restriction;
58                 std::string prefix;
59                 if (!ParseEntry(parameter, restriction, prefix))
60                         return MOD_RES_PASSTHRU;
61
62                 PrefixMode* pm = FindMode(prefix);
63                 if (!pm)
64                         return MOD_RES_PASSTHRU;
65
66                 if (channel->GetPrefixValue(source) >= pm->GetLevelRequired(adding))
67                         return MOD_RES_PASSTHRU;
68
69                 source->WriteNumeric(ERR_CHANOPRIVSNEEDED, channel->name, InspIRCd::Format("You must be able to %s mode %c (%s) to %s a restriction containing it",
70                         adding ? "set" : "unset", pm->GetModeChar(), pm->name.c_str(), adding ? "add" : "remove"));
71                 return MOD_RES_DENY;
72         }
73
74         bool ValidateParam(User* user, Channel* chan, std::string& word) CXX11_OVERRIDE
75         {
76                 std::string restriction;
77                 std::string prefix;
78                 if (!ParseEntry(word, restriction, prefix))
79                 {
80                         user->WriteNumeric(Numerics::InvalidModeParameter(chan, this, word, "Invalid exemptchanops entry, format is <restriction>:<prefix>"));
81                         return false;
82                 }
83
84                 // If there is a '-' in the restriction string ignore it and everything after it
85                 // to support "auditorium-vis" and "auditorium-see" in m_auditorium
86                 std::string::size_type dash = restriction.find('-');
87                 if (dash != std::string::npos)
88                         restriction.erase(dash);
89
90                 if (!ServerInstance->Modes->FindMode(restriction, MODETYPE_CHANNEL))
91                 {
92                         user->WriteNumeric(Numerics::InvalidModeParameter(chan, this, word, "Unknown restriction"));
93                         return false;
94                 }
95
96                 if (prefix != "*" && !FindMode(prefix))
97                 {
98                         user->WriteNumeric(Numerics::InvalidModeParameter(chan, this, word, "Unknown prefix mode"));
99                         return false;
100                 }
101
102                 return true;
103         }
104 };
105
106 class ExemptHandler : public CheckExemption::EventListener
107 {
108  public:
109         ExemptChanOps ec;
110         ExemptHandler(Module* me)
111                 : CheckExemption::EventListener(me)
112                 , ec(me)
113         {
114         }
115
116         ModResult OnCheckExemption(User* user, Channel* chan, const std::string& restriction) CXX11_OVERRIDE
117         {
118                 unsigned int mypfx = chan->GetPrefixValue(user);
119                 std::string minmode;
120
121                 ListModeBase::ModeList* list = ec.GetList(chan);
122
123                 if (list)
124                 {
125                         for (ListModeBase::ModeList::iterator i = list->begin(); i != list->end(); ++i)
126                         {
127                                 std::string::size_type pos = (*i).mask.find(':');
128                                 if (pos == std::string::npos)
129                                         continue;
130                                 if (!i->mask.compare(0, pos, restriction))
131                                         minmode.assign(i->mask, pos + 1, std::string::npos);
132                         }
133                 }
134
135                 PrefixMode* mh = ExemptChanOps::FindMode(minmode);
136                 if (mh && mypfx >= mh->GetPrefixRank())
137                         return MOD_RES_ALLOW;
138                 if (mh || minmode == "*")
139                         return MOD_RES_DENY;
140
141                 return MOD_RES_PASSTHRU;
142         }
143 };
144
145 class ModuleExemptChanOps : public Module
146 {
147         ExemptHandler eh;
148
149  public:
150         ModuleExemptChanOps() : eh(this)
151         {
152         }
153
154         Version GetVersion() CXX11_OVERRIDE
155         {
156                 return Version("Provides the ability to allow channel operators to be exempt from certain modes", VF_VENDOR);
157         }
158
159         void ReadConfig(ConfigStatus& status) CXX11_OVERRIDE
160         {
161                 eh.ec.DoRehash();
162         }
163 };
164
165 MODULE_INIT(ModuleExemptChanOps)