]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_namedmodes.cpp
46ecb8bfd1aacb4a174e87fc68ab0b4afcab20f3
[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         Version GetVersion() CXX11_OVERRIDE
107         {
108                 return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR);
109         }
110
111         void Prioritize()
112         {
113                 ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
114         }
115
116         ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters) CXX11_OVERRIDE
117         {
118                 if (!channel)
119                         return MOD_RES_PASSTHRU;
120                 if (parameters[1].find('Z') == std::string::npos)
121                         return MOD_RES_PASSTHRU;
122                 if (parameters.size() <= 2)
123                 {
124                         DisplayList(source, channel);
125                         return MOD_RES_DENY;
126                 }
127
128                 std::vector<std::string> newparms;
129                 newparms.push_back(parameters[0]);
130                 newparms.push_back(parameters[1]);
131
132                 std::string modelist = newparms[1];
133                 bool adding = true;
134                 unsigned int param_at = 2;
135                 for(unsigned int i = 0; i < modelist.length(); i++)
136                 {
137                         unsigned char modechar = modelist[i];
138                         if (modechar == '+' || modechar == '-')
139                         {
140                                 adding = (modechar == '+');
141                                 continue;
142                         }
143                         ModeHandler *mh = ServerInstance->Modes->FindMode(modechar, MODETYPE_CHANNEL);
144                         if (modechar == 'Z')
145                         {
146                                 modechar = 0;
147                                 std::string name, value;
148                                 if (param_at < parameters.size())
149                                         name = parameters[param_at++];
150                                 std::string::size_type eq = name.find('=');
151                                 if (eq != std::string::npos)
152                                 {
153                                         value = name.substr(eq + 1);
154                                         name = name.substr(0, eq);
155                                 }
156                                 for(char letter = 'A'; modechar == 0 && letter <= 'z'; letter++)
157                                 {
158                                         mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
159                                         if (mh && mh->name == name)
160                                         {
161                                                 if (mh->GetNumParams(adding))
162                                                 {
163                                                         if (!value.empty())
164                                                         {
165                                                                 newparms.push_back(value);
166                                                                 modechar = letter;
167                                                                 break;
168                                                         }
169                                                 }
170                                                 else
171                                                 {
172                                                         modechar = letter;
173                                                         break;
174                                                 }
175                                         }
176                                 }
177                                 if (modechar)
178                                         modelist[i] = modechar;
179                                 else
180                                         modelist.erase(i--, 1);
181                         }
182                         else if (mh && mh->GetNumParams(adding) && param_at < parameters.size())
183                         {
184                                 newparms.push_back(parameters[param_at++]);
185                         }
186                 }
187                 newparms[1] = modelist;
188                 ServerInstance->Modes->Process(newparms, source);
189                 return MOD_RES_DENY;
190         }
191 };
192
193 MODULE_INIT(ModuleNamedModes)