]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/numericbuilder.h
Add an oper only parameter to Simple{Channel,User}ModeHandler.
[user/henk/code/inspircd.git] / include / numericbuilder.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2015-2016 Attila Molnar <attilamolnar@hush.com>
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 #pragma once
21
22 namespace Numeric
23 {
24         class WriteNumericSink;
25         class WriteRemoteNumericSink;
26
27         template <char Sep, bool SendEmpty, typename Sink>
28         class GenericBuilder;
29
30         template <char Sep = ',', bool SendEmpty = false>
31         class Builder;
32
33         template <unsigned int NumStaticParams, bool SendEmpty, typename Sink>
34         class GenericParamBuilder;
35
36         template <unsigned int NumStaticParams, bool SendEmpty = false>
37         class ParamBuilder;
38 }
39
40 class Numeric::WriteNumericSink
41 {
42         LocalUser* const user;
43
44  public:
45         WriteNumericSink(LocalUser* u)
46                 : user(u)
47         {
48         }
49
50         void operator()(Numeric& numeric) const
51         {
52                 user->WriteNumeric(numeric);
53         }
54 };
55
56 class Numeric::WriteRemoteNumericSink
57 {
58         User* const user;
59
60  public:
61         WriteRemoteNumericSink(User* u)
62                 : user(u)
63         {
64         }
65
66         void operator()(Numeric& numeric) const
67         {
68                 user->WriteRemoteNumeric(numeric);
69         }
70 };
71
72 template <char Sep, bool SendEmpty, typename Sink>
73 class Numeric::GenericBuilder
74 {
75         Sink sink;
76         Numeric numeric;
77         const std::string::size_type max;
78
79         bool HasRoom(const std::string::size_type additional) const
80         {
81                 return (numeric.GetParams().back().size() + additional <= max);
82         }
83
84  public:
85         GenericBuilder(Sink s, unsigned int num, bool addparam = true, size_t additionalsize = 0)
86                 : sink(s)
87                 , numeric(num)
88                 , max(ServerInstance->Config->Limits.MaxLine - ServerInstance->Config->ServerName.size() - additionalsize - 10)
89         {
90                 if (addparam)
91                         numeric.push(std::string());
92         }
93
94         Numeric& GetNumeric() { return numeric; }
95
96         void Add(const std::string& entry)
97         {
98                 if (!HasRoom(entry.size()))
99                         Flush();
100                 numeric.GetParams().back().append(entry).push_back(Sep);
101         }
102
103         void Add(const std::string& entry1, const std::string& entry2)
104         {
105                 if (!HasRoom(entry1.size() + entry2.size()))
106                         Flush();
107                 numeric.GetParams().back().append(entry1).append(entry2).push_back(Sep);
108         }
109
110         void Flush()
111         {
112                 std::string& data = numeric.GetParams().back();
113                 if (IsEmpty())
114                 {
115                         if (!SendEmpty)
116                                 return;
117                 }
118                 else
119                 {
120                         data.erase(data.size()-1);
121                 }
122
123                 sink(numeric);
124                 data.clear();
125         }
126
127         bool IsEmpty() const { return (numeric.GetParams().back().empty()); }
128 };
129
130 template <char Sep, bool SendEmpty>
131 class Numeric::Builder : public GenericBuilder<Sep, SendEmpty, WriteNumericSink>
132 {
133  public:
134         Builder(LocalUser* user, unsigned int num, bool addparam = true, size_t additionalsize = 0)
135                 : ::Numeric::GenericBuilder<Sep, SendEmpty, WriteNumericSink>(WriteNumericSink(user), num, addparam, additionalsize + user->nick.size())
136         {
137         }
138 };
139
140 template <unsigned int NumStaticParams, bool SendEmpty, typename Sink>
141 class Numeric::GenericParamBuilder
142 {
143         Sink sink;
144         Numeric numeric;
145         std::string::size_type currlen;
146         std::string::size_type max;
147
148         bool HasRoom(const std::string::size_type additional) const
149         {
150                 return (currlen + additional <= max);
151         }
152
153  public:
154         GenericParamBuilder(Sink s, unsigned int num, size_t additionalsize)
155                 : sink(s)
156                 , numeric(num)
157                 , currlen(0)
158                 , max(ServerInstance->Config->Limits.MaxLine - ServerInstance->Config->ServerName.size() - additionalsize - 10)
159         {
160         }
161
162         void AddStatic(const std::string& entry)
163         {
164                 max -= (entry.length() + 1);
165                 numeric.GetParams().push_back(entry);
166         }
167
168         void Add(const std::string& entry)
169         {
170                 if (!HasRoom(entry.size()))
171                         Flush();
172
173                 currlen += entry.size() + 1;
174                 numeric.GetParams().push_back(entry);
175         }
176
177         void Flush()
178         {
179                 if ((!SendEmpty) && (IsEmpty()))
180                         return;
181
182                 sink(numeric);
183                 currlen = 0;
184                 numeric.GetParams().erase(numeric.GetParams().begin() + NumStaticParams, numeric.GetParams().end());
185         }
186
187         bool IsEmpty() const { return (numeric.GetParams().size() <= NumStaticParams); }
188 };
189
190 template <unsigned int NumStaticParams, bool SendEmpty>
191 class Numeric::ParamBuilder : public GenericParamBuilder<NumStaticParams, SendEmpty, WriteNumericSink>
192 {
193  public:
194         ParamBuilder(LocalUser* user, unsigned int num)
195                 : ::Numeric::GenericParamBuilder<NumStaticParams, SendEmpty, WriteNumericSink>(WriteNumericSink(user), num, user->nick.size())
196         {
197         }
198 };
199
200 namespace Numerics
201 {
202         class InvalidModeParameter;
203         class NoSuchChannel;
204         class NoSuchNick;
205 }
206
207 /* Builder for the ERR_INVALIDMODEPARAM numeric. */
208 class Numerics::InvalidModeParameter : public Numeric::Numeric
209 {
210  private:
211         void push_message(ModeHandler* mode, const std::string& message)
212         {
213                 if (!message.empty())
214                 {
215                         // The caller has specified their own message.
216                         push(message);
217                         return;
218                 }
219
220                 const std::string& syntax = mode->GetSyntax();
221                 if (!syntax.empty())
222                 {
223                         // If the mode has a syntax hint we include it in the message.
224                         push(InspIRCd::Format("Invalid %s mode parameter. Syntax: %s.", mode->name.c_str(), syntax.c_str()));
225                 }
226                 else
227                 {
228                         // Otherwise, send it without.
229                         push(InspIRCd::Format("Invalid %s mode parameter.", mode->name.c_str()));
230                 }
231         }
232
233  public:
234         InvalidModeParameter(Channel* chan, ModeHandler* mode, const std::string& parameter, const std::string& message = "")
235                 : Numeric(ERR_INVALIDMODEPARAM)
236         {
237                 push(chan->name);
238                 push(mode->GetModeChar());
239                 push(parameter);
240                 push_message(mode, message);
241         }
242
243         InvalidModeParameter(User* user, ModeHandler* mode, const std::string& parameter, const std::string& message = "")
244                 : Numeric(ERR_INVALIDMODEPARAM)
245         {
246                 push(user->registered & REG_NICK ? user->nick : "*");
247                 push(mode->GetModeChar());
248                 push(parameter);
249                 push_message(mode, message);
250         }
251 };
252
253 /** Builder for the ERR_NOSUCHCHANNEL numeric. */
254 class Numerics::NoSuchChannel : public Numeric::Numeric
255 {
256  public:
257         NoSuchChannel(const std::string& chan)
258                 : Numeric(ERR_NOSUCHCHANNEL)
259         {
260                 push(chan.empty() ? "*" : chan);
261                 push("No such channel");
262         }
263 };
264
265 /** Builder for the ERR_NOSUCHNICK numeric. */
266 class Numerics::NoSuchNick : public Numeric::Numeric
267 {
268  public:
269         NoSuchNick(const std::string& nick)
270                 : Numeric(ERR_NOSUCHNICK)
271         {
272                 push(nick.empty() ? "*" : nick);
273                 push("No such nick");
274         }
275 };