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