protocol.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church.
00010  *
00011  */
00012 
00013 #include "services.h"
00014 #include "modules.h"
00015 #include "protocol.h"
00016 #include "users.h"
00017 #include "servers.h"
00018 #include "config.h"
00019 #include "uplink.h"
00020 #include "bots.h"
00021 #include "channels.h"
00022 
00023 IRCDProto *IRCD = NULL;
00024 
00025 IRCDProto::IRCDProto(Module *creator, const Anope::string &p) : Service(creator, "IRCDProto", creator->name), proto_name(p)
00026 {
00027         DefaultPseudoclientModes = "+io";
00028         CanSVSNick = CanSVSJoin = CanSetVHost = CanSetVIdent = CanSNLine = CanSQLine = CanSQLineChannel
00029                 = CanSZLine = CanSVSHold = CanSVSO = CanCertFP = RequiresID = false;
00030         MaxModes = 3;
00031 
00032         if (IRCD == NULL)
00033                 IRCD = this;
00034 }
00035 
00036 IRCDProto::~IRCDProto()
00037 {
00038         if (IRCD == this)
00039                 IRCD = NULL;
00040 }
00041 
00042 const Anope::string &IRCDProto::GetProtocolName()
00043 {
00044         return this->proto_name;
00045 }
00046 
00047 void IRCDProto::SendSVSKillInternal(const BotInfo *source, User *user, const Anope::string &buf)
00048 {
00049         UplinkSocket::Message(source) << "KILL " << user->GetUID() << " :" << buf;
00050 }
00051 
00052 void IRCDProto::SendModeInternal(const BotInfo *bi, const Channel *dest, const Anope::string &buf)
00053 {
00054         UplinkSocket::Message(bi) << "MODE " << dest->name << " " << buf;
00055 }
00056 
00057 void IRCDProto::SendKickInternal(const BotInfo *bi, const Channel *c, const User *u, const Anope::string &r)
00058 {
00059         if (!r.empty())
00060                 UplinkSocket::Message(bi) << "KICK " << c->name << " " << u->GetUID() << " :" << r;
00061         else
00062                 UplinkSocket::Message(bi) << "KICK " << c->name << " " << u->GetUID();
00063 }
00064 
00065 void IRCDProto::SendMessageInternal(const BotInfo *bi, const Anope::string &dest, const Anope::string &buf)
00066 {
00067         if (Config->NSDefFlags.count("msg"))
00068                 SendPrivmsgInternal(bi, dest, buf);
00069         else
00070                 SendNoticeInternal(bi, dest, buf);
00071 }
00072 
00073 void IRCDProto::SendNoticeInternal(const BotInfo *bi, const Anope::string &dest, const Anope::string &msg)
00074 {
00075         UplinkSocket::Message(bi) << "NOTICE " << dest << " :" << msg;
00076 }
00077 
00078 void IRCDProto::SendPrivmsgInternal(const BotInfo *bi, const Anope::string &dest, const Anope::string &buf)
00079 {
00080         UplinkSocket::Message(bi) << "PRIVMSG " << dest << " :" << buf;
00081 }
00082 
00083 void IRCDProto::SendQuitInternal(const User *u, const Anope::string &buf)
00084 {
00085         if (!buf.empty())
00086                 UplinkSocket::Message(u) << "QUIT :" << buf;
00087         else
00088                 UplinkSocket::Message(u) << "QUIT";
00089 }
00090 
00091 void IRCDProto::SendPartInternal(const BotInfo *bi, const Channel *chan, const Anope::string &buf)
00092 {
00093         if (!buf.empty())
00094                 UplinkSocket::Message(bi) << "PART " << chan->name << " :" << buf;
00095         else
00096                 UplinkSocket::Message(bi) << "PART " << chan->name;
00097 }
00098 
00099 void IRCDProto::SendGlobopsInternal(const BotInfo *source, const Anope::string &buf)
00100 {
00101         if (source)
00102                 UplinkSocket::Message(source) << "GLOBOPS :" << buf;
00103         else
00104                 UplinkSocket::Message(Me) << "GLOBOPS :" << buf;
00105 }
00106 
00107 void IRCDProto::SendCTCPInternal(const BotInfo *bi, const Anope::string &dest, const Anope::string &buf)
00108 {
00109         Anope::string s = Anope::NormalizeBuffer(buf);
00110         this->SendNoticeInternal(bi, dest, "\1" + s + "\1");
00111 }
00112 
00113 void IRCDProto::SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf)
00114 {
00115         Anope::string n = stringify(numeric);
00116         if (numeric < 10)
00117                 n = "0" + n;
00118         if (numeric < 100)
00119                 n = "0" + n;
00120         UplinkSocket::Message(Me) << n << " " << dest << " " << buf;
00121 }
00122 
00123 void IRCDProto::SendTopic(BotInfo *bi, Channel *c)
00124 {
00125         UplinkSocket::Message(bi) << "TOPIC " << c->name << " :" << c->topic;
00126 }
00127 
00128 void IRCDProto::SendSVSKill(const BotInfo *source, User *user, const char *fmt, ...)
00129 {
00130         if (!user || !fmt)
00131                 return;
00132 
00133         va_list args;
00134         char buf[BUFSIZE] = "";
00135         va_start(args, fmt);
00136         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00137         va_end(args);
00138         SendSVSKillInternal(source, user, buf);
00139 }
00140 
00141 void IRCDProto::SendMode(const BotInfo *bi, const Channel *dest, const char *fmt, ...)
00142 {
00143         va_list args;
00144         char buf[BUFSIZE] = "";
00145         va_start(args, fmt);
00146         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00147         va_end(args);
00148         SendModeInternal(bi, dest, buf);
00149 }
00150 
00151 void IRCDProto::SendMode(const BotInfo *bi, const User *u, const char *fmt, ...)
00152 {
00153         va_list args;
00154         char buf[BUFSIZE] = "";
00155         va_start(args, fmt);
00156         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00157         va_end(args);
00158         SendModeInternal(bi, u, buf);
00159 }
00160 
00161 void IRCDProto::SendKick(const BotInfo *bi, const Channel *chan, const User *user, const char *fmt, ...)
00162 {
00163         if (!bi || !chan || !user)
00164                 return;
00165 
00166         va_list args;
00167         char buf[BUFSIZE] = "";
00168         va_start(args, fmt);
00169         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00170         va_end(args);
00171         SendKickInternal(bi, chan, user, buf);
00172 }
00173 
00174 void IRCDProto::SendMessage(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...)
00175 {
00176         va_list args;
00177         char buf[BUFSIZE] = "";
00178         va_start(args, fmt);
00179         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00180         va_end(args);
00181         SendMessageInternal(bi, dest, buf);
00182 }
00183 
00184 void IRCDProto::SendNotice(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...)
00185 {
00186         va_list args;
00187         char buf[BUFSIZE] = "";
00188         va_start(args, fmt);
00189         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00190         va_end(args);
00191         SendNoticeInternal(bi, dest, buf);
00192 }
00193 
00194 void IRCDProto::SendAction(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...)
00195 {
00196         va_list args;
00197         char buf[BUFSIZE] = "";
00198         va_start(args, fmt);
00199         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00200         va_end(args);
00201         Anope::string actionbuf = Anope::string("\1ACTION ") + buf + '\1';
00202         SendPrivmsgInternal(bi, dest, actionbuf);
00203 }
00204 
00205 void IRCDProto::SendPrivmsg(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...)
00206 {
00207         va_list args;
00208         char buf[BUFSIZE] = "";
00209         va_start(args, fmt);
00210         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00211         va_end(args);
00212         SendPrivmsgInternal(bi, dest, buf);
00213 }
00214 
00215 void IRCDProto::SendQuit(const User *u, const char *fmt, ...)
00216 {
00217         va_list args;
00218         char buf[BUFSIZE] = "";
00219         va_start(args, fmt);
00220         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00221         va_end(args);
00222         SendQuitInternal(u, buf);
00223 }
00224 
00225 void IRCDProto::SendPing(const Anope::string &servname, const Anope::string &who)
00226 {
00227         if (servname.empty())
00228                 UplinkSocket::Message(Me) << "PING " << who;
00229         else
00230                 UplinkSocket::Message(Me) << "PING " << servname << " " << who;
00231 }
00232 
00239 void IRCDProto::SendPong(const Anope::string &servname, const Anope::string &who)
00240 {
00241         if (servname.empty())
00242                 UplinkSocket::Message(Me) << "PONG " << who;
00243         else
00244                 UplinkSocket::Message(Me) << "PONG " << servname << " " << who;
00245 }
00246 
00247 void IRCDProto::SendInvite(const BotInfo *bi, const Channel *c, const User *u)
00248 {
00249         UplinkSocket::Message(bi) << "INVITE " << u->GetUID() << " " << c->name;
00250 }
00251 
00252 void IRCDProto::SendPart(const BotInfo *bi, const Channel *chan, const char *fmt, ...)
00253 {
00254         if (fmt)
00255         {
00256                 va_list args;
00257                 char buf[BUFSIZE] = "";
00258                 va_start(args, fmt);
00259                 vsnprintf(buf, BUFSIZE - 1, fmt, args);
00260                 va_end(args);
00261                 SendPartInternal(bi, chan, buf);
00262         }
00263         else
00264                 SendPartInternal(bi, chan, "");
00265 }
00266 
00267 void IRCDProto::SendGlobops(const BotInfo *source, const char *fmt, ...)
00268 {
00269         va_list args;
00270         char buf[BUFSIZE] = "";
00271         va_start(args, fmt);
00272         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00273         va_end(args);
00274         SendGlobopsInternal(source, buf);
00275 }
00276 
00277 void IRCDProto::SendSquit(Server *s, const Anope::string &message)
00278 {
00279         UplinkSocket::Message() << "SQUIT " << s->GetName() << " :" << message;
00280 }
00281 
00282 void IRCDProto::SendNickChange(const User *u, const Anope::string &newnick)
00283 {
00284         UplinkSocket::Message(u) << "NICK " << newnick << " " << Anope::CurTime;
00285 }
00286 
00287 void IRCDProto::SendForceNickChange(const User *u, const Anope::string &newnick, time_t when)
00288 {
00289         UplinkSocket::Message() << "SVSNICK " << u->nick << " " << newnick << " " << when;
00290 }
00291 
00292 void IRCDProto::SendCTCP(const BotInfo *bi, const Anope::string &dest, const char *fmt, ...)
00293 {
00294         va_list args;
00295         char buf[BUFSIZE] = "";
00296         va_start(args, fmt);
00297         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00298         va_end(args);
00299         SendCTCPInternal(bi, dest, buf);
00300 }
00301 
00302 void IRCDProto::SendNumeric(int numeric, const Anope::string &dest, const char *fmt, ...)
00303 {
00304         va_list args;
00305         char buf[BUFSIZE] = "";
00306         va_start(args, fmt);
00307         vsnprintf(buf, BUFSIZE - 1, fmt, args);
00308         va_end(args);
00309         SendNumericInternal(numeric, dest, buf);
00310 }
00311 
00312 bool IRCDProto::IsNickValid(const Anope::string &nick)
00313 {
00322          if (nick.empty())
00323                 return false;
00324         
00325         Anope::string special = "[]\\`_^{|}";
00326         
00327         for (unsigned i = 0; i < nick.length(); ++i)
00328                 if (!(nick[i] >= 'A' && nick[i] <= 'Z') && !(nick[i] >= 'a' && nick[i] <= 'z') && special.find(nick[i]) == Anope::string::npos
00329                 && (!i || (!(nick[i] >= '0' && nick[i] <= '9') && nick[i] != '-')))
00330                         return false;
00331         
00332         return true;
00333 }
00334 
00335 bool IRCDProto::IsChannelValid(const Anope::string &chan)
00336 {
00337         if (chan.empty() || chan[0] != '#' || chan.length() > Config->ChanLen)
00338                 return false;
00339 
00340         return true;
00341 }
00342 
00343 bool IRCDProto::IsIdentValid(const Anope::string &ident)
00344 {
00345         if (ident.empty() || ident.length() > Config->UserLen)
00346                 return false;
00347 
00348         for (unsigned i = 0; i < ident.length(); ++i)
00349         {
00350                 const char &c = ident[i];
00351                 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '-')
00352                         ;
00353                 else
00354                         return false;
00355         }
00356 
00357         return true;
00358 }
00359 
00360 bool IRCDProto::IsHostValid(const Anope::string &host)
00361 {
00362         if (host.empty() || host.length() > Config->HostLen)
00363                 return false;
00364 
00365         if (Config->VhostDisallowBE.find_first_of(host[0]) != Anope::string::npos)
00366                 return false;
00367         else if (Config->VhostDisallowBE.find_first_of(host[host.length() - 1]) != Anope::string::npos)
00368                 return false;
00369 
00370         int dots = 0;
00371         for (unsigned i = 0; i < host.length(); ++i)
00372         {
00373                 if (host[i] == '.')
00374                         ++dots;
00375                 if (Config->VhostChars.find_first_of(host[i]) == Anope::string::npos)
00376                         return false;
00377         }
00378 
00379         return Config->VhostUndotted || dots > 0;
00380 }
00381 
00382 void IRCDProto::SendOper(User *u)
00383 {
00384         SendNumericInternal(381, u->GetUID(), ":You are now an IRC operator (set by services)");
00385         u->SetMode(OperServ, "OPER");
00386 }
00387 
00388 MessageSource::MessageSource(const Anope::string &src) : source(src), u(NULL), s(NULL)
00389 {
00390         if (src.empty())
00391                 this->s = !Me->GetLinks().empty() ? Me->GetLinks().front() : NULL;
00392         else if (IRCD->RequiresID || src.find('.') != Anope::string::npos)
00393                 this->s = Server::Find(src);
00394         if (this->s == NULL)
00395                 this->u = User::Find(src);
00396 }
00397 
00398 MessageSource::MessageSource(User *_u) : source(_u ? _u->nick : ""), u(_u), s(NULL)
00399 {
00400 }
00401 
00402 MessageSource::MessageSource(Server *_s) : source(_s ? _s->GetName() : ""), u(NULL), s(_s)
00403 {
00404 }
00405 
00406 const Anope::string MessageSource::GetName()
00407 {
00408         if (this->s)
00409                 return this->s->GetName();
00410         else if (this->u)
00411                 return this->u->nick;
00412         else
00413                 return this->source;
00414 }
00415 
00416 const Anope::string &MessageSource::GetSource()
00417 {
00418         return this->source;
00419 }
00420 
00421 User *MessageSource::GetUser()
00422 {
00423         return this->u;
00424 }
00425 
00426 Server *MessageSource::GetServer()
00427 {
00428         return this->s;
00429 }
00430 
00431 IRCDMessage::IRCDMessage(Module *o, const Anope::string &n, unsigned p) : Service(o, "IRCDMessage", o->name + "/" + n.lower()), name(n), param_count(p)
00432 {
00433 }
00434 
00435 unsigned IRCDMessage::GetParamCount() const
00436 {
00437         return this->param_count;
00438 }
00439