]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_namedmodes.cpp
Replace hardcoded mode letters, part 3
[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 %s :End of mode list", user->nick.c_str(), 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                         for(char letter = 'A'; letter <= 'z'; letter++)
70                         {
71                                 ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
72                                 if (mh && mh->name == prop)
73                                 {
74                                         modes[1].append((plus ? "+" : "-") + std::string(1, letter));
75                                         if (mh->GetNumParams(plus))
76                                         {
77                                                 if (i != parameters.size())
78                                                         modes.push_back(parameters[i++]);
79                                         }
80                                 }
81                         }
82                 }
83                 ServerInstance->Modes->Process(modes, src);
84                 return CMD_SUCCESS;
85         }
86 };
87
88 class DummyZ : public ModeHandler
89 {
90  public:
91         DummyZ(Module* parent) : ModeHandler(parent, "namebase", 'Z', PARAM_ALWAYS, MODETYPE_CHANNEL)
92         {
93                 list = true;
94         }
95 };
96
97 class ModuleNamedModes : public Module
98 {
99         CommandProp cmd;
100         DummyZ dummyZ;
101  public:
102         ModuleNamedModes() : cmd(this), dummyZ(this)
103         {
104         }
105
106         void init() CXX11_OVERRIDE
107         {
108                 ServerInstance->Modules->AddService(cmd);
109                 ServerInstance->Modules->AddService(dummyZ);
110
111                 Implementation eventlist[] = { I_OnPreMode };
112                 ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
113         }
114
115         Version GetVersion() CXX11_OVERRIDE
116         {
117                 return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR);
118         }
119
120         void Prioritize()
121         {
122                 ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
123         }
124
125         ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters) CXX11_OVERRIDE
126         {
127                 if (!channel)
128                         return MOD_RES_PASSTHRU;
129                 if (parameters[1].find('Z') == std::string::npos)
130                         return MOD_RES_PASSTHRU;
131                 if (parameters.size() <= 2)
132                 {
133                         DisplayList(source, channel);
134                         return MOD_RES_DENY;
135                 }
136
137                 std::vector<std::string> newparms;
138                 newparms.push_back(parameters[0]);
139                 newparms.push_back(parameters[1]);
140
141                 std::string modelist = newparms[1];
142                 bool adding = true;
143                 unsigned int param_at = 2;
144                 for(unsigned int i = 0; i < modelist.length(); i++)
145                 {
146                         unsigned char modechar = modelist[i];
147                         if (modechar == '+' || modechar == '-')
148                         {
149                                 adding = (modechar == '+');
150                                 continue;
151                         }
152                         ModeHandler *mh = ServerInstance->Modes->FindMode(modechar, MODETYPE_CHANNEL);
153                         if (modechar == 'Z')
154                         {
155                                 modechar = 0;
156                                 std::string name, value;
157                                 if (param_at < parameters.size())
158                                         name = parameters[param_at++];
159                                 std::string::size_type eq = name.find('=');
160                                 if (eq != std::string::npos)
161                                 {
162                                         value = name.substr(eq + 1);
163                                         name = name.substr(0, eq);
164                                 }
165                                 for(char letter = 'A'; modechar == 0 && letter <= 'z'; letter++)
166                                 {
167                                         mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
168                                         if (mh && mh->name == name)
169                                         {
170                                                 if (mh->GetNumParams(adding))
171                                                 {
172                                                         if (!value.empty())
173                                                         {
174                                                                 newparms.push_back(value);
175                                                                 modechar = letter;
176                                                                 break;
177                                                         }
178                                                 }
179                                                 else
180                                                 {
181                                                         modechar = letter;
182                                                         break;
183                                                 }
184                                         }
185                                 }
186                                 if (modechar)
187                                         modelist[i] = modechar;
188                                 else
189                                         modelist.erase(i--, 1);
190                         }
191                         else if (mh && mh->GetNumParams(adding) && param_at < parameters.size())
192                         {
193                                 newparms.push_back(parameters[param_at++]);
194                         }
195                 }
196                 newparms[1] = modelist;
197                 ServerInstance->Modes->Process(newparms, source);
198                 return MOD_RES_DENY;
199         }
200 };
201
202 MODULE_INIT(ModuleNamedModes)