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