InspIRCd  3.0
numericbuilder.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  * Copyright (C) 2018-2019 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>
30 
31  template <char Sep = ',', bool SendEmpty = false>
32  class Builder;
33 
34  template <unsigned int NumStaticParams, bool SendEmpty, typename Sink>
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->ServerName.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;
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  , currlen(0)
159  , max(ServerInstance->Config->Limits.MaxLine - ServerInstance->Config->ServerName.size() - additionalsize - 10)
160  {
161  }
162 
163  void AddStatic(const std::string& entry)
164  {
165  max -= (entry.length() + 1);
166  numeric.GetParams().push_back(entry);
167  }
168 
169  void Add(const std::string& entry)
170  {
171  if (!HasRoom(entry.size()))
172  Flush();
173 
174  currlen += entry.size() + 1;
175  numeric.GetParams().push_back(entry);
176  }
177 
178  void Flush()
179  {
180  if ((!SendEmpty) && (IsEmpty()))
181  return;
182 
183  sink(numeric);
184  currlen = 0;
185  numeric.GetParams().erase(numeric.GetParams().begin() + NumStaticParams, numeric.GetParams().end());
186  }
187 
188  bool IsEmpty() const { return (numeric.GetParams().size() <= NumStaticParams); }
189 };
190 
191 template <unsigned int NumStaticParams, bool SendEmpty>
192 class Numeric::ParamBuilder : public GenericParamBuilder<NumStaticParams, SendEmpty, WriteNumericSink>
193 {
194  public:
195  ParamBuilder(LocalUser* user, unsigned int num)
196  : ::Numeric::GenericParamBuilder<NumStaticParams, SendEmpty, WriteNumericSink>(WriteNumericSink(user), num, user->nick.size())
197  {
198  }
199 };
200 
201 namespace Numerics
202 {
203  class InvalidModeParameter;
204  class NoSuchChannel;
205  class NoSuchNick;
206 }
207 
208 /* Builder for the ERR_INVALIDMODEPARAM numeric. */
210 {
211  private:
212  void push_message(ModeHandler* mode, const std::string& message)
213  {
214  if (!message.empty())
215  {
216  // The caller has specified their own message.
217  push(message);
218  return;
219  }
220 
221  const std::string& syntax = mode->GetSyntax();
222  if (!syntax.empty())
223  {
224  // If the mode has a syntax hint we include it in the message.
225  push(InspIRCd::Format("Invalid %s mode parameter. Syntax: %s.", mode->name.c_str(), syntax.c_str()));
226  }
227  else
228  {
229  // Otherwise, send it without.
230  push(InspIRCd::Format("Invalid %s mode parameter.", mode->name.c_str()));
231  }
232  }
233 
234  public:
235  InvalidModeParameter(Channel* chan, ModeHandler* mode, const std::string& parameter, const std::string& message = "")
236  : Numeric(ERR_INVALIDMODEPARAM)
237  {
238  push(chan->name);
239  push(mode->GetModeChar());
240  push(parameter);
241  push_message(mode, message);
242  }
243 
244  InvalidModeParameter(User* user, ModeHandler* mode, const std::string& parameter, const std::string& message = "")
245  : Numeric(ERR_INVALIDMODEPARAM)
246  {
247  push(user->registered & REG_NICK ? user->nick : "*");
248  push(mode->GetModeChar());
249  push(parameter);
250  push_message(mode, message);
251  }
252 };
253 
256 {
257  public:
258  NoSuchChannel(const std::string& chan)
259  : Numeric(ERR_NOSUCHCHANNEL)
260  {
261  push(chan.empty() ? "*" : chan);
262  push("No such channel");
263  }
264 };
265 
268 {
269  public:
270  NoSuchNick(const std::string& nick)
271  : Numeric(ERR_NOSUCHNICK)
272  {
273  push(nick.empty() ? "*" : nick);
274  push("No such nick");
275  }
276 };
Numeric::Numeric::push
Numeric & push(const T &x)
Definition: numeric.h:58
Channel::name
std::string name
Definition: channels.h:88
InspIRCd::Format
static std::string Format(const char *formatString,...)
Definition: helperfuncs.cpp:479
Numerics::InvalidModeParameter
Definition: numericbuilder.h:209
Numeric::WriteRemoteNumericSink
Definition: numericbuilder.h:57
Numeric::Builder
Definition: numericbuilder.h:32
Numerics::NoSuchChannel
Definition: numericbuilder.h:255
Numeric::GenericBuilder
Definition: numericbuilder.h:29
Numeric::ParamBuilder
Definition: numericbuilder.h:38
Channel
Definition: channels.h:40
Numeric::WriteNumericSink
Definition: numericbuilder.h:41
Numeric::Numeric::Numeric
Numeric(unsigned int num)
Definition: numeric.h:48
User::nick
std::string nick
Definition: users.h:311
Numerics::NoSuchNick
Definition: numericbuilder.h:267
User
Definition: users.h:233
Numeric::GenericParamBuilder
Definition: numericbuilder.h:35
Numeric::Numeric
Definition: numeric.h:30
ModeHandler
Definition: mode.h:99
LocalUser
Definition: users.h:727
User::registered
unsigned int registered
Definition: users.h:354