1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
|
/*
* Anope IRC Services
*
* Copyright (C) 2012-2016 Anope Team <team@anope.org>
*
* This file is part of Anope. Anope is free software; you can
* redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software
* Foundation, version 2.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "services.h"
#include "anope.h"
#include "service.h"
#include "servers.h"
#include "users.h"
#include "messages.h"
class IRCMessage;
/* Encapsultes the IRCd protocol we are speaking. */
class CoreExport IRCDProto : public Service
{
Anope::string proto_name;
public:
static constexpr const char *NAME = "ircdproto";
/* Modes used by default by our clients */
Anope::string DefaultPseudoclientModes = "+io";
/* Can we force change a users's nick? */
bool CanSVSNick = false;
/* Can we force join or part users? */
bool CanSVSJoin = false;
/* Can we set vhosts/vidents on users? */
bool CanSetVHost = false, CanSetVIdent = false;
/* Can we ban specific gecos from being used? */
bool CanSNLine = false;
/* Can we ban specific nicknames from being used? */
bool CanSQLine = false;
/* Can we ban sepcific channel names from being used? */
bool CanSQLineChannel = false;
/* Can we ban by IP? */
bool CanSZLine = false;
/* Can we place temporary holds on specific nicknames? */
bool CanSVSHold = false;
/* See ns_cert */
bool CanCertFP = false;
/* Whether this IRCd requires unique IDs for each user or server. See TS6/P10. */
bool RequiresID = false;
/* If this IRCd has unique ids, whether the IDs and nicknames are ambiguous */
bool AmbiguousID = false;
/* The maximum number of modes we are allowed to set with one MODE command */
unsigned int MaxModes = 3;
/* The maximum number of bytes a line may have */
unsigned int MaxLine = 512;
IRCDProto(Module *creator, const Anope::string &proto_name);
virtual ~IRCDProto();
const Anope::string &GetProtocolName() const;
virtual void Parse(const Anope::string &, Anope::string &, Anope::string &, std::vector<Anope::string> &);
virtual Anope::string Format(IRCMessage &);
virtual void SendCTCPReply(const MessageSource &, const Anope::string &dest, const Anope::string &buf);
virtual void SendNumeric(int numeric, User *dest, IRCMessage &);
/* Retrieves the next free UID or SID */
virtual Anope::string UID_Retrieve() { return ""; }
virtual Anope::string SID_Retrieve() { return ""; }
virtual void SendAction(const MessageSource &source, const Anope::string &dest, const Anope::string &message);
/** Used to introduce ourselves to our uplink.
*/
virtual void Handshake() anope_abstract;
/** Called right before we begin our burst, after we have handshaked successfully with the uplink.
* At this point none of our servers, users, or channels exist on the uplink
*/
virtual void SendBOB() { }
virtual void SendEOB() { }
virtual bool IsNickValid(const Anope::string &);
virtual bool IsChannelValid(const Anope::string &);
virtual bool IsIdentValid(const Anope::string &);
virtual bool IsHostValid(const Anope::string &);
virtual bool IsExtbanValid(const Anope::string &) { return false; }
/** Retrieve the maximum number of list modes settable on this channel
* Defaults to Config->ListSize
*/
virtual unsigned int GetMaxListFor(Channel *c);
virtual Anope::string NormalizeMask(const Anope::string &mask);
template<typename T, typename... Args> void Send(Args&&... args)
{
ServiceReference<MessageSender<T>> sender(T::NAME);
if (!sender)
{
const char *const name = T::NAME;
Anope::Logger.Debug("No message sender for type {0}", name);
return;
}
static_cast<T*>(static_cast<MessageSender<T>*>(sender))->Send(std::forward<Args>(args)...);
}
/* Templated functions which overload the normal functions to provide format strings */
template<typename... Args> void SendKill(const MessageSource &source, User *user, const Anope::string &reason, Args&&... args)
{
Send<messages::Kill>(source, user, Anope::Format(reason, std::forward<Args>(args)...));
}
template<typename... Args> void SendMode(const MessageSource &source, Channel *chan, const Anope::string &modes, Args&&... args)
{
Send<messages::ModeChannel>(source, chan, Anope::Format(modes, std::forward<Args>(args)...));
}
template<typename... Args> void SendMode(const MessageSource &source, User *u, const Anope::string &modes, Args&&... args)
{
Send<messages::ModeUser>(source, u, Anope::Format(modes, std::forward<Args>(args)...));
}
template<typename... Args> void SendKick(const MessageSource &source, Channel *chan, User *user, const Anope::string &reason, Args&&... args)
{
Send<messages::Kick>(source, chan, user, Anope::Format(reason, std::forward<Args>(args)...));
}
template<typename... Args> void SendNotice(const MessageSource &source, const Anope::string &dest, const Anope::string &message, Args&&... args)
{
Send<messages::Notice>(source, dest, Anope::Format(message, std::forward<Args>(args)...));
}
template<typename... Args> void SendPrivmsg(const MessageSource &source, const Anope::string &dest, const Anope::string &message, Args&&... args)
{
Send<messages::Privmsg>(source, dest, Anope::Format(message, std::forward<Args>(args)...));
}
template<typename... Args> void SendAction(const MessageSource &source, const Anope::string &dest, const Anope::string &message, Args&&... args)
{
SendAction(source, dest, Anope::Format(message, std::forward<Args>(args)...));
}
template<typename... Args> void SendCTCPReply(const MessageSource &source, const Anope::string &dest, const Anope::string &message, Args&&... args)
{
SendCTCPReply(source, dest, Anope::Format(message, std::forward<Args>(args)...));
}
template<typename... Args> void SendWallops(const MessageSource &source, const Anope::string &msg, Args&&... args)
{
Send<messages::Wallops>(source, Anope::Format(msg, std::forward<Args>(args)...));
}
template<typename... Args> void SendNumeric(int numeric, User *dest, Args&&... args);
template<typename... Args> void SendQuit(User *u, const Anope::string &reason, Args&&... args)
{
Send<messages::Quit>(u, Anope::Format(reason, std::forward<Args>(args)...));
}
template<typename... Args> void SendPart(User *u, Channel *chan, const Anope::string &reason, Args&&... args)
{
Send<messages::Part>(u, chan, Anope::Format(reason, std::forward<Args>(args)...));
}
};
class CoreExport MessageSource
{
Anope::string source;
User *u = nullptr;
Server *s = nullptr;
public:
MessageSource(const Anope::string &);
MessageSource(User *u);
MessageSource(Server *s);
const Anope::string &GetName() const;
const Anope::string &GetUID() const;
const Anope::string &GetSource() const;
User *GetUser() const;
ServiceBot *GetBot() const;
Server *GetServer() const;
};
enum IRCDMessageFlag
{
IRCDMESSAGE_SOFT_LIMIT,
IRCDMESSAGE_REQUIRE_SERVER,
IRCDMESSAGE_REQUIRE_USER
};
class CoreExport IRCDMessage : public Service
{
Anope::string name;
unsigned int param_count;
std::set<IRCDMessageFlag> flags;
public:
static constexpr const char *NAME = "ircdmessage";
IRCDMessage(Module *owner, const Anope::string &n, unsigned int p = 0);
unsigned int GetParamCount() const;
virtual void Run(MessageSource &, const std::vector<Anope::string> ¶ms) anope_abstract;
void SetFlag(IRCDMessageFlag f) { flags.insert(f); }
bool HasFlag(IRCDMessageFlag f) const { return flags.count(f); }
};
extern CoreExport IRCDProto *IRCD;
class IRCMessage
{
MessageSource source;
Anope::string command;
std::vector<Anope::string> parameters;
public:
template<typename... Args>
IRCMessage(const MessageSource &_source, const Anope::string &_command, Args&&... args)
: source(_source)
, command(_command)
{
parameters.reserve(sizeof...(args));
Push(std::forward<Args>(args)...);
}
template<typename T, typename... Args>
void Push(const T& t, Args&&... args)
{
parameters.push_back(stringify(t));
Push(std::forward<Args>(args)...);
}
void Push() { }
void TokenizeAndPush(const Anope::string &buf, char sepToken = ' ')
{
sepstream sep(buf, sepToken);
Anope::string token;
while (sep.GetToken(token))
Push(token);
}
const MessageSource &GetSource() const
{
return source;
}
void SetSource(const MessageSource &_source)
{
this->source = _source;
}
const Anope::string &GetCommand() const
{
return command;
}
const std::vector<Anope::string> &GetParameters() const
{
return parameters;
}
};
template<typename... Args>
void IRCDProto::SendNumeric(int numeric, User *dest, Args&&... args)
{
Anope::string numstr = stringify(numeric);
if (numeric < 10)
numstr.insert(numstr.begin(), '0');
if (numeric < 100)
numstr.insert(numstr.begin(), '0');
IRCMessage message(Me, numstr, dest->GetUID());
message.Push(std::forward<Args>(args)...);
SendNumeric(numeric, dest, message);
}
|