]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_namedmodes.cpp
Merge pull request #677 from Robby-/master-dnsblzline
[user/henk/code/inspircd.git] / src / modules / m_namedmodes.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
22 static void DisplayList(LocalUser* user, Channel* channel)
23 {
24         Numeric::ParamBuilder<1> numeric(user, 961);
25         numeric.AddStatic(channel->name);
26
27         const ModeParser::ModeHandlerMap& mhs = ServerInstance->Modes->GetModes(MODETYPE_CHANNEL);
28         for (ModeParser::ModeHandlerMap::const_iterator i = mhs.begin(); i != mhs.end(); ++i)
29         {
30                 ModeHandler* mh = i->second;
31                 if (!channel->IsModeSet(mh))
32                         continue;
33                 numeric.Add("+" + mh->name);
34                 if (mh->NeedsParam(true))
35                 {
36                         if ((mh->name == "key") && (!channel->HasUser(user)) && (!user->HasPrivPermission("channels/auspex")))
37                                 numeric.Add("<key>");
38                         else
39                                 numeric.Add(channel->GetModeParameter(mh));
40                 }
41         }
42         numeric.Flush();
43         user->WriteNumeric(960, channel->name, "End of mode list");
44 }
45
46 class CommandProp : public SplitCommand
47 {
48  public:
49         CommandProp(Module* parent)
50                 : SplitCommand(parent, "PROP", 1)
51         {
52                 syntax = "<user|channel> {[+-]<mode> [<value>]}*";
53         }
54
55         CmdResult HandleLocal(const std::vector<std::string>& parameters, LocalUser* src)
56         {
57                 Channel* const chan = ServerInstance->FindChan(parameters[0]);
58                 if (!chan)
59                 {
60                         src->WriteNumeric(Numerics::NoSuchNick(parameters[0]));
61                         return CMD_FAILURE;
62                 }
63
64                 if (parameters.size() == 1)
65                 {
66                         DisplayList(src, chan);
67                         return CMD_SUCCESS;
68                 }
69                 unsigned int i = 1;
70                 Modes::ChangeList modes;
71                 while (i < parameters.size())
72                 {
73                         std::string prop = parameters[i++];
74                         if (prop.empty())
75                                 continue;
76                         bool plus = prop[0] != '-';
77                         if (prop[0] == '+' || prop[0] == '-')
78                                 prop.erase(prop.begin());
79
80                         ModeHandler* mh = ServerInstance->Modes->FindMode(prop, MODETYPE_CHANNEL);
81                         if (mh)
82                         {
83                                 if (mh->NeedsParam(plus))
84                                 {
85                                         if (i != parameters.size())
86                                                 modes.push(mh, plus, parameters[i++]);
87                                 }
88                                 else
89                                         modes.push(mh, plus);
90                         }
91                 }
92                 ServerInstance->Modes->ProcessSingle(src, chan, NULL, modes, ModeParser::MODE_CHECKACCESS);
93                 return CMD_SUCCESS;
94         }
95 };
96
97 class DummyZ : public ModeHandler
98 {
99  public:
100         DummyZ(Module* parent) : ModeHandler(parent, "namebase", 'Z', PARAM_ALWAYS, MODETYPE_CHANNEL)
101         {
102                 list = true;
103         }
104
105         // Handle /MODE #chan Z
106         void DisplayList(User* user, Channel* chan)
107         {
108                 if (IS_LOCAL(user))
109                         ::DisplayList(static_cast<LocalUser*>(user), chan);
110         }
111 };
112
113 class ModuleNamedModes : public Module
114 {
115         CommandProp cmd;
116         DummyZ dummyZ;
117  public:
118         ModuleNamedModes() : cmd(this), dummyZ(this)
119         {
120         }
121
122         Version GetVersion() CXX11_OVERRIDE
123         {
124                 return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR);
125         }
126
127         void Prioritize()
128         {
129                 ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
130         }
131
132         ModResult OnPreMode(User* source, User* dest, Channel* channel, Modes::ChangeList& modes) CXX11_OVERRIDE
133         {
134                 if (!channel)
135                         return MOD_RES_PASSTHRU;
136
137                 Modes::ChangeList::List& list = modes.getlist();
138                 for (Modes::ChangeList::List::iterator i = list.begin(); i != list.end(); )
139                 {
140                         Modes::Change& curr = *i;
141                         // Replace all namebase (dummyZ) modes being changed with the actual
142                         // mode handler and parameter. The parameter format of the namebase mode is
143                         // <modename>[=<parameter>].
144                         if (curr.mh == &dummyZ)
145                         {
146                                 std::string name = curr.param;
147                                 std::string value;
148                                 std::string::size_type eq = name.find('=');
149                                 if (eq != std::string::npos)
150                                 {
151                                         value.assign(name, eq + 1, std::string::npos);
152                                         name.erase(eq);
153                                 }
154
155                                 ModeHandler* mh = ServerInstance->Modes->FindMode(name, MODETYPE_CHANNEL);
156                                 if (!mh)
157                                 {
158                                         // Mode handler not found
159                                         i = list.erase(i);
160                                         continue;
161                                 }
162
163                                 curr.param.clear();
164                                 if (mh->NeedsParam(curr.adding))
165                                 {
166                                         if (value.empty())
167                                         {
168                                                 // Mode needs a parameter but there wasn't one
169                                                 i = list.erase(i);
170                                                 continue;
171                                         }
172
173                                         // Change parameter to the text after the '='
174                                         curr.param = value;
175                                 }
176
177                                 // Put the actual ModeHandler in place of the namebase handler
178                                 curr.mh = mh;
179                         }
180
181                         ++i;
182                 }
183
184                 return MOD_RES_PASSTHRU;
185         }
186 };
187
188 MODULE_INIT(ModuleNamedModes)