]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_namedmodes.cpp
m_dccallow Add config option to control max entries on a list
[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                         if (prop.empty())
69                                 continue;
70                         bool plus = prop[0] != '-';
71                         if (prop[0] == '+' || prop[0] == '-')
72                                 prop.erase(prop.begin());
73
74                         for(char letter = 'A'; letter <= 'z'; letter++)
75                         {
76                                 ModeHandler* mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
77                                 if (mh && mh->name == prop)
78                                 {
79                                         modes[1].append((plus ? "+" : "-") + std::string(1, letter));
80                                         if (mh->GetNumParams(plus))
81                                         {
82                                                 if (i != parameters.size())
83                                                         modes.push_back(parameters[i++]);
84                                         }
85                                 }
86                         }
87                 }
88                 ServerInstance->SendGlobalMode(modes, src);
89                 return CMD_SUCCESS;
90         }
91 };
92
93 class DummyZ : public ModeHandler
94 {
95  public:
96         DummyZ(Module* parent) : ModeHandler(parent, "namebase", 'Z', PARAM_ALWAYS, MODETYPE_CHANNEL)
97         {
98                 list = true;
99         }
100 };
101
102 class ModuleNamedModes : public Module
103 {
104         CommandProp cmd;
105         DummyZ dummyZ;
106  public:
107         ModuleNamedModes() : cmd(this), dummyZ(this)
108         {
109         }
110
111         void init()
112         {
113                 ServerInstance->Modules->AddService(cmd);
114                 ServerInstance->Modules->AddService(dummyZ);
115
116                 Implementation eventlist[] = { I_OnPreMode };
117                 ServerInstance->Modules->Attach(eventlist, this, sizeof(eventlist)/sizeof(Implementation));
118         }
119
120         Version GetVersion()
121         {
122                 return Version("Provides the ability to manipulate modes via long names.",VF_VENDOR);
123         }
124
125         void Prioritize()
126         {
127                 ServerInstance->Modules->SetPriority(this, I_OnPreMode, PRIORITY_FIRST);
128         }
129
130         ModResult OnPreMode(User* source, User* dest, Channel* channel, const std::vector<std::string>& parameters)
131         {
132                 if (!channel)
133                         return MOD_RES_PASSTHRU;
134                 if (parameters[1].find('Z') == std::string::npos)
135                         return MOD_RES_PASSTHRU;
136                 if (parameters.size() <= 2)
137                 {
138                         DisplayList(source, channel);
139                         return MOD_RES_DENY;
140                 }
141
142                 std::vector<std::string> newparms;
143                 newparms.push_back(parameters[0]);
144                 newparms.push_back(parameters[1]);
145
146                 std::string modelist = newparms[1];
147                 bool adding = true;
148                 unsigned int param_at = 2;
149                 for(unsigned int i = 0; i < modelist.length(); i++)
150                 {
151                         unsigned char modechar = modelist[i];
152                         if (modechar == '+' || modechar == '-')
153                         {
154                                 adding = (modechar == '+');
155                                 continue;
156                         }
157                         ModeHandler *mh = ServerInstance->Modes->FindMode(modechar, MODETYPE_CHANNEL);
158                         if (modechar == 'Z')
159                         {
160                                 modechar = 0;
161                                 std::string name, value;
162                                 if (param_at < parameters.size())
163                                         name = parameters[param_at++];
164                                 std::string::size_type eq = name.find('=');
165                                 if (eq != std::string::npos)
166                                 {
167                                         value = name.substr(eq + 1);
168                                         name = name.substr(0, eq);
169                                 }
170                                 for(char letter = 'A'; modechar == 0 && letter <= 'z'; letter++)
171                                 {
172                                         mh = ServerInstance->Modes->FindMode(letter, MODETYPE_CHANNEL);
173                                         if (mh && mh->name == name)
174                                         {
175                                                 if (mh->GetNumParams(adding))
176                                                 {
177                                                         if (!value.empty())
178                                                         {
179                                                                 newparms.push_back(value);
180                                                                 modechar = letter;
181                                                                 break;
182                                                         }
183                                                 }
184                                                 else
185                                                 {
186                                                         modechar = letter;
187                                                         break;
188                                                 }
189                                         }
190                                 }
191                                 if (modechar)
192                                         modelist[i] = modechar;
193                                 else
194                                         modelist.erase(i--, 1);
195                         }
196                         else if (mh && mh->GetNumParams(adding) && param_at < parameters.size())
197                         {
198                                 newparms.push_back(parameters[param_at++]);
199                         }
200                 }
201                 newparms[1] = modelist;
202                 ServerInstance->Modes->Process(newparms, source, false);
203                 return MOD_RES_DENY;
204         }
205 };
206
207 MODULE_INIT(ModuleNamedModes)