]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_namedmodes.cpp
4004db00e93d488301a58b30088ab897a4a4c2ad
[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         // Handle /MODE #chan Z
94         void DisplayList(User* user, Channel* chan)
95         {
96                 ::DisplayList(user, chan);
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         Version GetVersion() CXX11_OVERRIDE
110         {
111                 return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR);
112         }
113
114         void Prioritize()
115         {
116                 ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
117         }
118
119         ModResult OnPreMode(User* source, User* dest, Channel* channel, Modes::ChangeList& modes) CXX11_OVERRIDE
120         {
121                 if (!channel)
122                         return MOD_RES_PASSTHRU;
123
124                 Modes::ChangeList::List& list = modes.getlist();
125                 for (Modes::ChangeList::List::iterator i = list.begin(); i != list.end(); )
126                 {
127                         Modes::Change& curr = *i;
128                         // Replace all namebase (dummyZ) modes being changed with the actual
129                         // mode handler and parameter. The parameter format of the namebase mode is
130                         // <modename>[=<parameter>].
131                         if (curr.mh == &dummyZ)
132                         {
133                                 std::string name = curr.param;
134                                 std::string value;
135                                 std::string::size_type eq = name.find('=');
136                                 if (eq != std::string::npos)
137                                 {
138                                         value = name.substr(eq + 1);
139                                         name = name.substr(0, eq);
140                                 }
141
142                                 ModeHandler* mh = ServerInstance->Modes->FindMode(name, MODETYPE_CHANNEL);
143                                 if (!mh)
144                                 {
145                                         // Mode handler not found
146                                         i = list.erase(i);
147                                         continue;
148                                 }
149
150                                 curr.param.clear();
151                                 if (mh->GetNumParams(curr.adding))
152                                 {
153                                         if (value.empty())
154                                         {
155                                                 // Mode needs a parameter but there wasn't one
156                                                 i = list.erase(i);
157                                                 continue;
158                                         }
159
160                                         // Change parameter to the text after the '='
161                                         curr.param = value;
162                                 }
163
164                                 // Put the actual ModeHandler in place of the namebase handler
165                                 curr.mh = mh;
166                         }
167
168                         ++i;
169                 }
170
171                 return MOD_RES_PASSTHRU;
172         }
173 };
174
175 MODULE_INIT(ModuleNamedModes)