InspIRCd  4.0
numericbuilder.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  * Copyright (C) 2018-2020 Sadie Powell <[email protected]>
5  * Copyright (C) 2015-2016 Attila Molnar <[email protected]>
6  *
7  * This file is part of InspIRCd. InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 
21 #pragma once
22 
23 namespace Numeric
24 {
25  class WriteNumericSink;
26  class WriteRemoteNumericSink;
27 
28  template <char Sep, bool SendEmpty, typename Sink>
29  class GenericBuilder;
30 
31  template <char Sep = ',', bool SendEmpty = false>
32  class Builder;
33 
34  template <unsigned int NumStaticParams, bool SendEmpty, typename Sink>
35  class GenericParamBuilder;
36 
37  template <unsigned int NumStaticParams, bool SendEmpty = false>
38  class ParamBuilder;
39 }
40 
42 {
43  LocalUser* const user;
44 
45  public:
47  : user(u)
48  {
49  }
50 
51  void operator()(Numeric& numeric) const
52  {
53  user->WriteNumeric(numeric);
54  }
55 };
56 
58 {
59  User* const user;
60 
61  public:
63  : user(u)
64  {
65  }
66 
67  void operator()(Numeric& numeric) const
68  {
69  user->WriteRemoteNumeric(numeric);
70  }
71 };
72 
73 template <char Sep, bool SendEmpty, typename Sink>
75 {
76  Sink sink;
77  Numeric numeric;
78  const std::string::size_type max;
79 
80  bool HasRoom(const std::string::size_type additional) const
81  {
82  return (numeric.GetParams().back().size() + additional <= max);
83  }
84 
85  public:
86  GenericBuilder(Sink s, unsigned int num, bool addparam = true, size_t additionalsize = 0)
87  : sink(s)
88  , numeric(num)
89  , max(ServerInstance->Config->Limits.MaxLine - ServerInstance->Config->GetServerName().size() - additionalsize - 10)
90  {
91  if (addparam)
92  numeric.push(std::string());
93  }
94 
95  Numeric& GetNumeric() { return numeric; }
96 
97  void Add(const std::string& entry)
98  {
99  if (!HasRoom(entry.size()))
100  Flush();
101  numeric.GetParams().back().append(entry).push_back(Sep);
102  }
103 
104  void Add(const std::string& entry1, const std::string& entry2)
105  {
106  if (!HasRoom(entry1.size() + entry2.size()))
107  Flush();
108  numeric.GetParams().back().append(entry1).append(entry2).push_back(Sep);
109  }
110 
111  void Flush()
112  {
113  std::string& data = numeric.GetParams().back();
114  if (IsEmpty())
115  {
116  if (!SendEmpty)
117  return;
118  }
119  else
120  {
121  data.erase(data.size()-1);
122  }
123 
124  sink(numeric);
125  data.clear();
126  }
127 
128  bool IsEmpty() const { return (numeric.GetParams().back().empty()); }
129 };
130 
131 template <char Sep, bool SendEmpty>
132 class Numeric::Builder : public GenericBuilder<Sep, SendEmpty, WriteNumericSink>
133 {
134  public:
135  Builder(LocalUser* user, unsigned int num, bool addparam = true, size_t additionalsize = 0)
136  : ::Numeric::GenericBuilder<Sep, SendEmpty, WriteNumericSink>(WriteNumericSink(user), num, addparam, additionalsize + user->nick.size())
137  {
138  }
139 };
140 
141 template <unsigned int NumStaticParams, bool SendEmpty, typename Sink>
143 {
144  Sink sink;
145  Numeric numeric;
146  std::string::size_type currlen = 0;
147  std::string::size_type max;
148 
149  bool HasRoom(const std::string::size_type additional) const
150  {
151  return (currlen + additional <= max);
152  }
153 
154  public:
155  GenericParamBuilder(Sink s, unsigned int num, size_t additionalsize)
156  : sink(s)
157  , numeric(num)
158  , max(ServerInstance->Config->Limits.MaxLine - ServerInstance->Config->GetServerName().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)
196  {
197  }
198 };
199 
200 namespace Numerics
201 {
202  class CannotSendTo;
203  class InvalidModeParameter;
204  class NoSuchChannel;
205  class NoSuchNick;
206 }
207 
210 {
211  public:
212  CannotSendTo(Channel* chan, const std::string& message)
213  : Numeric(ERR_CANNOTSENDTOCHAN)
214  {
215  push(chan->name);
216  push(message);
217  }
218 
219  CannotSendTo(Channel* chan, const std::string& what, ModeHandler* mh)
220  : Numeric(ERR_CANNOTSENDTOCHAN)
221  {
222  push(chan->name);
223  push(InspIRCd::Format("You cannot send %s to this channel whilst the +%c (%s) mode is set.",
224  what.c_str(), mh->GetModeChar(), mh->name.c_str()));
225  }
226 
227  CannotSendTo(Channel* chan, const std::string& what, char extban, const std::string& extbandesc)
228  : Numeric(ERR_CANNOTSENDTOCHAN)
229  {
230  push(chan->name);
231  push(InspIRCd::Format("You cannot send %s to this channel whilst %s %c: (%s) extban is set matching you.",
232  what.c_str(), strchr("AEIOUaeiou", extban) ? "an" : "a", extban, extbandesc.c_str()));
233  }
234 
235  CannotSendTo(User* user, const std::string& message)
236  : Numeric(ERR_CANNOTSENDTOUSER)
237  {
238  push(user->registered & REG_NICK ? user->nick : "*");
239  push(message);
240  }
241 
242  CannotSendTo(User* user, const std::string& what, ModeHandler* mh, bool self = false)
243  : Numeric(ERR_CANNOTSENDTOUSER)
244  {
245  push(user->registered & REG_NICK ? user->nick : "*");
246  push(InspIRCd::Format("You cannot send %s to this user whilst %s have the +%c (%s) mode set.",
247  what.c_str(), self ? "you" : "they", mh->GetModeChar(), mh->name.c_str()));
248  }
249 };
250 
251 /* Builder for the ERR_INVALIDMODEPARAM numeric. */
253 {
254  private:
255  void push_message(ModeHandler* mode, const std::string& message)
256  {
257  if (!message.empty())
258  {
259  // The caller has specified their own message.
260  push(message);
261  return;
262  }
263 
264  const std::string& syntax = mode->GetSyntax();
265  if (!syntax.empty())
266  {
267  // If the mode has a syntax hint we include it in the message.
268  push(InspIRCd::Format("Invalid %s mode parameter. Syntax: %s.", mode->name.c_str(), syntax.c_str()));
269  }
270  else
271  {
272  // Otherwise, send it without.
273  push(InspIRCd::Format("Invalid %s mode parameter.", mode->name.c_str()));
274  }
275  }
276 
277  public:
278  InvalidModeParameter(Channel* chan, ModeHandler* mode, const std::string& parameter, const std::string& message = "")
279  : Numeric(ERR_INVALIDMODEPARAM)
280  {
281  push(chan->name);
282  push(mode->GetModeChar());
283  push(parameter);
284  push_message(mode, message);
285  }
286 
287  InvalidModeParameter(User* user, ModeHandler* mode, const std::string& parameter, const std::string& message = "")
288  : Numeric(ERR_INVALIDMODEPARAM)
289  {
290  push(user->registered & REG_NICK ? user->nick : "*");
291  push(mode->GetModeChar());
292  push(parameter);
293  push_message(mode, message);
294  }
295 };
296 
299 {
300  public:
301  NoSuchChannel(const std::string& chan)
302  : Numeric(ERR_NOSUCHCHANNEL)
303  {
304  push(chan.empty() ? "*" : chan);
305  push("No such channel");
306  }
307 };
308 
311 {
312  public:
313  NoSuchNick(const std::string& nick)
314  : Numeric(ERR_NOSUCHNICK)
315  {
316  push(nick.empty() ? "*" : nick);
317  push("No such nick");
318  }
319 };
Definition: channels.h:41
std::string name
Definition: channels.h:88
static std::string Format(const char *formatString,...)
Definition: helperfuncs.cpp:409
ServerConfig * Config
Definition: inspircd.h:265
Definition: users.h:658
Definition: mode.h:100
char GetModeChar() const
Definition: mode.h:242
const std::string & GetSyntax() const
Definition: mode.h:342
Definition: numericbuilder.h:133
Definition: numericbuilder.h:75
Definition: numericbuilder.h:143
Definition: numeric.h:31
Numeric & push(const Args &... args)
Definition: numeric.h:57
Numeric(unsigned int num)
Definition: numeric.h:48
Definition: numericbuilder.h:192
Definition: numericbuilder.h:42
Definition: numericbuilder.h:58
Definition: numericbuilder.h:210
Definition: numericbuilder.h:253
Definition: numericbuilder.h:299
Definition: numericbuilder.h:311
ServerLimits Limits
Definition: configreader.h:340
const std::string & GetServerName() const
Definition: configreader.h:474
size_t MaxLine
Definition: configreader.h:119
const std::string name
Definition: base.h:209
Definition: users.h:238
std::string nick
Definition: users.h:328
unsigned int registered
Definition: users.h:371