]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_namedmodes.cpp
Add a ModeParser::FindMode() overload that takes a mode name and a mode type
[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(User* user, Channel* channel)
23 {
24         std::stringstream items;
25         for(char letter = 'A'; letter <= 'z'; letter++)
26         {
27                 ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
28                 if (!mh || mh->IsListMode())
29                         continue;
30                 if (!channel->IsModeSet(mh))
31                         continue;
32                 items << " +" << mh->name;
33                 if (mh->GetNumParams(true))
34                         items << " " << channel->GetModeParameter(mh);
35         }
36         const std::string line = ":" + ServerInstance->Config->ServerName + " 961 " + user->nick + " " + channel->name;
37         user->SendText(line, items);
38         user->WriteNumeric(960, "%s :End of mode list", channel->name.c_str());
39 }
40
41 class CommandProp : public Command
42 {
43  public:
44         CommandProp(Module* parent) : Command(parent, "PROP", 1)
45         {
46                 syntax = "<user|channel> {[+-]<mode> [<value>]}*";
47         }
48
49         CmdResult Handle(const std::vector<std::string> &parameters, User *src)
50         {
51                 if (parameters.size() == 1)
52                 {
53                         Channel* chan = ServerInstance->FindChan(parameters[0]);
54                         if (chan)
55                                 DisplayList(src, chan);
56                         return CMD_SUCCESS;
57                 }
58                 unsigned int i = 1;
59                 std::vector<std::string> modes;
60                 modes.push_back(parameters[0]);
61                 modes.push_back("");
62                 while (i < parameters.size())
63                 {
64                         std::string prop = parameters[i++];
65                         bool plus = prop[0] != '-';
66                         if (prop[0] == '+' || prop[0] == '-')
67                                 prop.erase(prop.begin());
68
69                         ModeHandler* mh = ServerInstance->Modes->FindMode(prop, MODETYPE_CHANNEL);
70                         if (mh)
71                         {
72                                 modes[1].push_back(plus ? '+' : '-');
73                                 modes[1].push_back(mh->GetModeChar());
74                                 if (mh->GetNumParams(plus))
75                                 {
76                                         if (i != parameters.size())
77                                                 modes.push_back(parameters[i++]);
78                                 }
79                         }
80                 }
81                 ServerInstance->Modes->Process(modes, src);
82                 return CMD_SUCCESS;
83         }
84 };
85
86 class DummyZ : public ModeHandler
87 {
88  public:
89         DummyZ(Module* parent) : ModeHandler(parent, "namebase", 'Z', PARAM_ALWAYS, MODETYPE_CHANNEL)
90         {
91                 list = true;
92         }
93 };
94
95 class ModuleNamedModes : public Module
96 {
97         CommandProp cmd;
98         DummyZ dummyZ;
99  public:
100         ModuleNamedModes() : cmd(this), dummyZ(this)
101         {
102         }
103
104         Version GetVersion() CXX11_OVERRIDE
105         {
106                 return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR);
107         }
108
109         void Prioritize()
110         {
111                 ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
112         }
113
114         ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters) CXX11_OVERRIDE
115         {
116                 if (!channel)
117                         return MOD_RES_PASSTHRU;
118                 if (parameters[1].find('Z') == std::string::npos)
119                         return MOD_RES_PASSTHRU;
120                 if (parameters.size() <= 2)
121                 {
122                         DisplayList(source, channel);
123                         return MOD_RES_DENY;
124                 }
125
126                 std::vector<std::string> newparms;
127                 newparms.push_back(parameters[0]);
128                 newparms.push_back(parameters[1]);
129
130                 std::string modelist = newparms[1];
131                 bool adding = true;
132                 unsigned int param_at = 2;
133                 for(unsigned int i = 0; i < modelist.length(); i++)
134                 {
135                         unsigned char modechar = modelist[i];
136                         if (modechar == '+' || modechar == '-')
137                         {
138                                 adding = (modechar == '+');
139                                 continue;
140                         }
141                         ModeHandler *mh = ServerInstance->Modes->FindMode(modechar, MODETYPE_CHANNEL);
142                         if (modechar == 'Z')
143                         {
144                                 std::string name, value;
145                                 if (param_at < parameters.size())
146                                         name = parameters[param_at++];
147                                 std::string::size_type eq = name.find('=');
148                                 if (eq != std::string::npos)
149                                 {
150                                         value = name.substr(eq + 1);
151                                         name = name.substr(0, eq);
152                                 }
153
154                                 mh = ServerInstance->Modes->FindMode(name, MODETYPE_CHANNEL);
155                                 if (!mh)
156                                 {
157                                         // Mode handler not found
158                                         modelist.erase(i--, 1);
159                                         continue;
160                                 }
161
162                                 if (mh->GetNumParams(adding))
163                                 {
164                                         if (value.empty())
165                                         {
166                                                 // Mode needs a parameter but there wasn't one
167                                                 modelist.erase(i--, 1);
168                                                 continue;
169                                         }
170
171                                         newparms.push_back(value);
172                                 }
173
174                                 modelist[i] = mh->GetModeChar();
175                         }
176                         else if (mh && mh->GetNumParams(adding) && param_at < parameters.size())
177                         {
178                                 newparms.push_back(parameters[param_at++]);
179                         }
180                 }
181                 newparms[1] = modelist;
182                 ServerInstance->Modes->Process(newparms, source);
183                 return MOD_RES_DENY;
184         }
185 };
186
187 MODULE_INIT(ModuleNamedModes)