Anope IRC Services  Version 2.0
protocol.cpp
Go to the documentation of this file.
1 /*
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  */
12 
13 #include "services.h"
14 #include "modules.h"
15 #include "protocol.h"
16 #include "users.h"
17 #include "servers.h"
18 #include "config.h"
19 #include "uplink.h"
20 #include "bots.h"
21 #include "channels.h"
22 
23 IRCDProto *IRCD = NULL;
24 
25 IRCDProto::IRCDProto(Module *creator, const Anope::string &p) : Service(creator, "IRCDProto", creator->name), proto_name(p)
26 {
30  MaxModes = 3;
31  MaxLine = 512;
32 
33  if (IRCD == NULL)
34  IRCD = this;
35 }
36 
38 {
39  if (IRCD == this)
40  IRCD = NULL;
41 }
42 
44 {
45  return this->proto_name;
46 }
47 
48 static inline char& nextID(char &c)
49 {
50  if (c == 'Z')
51  c = '0';
52  else if (c != '9')
53  ++c;
54  else
55  c = 'A';
56  return c;
57 }
58 
60 {
61  if (!IRCD || !IRCD->RequiresID)
62  return "";
63 
64  static Anope::string current_uid = "AAAAAA";
65 
66  do
67  {
68  int current_len = current_uid.length() - 1;
69  while (current_len >= 0 && nextID(current_uid[current_len--]) == 'A');
70  }
71  while (User::Find(Me->GetSID() + current_uid) != NULL);
72 
73  return Me->GetSID() + current_uid;
74 }
75 
77 {
78  if (!IRCD || !IRCD->RequiresID)
79  return "";
80 
81  static Anope::string current_sid = Config->GetBlock("serverinfo")->Get<const Anope::string>("id");
82  if (current_sid.empty())
83  current_sid = "00A";
84 
85  do
86  {
87  int current_len = current_sid.length() - 1;
88  while (current_len >= 0 && nextID(current_sid[current_len--]) == 'A');
89  }
90  while (Server::Find(current_sid) != NULL);
91 
92  return current_sid;
93 }
94 
95 void IRCDProto::SendKill(const MessageSource &source, const Anope::string &target, const Anope::string &reason)
96 {
97  UplinkSocket::Message(source) << "KILL " << target << " :" << reason;
98 }
99 
100 void IRCDProto::SendSVSKillInternal(const MessageSource &source, User *user, const Anope::string &buf)
101 {
102  UplinkSocket::Message(source) << "KILL " << user->GetUID() << " :" << buf;
103 }
104 
105 void IRCDProto::SendModeInternal(const MessageSource &source, const Channel *dest, const Anope::string &buf)
106 {
107  UplinkSocket::Message(source) << "MODE " << dest->name << " " << buf;
108 }
109 
110 void IRCDProto::SendModeInternal(const MessageSource &source, User *dest, const Anope::string &buf)
111 {
112  UplinkSocket::Message(source) << "MODE " << dest->GetUID() << " " << buf;
113 }
114 
115 void IRCDProto::SendKickInternal(const MessageSource &source, const Channel *c, User *u, const Anope::string &r)
116 {
117  if (!r.empty())
118  UplinkSocket::Message(source) << "KICK " << c->name << " " << u->GetUID() << " :" << r;
119  else
120  UplinkSocket::Message(source) << "KICK " << c->name << " " << u->GetUID();
121 }
122 
123 void IRCDProto::SendNoticeInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &msg)
124 {
125  UplinkSocket::Message(source) << "NOTICE " << dest << " :" << msg;
126 }
127 
128 void IRCDProto::SendPrivmsgInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &buf)
129 {
130  UplinkSocket::Message(source) << "PRIVMSG " << dest << " :" << buf;
131 }
132 
134 {
135  if (!buf.empty())
136  UplinkSocket::Message(u) << "QUIT :" << buf;
137  else
138  UplinkSocket::Message(u) << "QUIT";
139 }
140 
141 void IRCDProto::SendPartInternal(User *u, const Channel *chan, const Anope::string &buf)
142 {
143  if (!buf.empty())
144  UplinkSocket::Message(u) << "PART " << chan->name << " :" << buf;
145  else
146  UplinkSocket::Message(u) << "PART " << chan->name;
147 }
148 
150 {
151  UplinkSocket::Message(source) << "GLOBOPS :" << buf;
152 }
153 
154 void IRCDProto::SendCTCPInternal(const MessageSource &source, const Anope::string &dest, const Anope::string &buf)
155 {
157  this->SendNoticeInternal(source, dest, "\1" + s + "\1");
158 }
159 
160 void IRCDProto::SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf)
161 {
162  Anope::string n = stringify(numeric);
163  if (numeric < 10)
164  n = "0" + n;
165  if (numeric < 100)
166  n = "0" + n;
167  UplinkSocket::Message(Me) << n << " " << dest << " " << buf;
168 }
169 
171 {
172  UplinkSocket::Message(source) << "TOPIC " << c->name << " :" << c->topic;
173 }
174 
175 void IRCDProto::SendSVSKill(const MessageSource &source, User *user, const char *fmt, ...)
176 {
177  if (!user || !fmt)
178  return;
179 
180  va_list args;
181  char buf[BUFSIZE] = "";
182  va_start(args, fmt);
183  vsnprintf(buf, BUFSIZE - 1, fmt, args);
184  va_end(args);
185  SendSVSKillInternal(source, user, buf);
186 }
187 
188 void IRCDProto::SendMode(const MessageSource &source, const Channel *dest, const char *fmt, ...)
189 {
190  va_list args;
191  char buf[BUFSIZE] = "";
192  va_start(args, fmt);
193  vsnprintf(buf, BUFSIZE - 1, fmt, args);
194  va_end(args);
195  SendModeInternal(source, dest, buf);
196 }
197 
198 void IRCDProto::SendMode(const MessageSource &source, User *u, const char *fmt, ...)
199 {
200  va_list args;
201  char buf[BUFSIZE] = "";
202  va_start(args, fmt);
203  vsnprintf(buf, BUFSIZE - 1, fmt, args);
204  va_end(args);
205  SendModeInternal(source, u, buf);
206 }
207 
208 void IRCDProto::SendKick(const MessageSource &source, const Channel *chan, User *user, const char *fmt, ...)
209 {
210  if (!chan || !user)
211  return;
212 
213  va_list args;
214  char buf[BUFSIZE] = "";
215  va_start(args, fmt);
216  vsnprintf(buf, BUFSIZE - 1, fmt, args);
217  va_end(args);
218  SendKickInternal(source, chan, user, buf);
219 }
220 
221 void IRCDProto::SendNotice(const MessageSource &source, const Anope::string &dest, const char *fmt, ...)
222 {
223  va_list args;
224  char buf[BUFSIZE] = "";
225  va_start(args, fmt);
226  vsnprintf(buf, BUFSIZE - 1, fmt, args);
227  va_end(args);
228  SendNoticeInternal(source, dest, buf);
229 }
230 
231 void IRCDProto::SendAction(const MessageSource &source, const Anope::string &dest, const char *fmt, ...)
232 {
233  va_list args;
234  char buf[BUFSIZE] = "";
235  va_start(args, fmt);
236  vsnprintf(buf, BUFSIZE - 1, fmt, args);
237  va_end(args);
238  Anope::string actionbuf = Anope::string("\1ACTION ") + buf + '\1';
239  SendPrivmsgInternal(source, dest, actionbuf);
240 }
241 
242 void IRCDProto::SendPrivmsg(const MessageSource &source, const Anope::string &dest, const char *fmt, ...)
243 {
244  va_list args;
245  char buf[BUFSIZE] = "";
246  va_start(args, fmt);
247  vsnprintf(buf, BUFSIZE - 1, fmt, args);
248  va_end(args);
249  SendPrivmsgInternal(source, dest, buf);
250 }
251 
252 void IRCDProto::SendQuit(User *u, const char *fmt, ...)
253 {
254  va_list args;
255  char buf[BUFSIZE] = "";
256  va_start(args, fmt);
257  vsnprintf(buf, BUFSIZE - 1, fmt, args);
258  va_end(args);
259  SendQuitInternal(u, buf);
260 }
261 
262 void IRCDProto::SendPing(const Anope::string &servname, const Anope::string &who)
263 {
264  if (servname.empty())
265  UplinkSocket::Message(Me) << "PING " << who;
266  else
267  UplinkSocket::Message(Me) << "PING " << servname << " " << who;
268 }
269 
276 void IRCDProto::SendPong(const Anope::string &servname, const Anope::string &who)
277 {
278  if (servname.empty())
279  UplinkSocket::Message(Me) << "PONG " << who;
280  else
281  UplinkSocket::Message(Me) << "PONG " << servname << " " << who;
282 }
283 
284 void IRCDProto::SendInvite(const MessageSource &source, const Channel *c, User *u)
285 {
286  UplinkSocket::Message(source) << "INVITE " << u->GetUID() << " " << c->name;
287 }
288 
289 void IRCDProto::SendPart(User *user, const Channel *chan, const char *fmt, ...)
290 {
291  if (fmt)
292  {
293  va_list args;
294  char buf[BUFSIZE] = "";
295  va_start(args, fmt);
296  vsnprintf(buf, BUFSIZE - 1, fmt, args);
297  va_end(args);
298  SendPartInternal(user, chan, buf);
299  }
300  else
301  SendPartInternal(user, chan, "");
302 }
303 
304 void IRCDProto::SendGlobops(const MessageSource &source, const char *fmt, ...)
305 {
306  va_list args;
307  char buf[BUFSIZE] = "";
308  va_start(args, fmt);
309  vsnprintf(buf, BUFSIZE - 1, fmt, args);
310  va_end(args);
311  SendGlobopsInternal(source, buf);
312 }
313 
314 void IRCDProto::SendSquit(Server *s, const Anope::string &message)
315 {
316  UplinkSocket::Message() << "SQUIT " << s->GetSID() << " :" << message;
317 }
318 
320 {
321  UplinkSocket::Message(u) << "NICK " << newnick << " " << Anope::CurTime;
322 }
323 
324 void IRCDProto::SendForceNickChange(User *u, const Anope::string &newnick, time_t when)
325 {
326  UplinkSocket::Message() << "SVSNICK " << u->GetUID() << " " << newnick << " " << when;
327 }
328 
329 void IRCDProto::SendCTCP(const MessageSource &source, const Anope::string &dest, const char *fmt, ...)
330 {
331  va_list args;
332  char buf[BUFSIZE] = "";
333  va_start(args, fmt);
334  vsnprintf(buf, BUFSIZE - 1, fmt, args);
335  va_end(args);
336  SendCTCPInternal(source, dest, buf);
337 }
338 
339 void IRCDProto::SendNumeric(int numeric, const Anope::string &dest, const char *fmt, ...)
340 {
341  va_list args;
342  char buf[BUFSIZE] = "";
343  va_start(args, fmt);
344  vsnprintf(buf, BUFSIZE - 1, fmt, args);
345  va_end(args);
346  SendNumericInternal(numeric, dest, buf);
347 }
348 
350 {
359  if (nick.empty())
360  return false;
361 
362  Anope::string special = "[]\\`_^{|}";
363 
364  for (unsigned i = 0; i < nick.length(); ++i)
365  if (!(nick[i] >= 'A' && nick[i] <= 'Z') && !(nick[i] >= 'a' && nick[i] <= 'z') && special.find(nick[i]) == Anope::string::npos
366  && (!i || (!(nick[i] >= '0' && nick[i] <= '9') && nick[i] != '-')))
367  return false;
368 
369  return true;
370 }
371 
373 {
374  if (chan.empty() || chan[0] != '#' || chan.length() > Config->GetBlock("networkinfo")->Get<unsigned>("chanlen"))
375  return false;
376 
377  if (chan.find_first_of(" ,") != Anope::string::npos)
378  return false;
379 
380  return true;
381 }
382 
384 {
385  if (ident.empty() || ident.length() > Config->GetBlock("networkinfo")->Get<unsigned>("userlen"))
386  return false;
387 
388  for (unsigned i = 0; i < ident.length(); ++i)
389  {
390  const char &c = ident[i];
391 
392  if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-')
393  continue;
394 
395  return false;
396  }
397 
398  return true;
399 }
400 
402 {
403  if (host.empty() || host.length() > Config->GetBlock("networkinfo")->Get<unsigned>("hostlen"))
404  return false;
405 
406  const Anope::string &vhostdisablebe = Config->GetBlock("networkinfo")->Get<const Anope::string>("disallow_start_or_end"),
407  vhostchars = Config->GetBlock("networkinfo")->Get<const Anope::string>("vhost_chars");
408 
409  if (vhostdisablebe.find_first_of(host[0]) != Anope::string::npos)
410  return false;
411  else if (vhostdisablebe.find_first_of(host[host.length() - 1]) != Anope::string::npos)
412  return false;
413 
414  int dots = 0;
415  for (unsigned i = 0; i < host.length(); ++i)
416  {
417  if (host[i] == '.')
418  ++dots;
419  if (vhostchars.find_first_of(host[i]) == Anope::string::npos)
420  return false;
421  }
422 
423  return dots > 0 || Config->GetBlock("networkinfo")->Get<bool>("allow_undotted_vhosts");
424 }
425 
427 {
428  SendNumericInternal(381, u->GetUID(), ":You are now an IRC operator (set by services)");
429  u->SetMode(NULL, "OPER");
430 }
431 
433 {
434  return c->HasMode("LBAN") ? 0 : Config->GetBlock("networkinfo")->Get<int>("modelistsize");
435 }
436 
438 {
439  if (IsExtbanValid(mask))
440  return mask;
441  return Entry("", mask).GetNUHMask();
442 }
443 
444 MessageSource::MessageSource(const Anope::string &src) : source(src), u(NULL), s(NULL)
445 {
446  /* no source for incoming message is our uplink */
447  if (src.empty())
448  this->s = Servers::GetUplink();
449  else if (IRCD->RequiresID || src.find('.') != Anope::string::npos)
450  this->s = Server::Find(src);
451  if (this->s == NULL)
452  this->u = User::Find(src);
453 }
454 
455 MessageSource::MessageSource(User *_u) : source(_u ? _u->nick : ""), u(_u), s(NULL)
456 {
457 }
458 
459 MessageSource::MessageSource(Server *_s) : source(_s ? _s->GetName() : ""), u(NULL), s(_s)
460 {
461 }
462 
464 {
465  if (this->s)
466  return this->s->GetName();
467  else if (this->u)
468  return this->u->nick;
469  else
470  return this->source;
471 }
472 
474 {
475  return this->source;
476 }
477 
479 {
480  return this->u;
481 }
482 
484 {
485  return BotInfo::Find(this->GetName(), true);
486 }
487 
489 {
490  return this->s;
491 }
492 
493 IRCDMessage::IRCDMessage(Module *o, const Anope::string &n, unsigned p) : Service(o, "IRCDMessage", o->name + "/" + n.lower()), name(n), param_count(p)
494 {
495 }
496 
498 {
499  return this->param_count;
500 }
501 
Definition: bots.h:24
Anope::string source
Definition: protocol.h:250
bool CanSZLine
Definition: protocol.h:61
unsigned GetParamCount() const
Definition: protocol.cpp:497
Definition: servers.h:42
bool AmbiguousID
Definition: protocol.h:71
bool CanSNLine
Definition: protocol.h:55
virtual void SendAction(const MessageSource &source, const Anope::string &dest, const char *fmt,...)
Definition: protocol.cpp:231
bool CanSQLineChannel
Definition: protocol.h:59
virtual void SendInvite(const MessageSource &source, const Channel *c, User *u)
Definition: protocol.cpp:284
void SetMode(BotInfo *bi, UserMode *um, const Anope::string &param="")
Definition: users.cpp:573
virtual void SendSVSKillInternal(const MessageSource &, User *, const Anope::string &)
Definition: protocol.cpp:100
virtual void SendCTCP(const MessageSource &source, const Anope::string &dest, const char *fmt,...)
Definition: protocol.cpp:329
virtual void SendPrivmsg(const MessageSource &source, const Anope::string &dest, const char *fmt,...)
Definition: protocol.cpp:242
virtual void SendNotice(const MessageSource &source, const Anope::string &dest, const char *fmt,...)
Definition: protocol.cpp:221
virtual void SendPart(User *u, const Channel *chan, const char *fmt,...)
Definition: protocol.cpp:289
virtual void SendTopic(const MessageSource &, Channel *)
Definition: protocol.cpp:170
const Anope::string & GetSID() const
Definition: servers.cpp:203
virtual void SendCTCPInternal(const MessageSource &, const Anope::string &dest, const Anope::string &buf)
Definition: protocol.cpp:154
#define BUFSIZE
Definition: services.h:18
const Anope::string & GetProtocolName()
Definition: protocol.cpp:43
virtual void SendPartInternal(User *, const Channel *chan, const Anope::string &buf)
Definition: protocol.cpp:141
Definition: users.h:34
virtual void SendKick(const MessageSource &source, const Channel *chan, User *user, const char *fmt,...)
Definition: protocol.cpp:208
MessageSource(const Anope::string &)
Definition: protocol.cpp:444
virtual void SendQuitInternal(User *, const Anope::string &buf)
Definition: protocol.cpp:133
virtual void SendSVSKill(const MessageSource &source, User *user, const char *fmt,...)
Definition: protocol.cpp:175
Anope::string DefaultPseudoclientModes
Definition: protocol.h:47
User * u
Definition: protocol.h:251
virtual ~IRCDProto()
Definition: protocol.cpp:37
virtual bool IsIdentValid(const Anope::string &)
Definition: protocol.cpp:383
bool CanSetVHost
Definition: protocol.h:53
size_type find_first_of(const string &_str, size_type pos=0) const
Definition: anope.h:202
const Anope::string & GetSource() const
Definition: protocol.cpp:473
virtual void SendQuit(User *u, const char *fmt,...)
Definition: protocol.cpp:252
bool RequiresID
Definition: protocol.h:69
CoreExport Server * GetUplink()
Definition: servers.cpp:355
Anope::string name
Definition: channels.h:44
virtual bool IsHostValid(const Anope::string &)
Definition: protocol.cpp:401
CoreExport time_t CurTime
Definition: main.cpp:41
Anope::string topic
Definition: channels.h:59
virtual void SendNoticeInternal(const MessageSource &, const Anope::string &dest, const Anope::string &msg)
Definition: protocol.cpp:123
virtual Anope::string SID_Retrieve()
Definition: protocol.cpp:76
unsigned param_count
Definition: protocol.h:275
virtual bool IsExtbanValid(const Anope::string &)
Definition: protocol.h:238
Anope::string proto_name
Definition: protocol.h:23
virtual void SendForceNickChange(User *u, const Anope::string &newnick, time_t when)
Definition: protocol.cpp:324
bool CanSetVIdent
Definition: protocol.h:53
size_type length() const
Definition: anope.h:131
bool CanSQLine
Definition: protocol.h:57
Definition: Config.cs:26
bool CanSVSNick
Definition: protocol.h:49
bool CanCertFP
Definition: protocol.h:67
unsigned MaxModes
Definition: protocol.h:73
virtual void SendNickChange(User *u, const Anope::string &newnick)
Definition: protocol.cpp:319
virtual void SendKickInternal(const MessageSource &, const Channel *, User *, const Anope::string &)
Definition: protocol.cpp:115
Server * GetServer() const
Definition: protocol.cpp:488
static const size_type npos
Definition: anope.h:44
const Anope::string & GetUID() const
Definition: users.cpp:230
virtual void SendPing(const Anope::string &servname, const Anope::string &who)
Definition: protocol.cpp:262
bool CanSVSO
Definition: protocol.h:65
virtual bool IsNickValid(const Anope::string &)
Definition: protocol.cpp:349
IRCDMessage(Module *owner, const Anope::string &n, unsigned p=0)
Definition: protocol.cpp:493
BotInfo * GetBot() const
Definition: protocol.cpp:483
virtual void SendNumeric(int numeric, const Anope::string &dest, const char *fmt,...)
Definition: protocol.cpp:339
Server * s
Definition: protocol.h:252
CoreExport Anope::string NormalizeBuffer(const Anope::string &)
Definition: misc.cpp:664
User * GetUser() const
Definition: protocol.cpp:478
bool empty() const
Definition: anope.h:126
static Server * Find(const Anope::string &name, bool name_only=false)
Definition: servers.cpp:337
virtual void SendSquit(Server *, const Anope::string &message)
Definition: protocol.cpp:314
std::basic_string< char, ci_char_traits, std::allocator< char > > string
Definition: hashcomp.h:133
virtual void SendKill(const MessageSource &source, const Anope::string &target, const Anope::string &reason)
Definition: protocol.cpp:95
size_t HasMode(const Anope::string &name, const Anope::string &param="")
Definition: channels.cpp:201
bool CanSVSHold
Definition: protocol.h:63
Anope::string stringify(const T &x)
Definition: anope.h:710
virtual unsigned GetMaxListFor(Channel *c)
Definition: protocol.cpp:432
Anope::string nick
Definition: users.h:62
virtual void SendModeInternal(const MessageSource &, const Channel *, const Anope::string &)
Definition: protocol.cpp:105
virtual bool IsChannelValid(const Anope::string &)
Definition: protocol.cpp:372
static User * Find(const Anope::string &name, bool nick_only=false)
Definition: users.cpp:815
IRCDProto * IRCD
Definition: protocol.cpp:23
const Anope::string & GetName() const
Definition: servers.cpp:175
virtual void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf)
Definition: protocol.cpp:160
static char & nextID(char &c)
Definition: protocol.cpp:48
IRCDProto(Module *creator, const Anope::string &proto_name)
Definition: protocol.cpp:25
virtual Anope::string NormalizeMask(const Anope::string &mask)
Definition: protocol.cpp:437
Anope::string name
Definition: access.cpp:22
virtual void SendGlobops(const MessageSource &source, const char *fmt,...)
Definition: protocol.cpp:304
CoreExport Server * Me
Definition: servers.cpp:24
virtual Anope::string UID_Retrieve()
Definition: protocol.cpp:59
bool CanSVSJoin
Definition: protocol.h:51
virtual void SendMode(const MessageSource &source, const Channel *dest, const char *fmt,...)
Definition: protocol.cpp:188
Definition: modes.h:388
const Anope::string GetNUHMask() const
Definition: modes.cpp:822
unsigned MaxLine
Definition: protocol.h:75
size_type find(const string &_str, size_type pos=0) const
Definition: anope.h:192
virtual void SendGlobopsInternal(const MessageSource &, const Anope::string &buf)
Definition: protocol.cpp:149
static BotInfo * Find(const Anope::string &nick, bool nick_only=false)
Definition: bots.cpp:249
virtual void SendOper(User *u)
Definition: protocol.cpp:426
static struct special_chars special[]
virtual void SendPong(const Anope::string &servname, const Anope::string &who)
Definition: protocol.cpp:276
const Anope::string & GetName() const
Definition: protocol.cpp:463
virtual void SendPrivmsgInternal(const MessageSource &, const Anope::string &dest, const Anope::string &buf)
Definition: protocol.cpp:128