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