inspircd11.cpp

Go to the documentation of this file.
00001 /* inspircd 1.1 beta 6+ functions
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 
00014 #include "module.h"
00015 
00016 static bool has_servicesmod = false;
00017 static bool has_globopsmod = false;
00018 static bool has_chghostmod = false;
00019 static bool has_chgidentmod = false;
00020 static bool has_hidechansmod = false;
00021 
00022 class InspIRCdProto : public IRCDProto
00023 {
00024  public:
00025         InspIRCdProto(Module *creator) : IRCDProto(creator, "InspIRCd 1.1")
00026         {
00027                 DefaultPseudoclientModes = "+I";
00028                 CanSVSNick = true;
00029                 CanSVSJoin = true;
00030                 CanSetVHost = true;
00031                 CanSetVIdent = true;
00032                 CanSNLine = true;
00033                 CanSQLine = true;
00034                 CanSZLine = true;
00035                 CanSVSHold = true;
00036                 CanSVSO = true;
00037                 MaxModes = 20;
00038         }
00039  private:
00040 
00041         Anope::string current_pass;
00042 
00043         void inspircd_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent)
00044         {
00045                 if (has_chgidentmod)
00046                 {
00047                         if (nick.empty() || vIdent.empty())
00048                                 return;
00049                         UplinkSocket::Message(OperServ) << "CHGIDENT " << nick << " " << vIdent;
00050                 }
00051                 else
00052                         Log() << "CHGIDENT not loaded!";
00053         }
00054 
00055         void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost)
00056         {
00057                 if (has_chghostmod)
00058                 {
00059                         if (nick.empty() || vhost.empty())
00060                                 return;
00061                         UplinkSocket::Message(OperServ) << "CHGHOST " << nick << " " << vhost;
00062                 }
00063                 else
00064                         Log() << "CHGHOST not loaded!";
00065         }
00066 
00067         void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
00068         {
00069                 UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg;
00070         }
00071 
00072         void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override
00073         {
00074                 UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg;
00075         }
00076 
00077         void SendAkillDel(const XLine *x) anope_override
00078         {
00079                 if (x->IsRegex() || x->HasNickOrReal())
00080                         return;
00081 
00082                 /* ZLine if we can instead */
00083                 try
00084                 {
00085                         if (x->GetUser() == "*")
00086                         {
00087                                 sockaddrs(x->GetHost());
00088                                 IRCD->SendSZLineDel(x);
00089                                 return;
00090                         }
00091                 }
00092                 catch (const SocketException &) { }
00093 
00094                 UplinkSocket::Message(OperServ) << "GLINE " << x->mask;
00095         }
00096 
00097         void SendTopic(BotInfo *whosets, Channel *c) anope_override
00098         {
00099                 UplinkSocket::Message(whosets) << "FTOPIC " << c->name << " " << c->topic_time << " " << c->topic_ts <<" :" << c->topic;
00100         }
00101 
00102         void SendVhostDel(User *u) anope_override
00103         {
00104                 if (u->HasMode("CLOAK"))
00105                         inspircd_cmd_chghost(u->nick, u->chost);
00106                 else
00107                         inspircd_cmd_chghost(u->nick, u->host);
00108 
00109                 if (has_chgidentmod && u->GetIdent() != u->GetVIdent())
00110                         inspircd_cmd_chgident(u->nick, u->GetIdent());
00111         }
00112 
00113         void SendAkill(User *u, XLine *x) anope_override
00114         {
00115                 if (x->IsRegex() || x->HasNickOrReal())
00116                 {
00117                         if (!u)
00118                         {
00119                                 /* No user (this akill was just added), and contains nick and/or realname. Find users that match and ban them */
00120                                 for (user_map::const_iterator it = UserListByNick.begin(); it != UserListByNick.end(); ++it)
00121                                         if (x->manager->Check(it->second, x))
00122                                                 this->SendAkill(it->second, x);
00123                                 return;
00124                         }
00125 
00126                         const XLine *old = x;
00127 
00128                         if (old->manager->HasEntry("*@" + u->host))
00129                                 return;
00130 
00131                         /* We can't akill x as it has a nick and/or realname included, so create a new akill for *@host */
00132                         x = new XLine("*@" + u->host, old->by, old->expires, old->reason, old->id);
00133                         old->manager->AddXLine(x);
00134 
00135                         Log(OperServ, "akill") << "AKILL: Added an akill for " << x->mask << " because " << u->GetMask() << "#" << u->realname << " matches " << old->mask;
00136                 }
00137 
00138                 /* ZLine if we can instead */
00139                 try
00140                 {
00141                         if (x->GetUser() == "*")
00142                         {
00143                                 sockaddrs(x->GetHost());
00144                                 IRCD->SendSZLine(u, x);
00145                                 return;
00146                         }
00147                 }
00148                 catch (const SocketException &) { }
00149 
00150                 // Calculate the time left before this would expire, capping it at 2 days
00151                 time_t timeleft = x->expires - Anope::CurTime;
00152                 if (timeleft > 172800 || !x->expires)
00153                         timeleft = 172800;
00154                 UplinkSocket::Message(Me) << "ADDLINE G " << x->mask << " " << x->by << " " << Anope::CurTime << " " << timeleft << " :" << x->GetReason();
00155         }
00156 
00157         void SendSVSKillInternal(const BotInfo *source, User *user, const Anope::string &buf) anope_override
00158         {
00159                 if (source)
00160                 {
00161                         UplinkSocket::Message(source) << "KILL " << user->nick << " :" << buf;
00162                         user->KillInternal(source->nick, buf);
00163                 }
00164                 else
00165                 {
00166                         UplinkSocket::Message(Me) << "KILL " << user->nick << " :" << buf;
00167                         user->KillInternal(Me->GetName(), buf);
00168                 }
00169         }
00170 
00171         void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override
00172         {
00173                 UplinkSocket::Message() << "PUSH " << dest << " ::" << Me->GetName() << " " << numeric << " " << dest << " " << buf;
00174         }
00175 
00176         void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) anope_override
00177         {
00178                 if (source)
00179                         UplinkSocket::Message(source) << "FMODE " << dest->name << " " << dest->creation_time << " " << buf;
00180                 else
00181                         UplinkSocket::Message(Me) << "FMODE " << dest->name << " " << dest->creation_time << " " << buf;
00182         }
00183 
00184         void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) anope_override
00185         {
00186                 if (bi)
00187                         UplinkSocket::Message(bi) << "MODE " << u->nick << " " << buf;
00188                 else
00189                         UplinkSocket::Message(Me) << "MODE " << u->nick << " " << buf;
00190         }
00191 
00192         void SendClientIntroduction(const User *u) anope_override
00193         {
00194                 Anope::string modes = "+" + u->GetModes();
00195                 UplinkSocket::Message(Me) << "NICK " << u->timestamp << " " << u->nick << " " << u->host << " " << u->host << " " << u->GetIdent() << " " << modes << " 0.0.0.0 :" << u->realname;
00196                 UplinkSocket::Message(u) << "OPERTYPE Service";
00197         }
00198 
00199         /* SERVER services-dev.chatspike.net password 0 :Description here */
00200         void SendServer(const Server *server) anope_override
00201         {
00202                 UplinkSocket::Message(Me) << "SERVER " << server->GetName() << " " << current_pass << " " << server->GetHops() << " :" << server->GetDescription();
00203         }
00204 
00205         /* JOIN */
00206         void SendJoin(const User *user, Channel *c, const ChannelStatus *status) anope_override
00207         {
00208                 UplinkSocket::Message(user) << "JOIN " << c->name << " " << c->creation_time;
00209                 if (status)
00210                 {
00211                         /* First save the channel status incase uc->Status == status */
00212                         ChannelStatus cs = *status;
00213                         /* If the user is internally on the channel with flags, kill them so that
00214                          * the stacker will allow this.
00215                          */
00216                         ChanUserContainer *uc = c->FindUser(user);
00217                         if (uc != NULL)
00218                                 uc->status.modes.clear();
00219 
00220                         BotInfo *setter = BotInfo::Find(user->nick);
00221                         for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
00222                                 if (cs.modes.count(ModeManager::ChannelModes[i]->name))
00223                                         c->SetMode(setter, ModeManager::ChannelModes[i], user->GetUID(), false);
00224                 }
00225         }
00226 
00227         /* UNSQLINE */
00228         void SendSQLineDel(const XLine *x) anope_override
00229         {
00230                 UplinkSocket::Message(OperServ) << "QLINE " << x->mask;
00231         }
00232 
00233         /* SQLINE */
00234         void SendSQLine(User *, const XLine *x) anope_override
00235         {
00236                 // Calculate the time left before this would expire, capping it at 2 days
00237                 time_t timeleft = x->expires - Anope::CurTime;
00238                 if (timeleft > 172800 || !x->expires)
00239                         timeleft = 172800;
00240                 UplinkSocket::Message(Me) << "ADDLINE Q " << x->mask << " " << x->by << " " << Anope::CurTime << " " << timeleft << " :" << x->GetReason();
00241         }
00242 
00243         /* Functions that use serval cmd functions */
00244 
00245         void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) anope_override
00246         {
00247                 if (!vIdent.empty())
00248                         inspircd_cmd_chgident(u->nick, vIdent);
00249                 if (!vhost.empty())
00250                         inspircd_cmd_chghost(u->nick, vhost);
00251         }
00252 
00253         void SendConnect() anope_override
00254         {
00255                 current_pass = Config->Uplinks[Anope::CurrentUplink]->password;
00256                 SendServer(Me);
00257                 UplinkSocket::Message() << "BURST";
00258                 Module *enc = ModuleManager::FindFirstOf(ENCRYPTION);
00259                 UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << this->GetProtocolName() << " - (" << (enc ? enc->name : "none") << ") -- " << Anope::VersionBuildString();
00260         }
00261 
00262         /* SVSHOLD - set */
00263         void SendSVSHold(const Anope::string &nick) anope_override
00264         {
00265                 UplinkSocket::Message(OperServ) << "SVSHOLD " << nick << " " << Config->NSReleaseTimeout << "s :Being held for registered user";
00266         }
00267 
00268         /* SVSHOLD - release */
00269         void SendSVSHoldDel(const Anope::string &nick) anope_override
00270         {
00271                 UplinkSocket::Message(OperServ) << "SVSHOLD " << nick;
00272         }
00273 
00274         /* UNSZLINE */
00275         void SendSZLineDel(const XLine *x) anope_override
00276         {
00277                 UplinkSocket::Message(OperServ) << "ZLINE " << x->GetHost();
00278         }
00279 
00280         /* SZLINE */
00281         void SendSZLine(User *, const XLine *x) anope_override
00282         {
00283                 // Calculate the time left before this would expire, capping it at 2 days
00284                 time_t timeleft = x->expires - Anope::CurTime;
00285                 if (timeleft > 172800 || !x->expires)
00286                         timeleft = 172800;
00287                 UplinkSocket::Message(Me) << "ADDLINE Z " << x->GetHost() << " " << x->by << " " << Anope::CurTime << " " << timeleft << " :" << x->GetReason();
00288         }
00289 
00290         void SendSVSJoin(const BotInfo *source, const User *u, const Anope::string &chan, const Anope::string &) anope_override
00291         {
00292                 UplinkSocket::Message(source) << "SVSJOIN " << u->GetUID() << " " << chan;
00293         }
00294 
00295         void SendSVSPart(const BotInfo *source, const User *u, const Anope::string &chan, const Anope::string &param) anope_override
00296         {
00297                 if (!param.empty())
00298                         UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan << " :" << param;
00299                 else
00300                         UplinkSocket::Message(source) << "SVSPART " << u->GetUID() << " " << chan;
00301         }
00302 
00303         void SendBOB() anope_override
00304         {
00305                 UplinkSocket::Message() << "BURST " << Anope::CurTime;
00306         }
00307 
00308         void SendEOB() anope_override
00309         {
00310                 UplinkSocket::Message() << "ENDBURST";
00311         }
00312 
00313         void SendLogin(User *u) anope_override
00314         {
00315                 if (!u->Account())
00316                         return;
00317 
00318                 Anope::string svidbuf = stringify(u->timestamp);
00319                 u->Account()->Extend("authenticationtoken", new ExtensibleItemClass<Anope::string>(svidbuf));
00320         }
00321 
00322         void SendLogout(User *u) anope_override
00323         {
00324         }
00325 };
00326 
00327 class ChannelModeFlood : public ChannelModeParam
00328 {
00329  public:
00330         ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam("FLOOD", modeChar, minusNoArg) { }
00331 
00332         bool IsValid(const Anope::string &value) const anope_override
00333         {
00334                 try
00335                 {
00336                         Anope::string rest;
00337                         if (!value.empty() && value[0] != ':' && convertTo<int>(value[0] == '*' ? value.substr(1) : value, rest, false) > 0 && rest[0] == ':' && rest.length() > 1 && convertTo<int>(rest.substr(1), rest, false) > 0 && rest.empty())
00338                                 return true;
00339                 }
00340                 catch (const ConvertException &) { }
00341 
00342                 return false;
00343         }
00344 };
00345 
00346 struct IRCDMessageCapab : Message::Capab
00347 {
00348         IRCDMessageCapab(Module *creator) : Message::Capab(creator, "CAPAB") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00349 
00350         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00351         {
00352                 if (params[0].equals_cs("START"))
00353                 {
00354                         /* reset CAPAB */
00355                         has_servicesmod = false;
00356                         has_globopsmod = false;
00357                         has_chghostmod = false;
00358                         has_chgidentmod = false;
00359                         has_hidechansmod = false;
00360                         IRCD->CanSVSHold = false;
00361                 }
00362                 else if (params[0].equals_cs("MODULES") && params.size() > 1)
00363                 {
00364                         if (params[1].find("m_globops.so") != Anope::string::npos)
00365                                 has_globopsmod = true;
00366                         if (params[1].find("m_services.so") != Anope::string::npos)
00367                         has_servicesmod = true;
00368                         if (params[1].find("m_svshold.so") != Anope::string::npos)
00369                                 IRCD->CanSVSHold = true;
00370                         if (params[1].find("m_chghost.so") != Anope::string::npos)
00371                                 has_chghostmod = true;
00372                         if (params[1].find("m_chgident.so") != Anope::string::npos)
00373                                 has_chgidentmod = true;
00374                         if (params[1].find("m_hidechans.so") != Anope::string::npos)
00375                                 has_hidechansmod = true;
00376                 }
00377                 else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1)
00378                 {
00379                         spacesepstream ssep(params[1]);
00380                         Anope::string capab;
00381                         while (ssep.GetToken(capab))
00382                         {
00383                                 if (capab.find("CHANMODES") != Anope::string::npos)
00384                                 {
00385                                         Anope::string modes(capab.begin() + 10, capab.end());
00386                                         commasepstream sep(modes);
00387                                         Anope::string modebuf;
00388 
00389                                         sep.GetToken(modebuf);
00390                                         for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00391                                         {
00392                                                 switch (modebuf[t])
00393                                                 {
00394                                                         case 'b':
00395                                                                 ModeManager::AddChannelMode(new ChannelModeList("BAN", 'b'));
00396                                                                 continue;
00397                                                         case 'e':
00398                                                                 ModeManager::AddChannelMode(new ChannelModeList("EXCEPT", 'e'));
00399                                                                 continue;
00400                                                         case 'I':
00401                                                                 ModeManager::AddChannelMode(new ChannelModeList("INVITEOVERRIDE", 'I'));
00402                                                                 continue;
00403                                                         default:
00404                                                                 ModeManager::AddChannelMode(new ChannelModeList("END", modebuf[t]));
00405                                                 }
00406                                         }
00407 
00408                                         sep.GetToken(modebuf);
00409                                         for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00410                                         {
00411                                                 switch (modebuf[t])
00412                                                 {
00413                                                         case 'k':
00414                                                                 ModeManager::AddChannelMode(new ChannelModeKey('k'));
00415                                                                 continue;
00416                                                         default:
00417                                                                 ModeManager::AddChannelMode(new ChannelModeParam("END", modebuf[t]));
00418                                                 }
00419                                         }
00420 
00421                                         sep.GetToken(modebuf);
00422                                         for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00423                                         {
00424                                                 switch (modebuf[t])
00425                                                 {
00426                                                         case 'f':
00427                                                                 ModeManager::AddChannelMode(new ChannelModeFlood('f', false));
00428                                                                 continue;
00429                                                         case 'l':
00430                                                                 ModeManager::AddChannelMode(new ChannelModeParam("LIMIT", 'l', true));
00431                                                                 continue;
00432                                                         case 'L':
00433                                                                 ModeManager::AddChannelMode(new ChannelModeParam("REDIRECT", 'L', true));
00434                                                                 continue;
00435                                                         default:
00436                                                                 ModeManager::AddChannelMode(new ChannelModeParam("END", modebuf[t], true));
00437                                                 }
00438                                         }
00439 
00440                                         sep.GetToken(modebuf);
00441                                         for (size_t t = 0, end = modebuf.length(); t < end; ++t)
00442                                         {
00443                                                 switch (modebuf[t])
00444                                                 {
00445                                                         case 'i':
00446                                                                 ModeManager::AddChannelMode(new ChannelMode("INVITE", 'i'));
00447                                                                 continue;
00448                                                         case 'm':
00449                                                                 ModeManager::AddChannelMode(new ChannelMode("MODERATED", 'm'));
00450                                                                 continue;
00451                                                         case 'n':
00452                                                                 ModeManager::AddChannelMode(new ChannelMode("NOEXTERNAL", 'n'));
00453                                                                 continue;
00454                                                         case 'p':
00455                                                                 ModeManager::AddChannelMode(new ChannelMode("PRIVATE", 'p'));
00456                                                                 continue;
00457                                                         case 's':
00458                                                                 ModeManager::AddChannelMode(new ChannelMode("SECRET", 's'));
00459                                                                 continue;
00460                                                         case 't':
00461                                                                 ModeManager::AddChannelMode(new ChannelMode("TOPIC", 't'));
00462                                                                 continue;
00463                                                         case 'r':
00464                                                                 ModeManager::AddChannelMode(new ChannelModeRegistered('r'));
00465                                                                 continue;
00466                                                         case 'c':
00467                                                                 ModeManager::AddChannelMode(new ChannelMode("BLOCKCOLOR", 'c'));
00468                                                                 continue;
00469                                                         case 'u':
00470                                                                 ModeManager::AddChannelMode(new ChannelMode("AUDITORIUM", 'u'));
00471                                                                 continue;
00472                                                         case 'z':
00473                                                                 ModeManager::AddChannelMode(new ChannelMode("SSL", 'z'));
00474                                                                 continue;
00475                                                         case 'A':
00476                                                                 ModeManager::AddChannelMode(new ChannelMode("ALLINVITE", 'A'));
00477                                                                 continue;
00478                                                         case 'C':
00479                                                                 ModeManager::AddChannelMode(new ChannelMode("NOCTCP", 'C'));
00480                                                                 continue;
00481                                                         case 'G':
00482                                                                 ModeManager::AddChannelMode(new ChannelMode("FILTER", 'G'));
00483                                                                 continue;
00484                                                         case 'K':
00485                                                                 ModeManager::AddChannelMode(new ChannelMode("NOKNOCK", 'K'));
00486                                                                 continue;
00487                                                         case 'N':
00488                                                                 ModeManager::AddChannelMode(new ChannelMode("NONICK", 'N'));
00489                                                                 continue;
00490                                                         case 'O':
00491                                                                 ModeManager::AddChannelMode(new ChannelModeOper('O'));
00492                                                                 continue;
00493                                                         case 'Q':
00494                                                                 ModeManager::AddChannelMode(new ChannelMode("NOKICK", 'Q'));
00495                                                                 continue;
00496                                                         case 'R':
00497                                                                 ModeManager::AddChannelMode(new ChannelMode("REGISTEREDONLY", 'R'));
00498                                                                 continue;
00499                                                         case 'S':
00500                                                                 ModeManager::AddChannelMode(new ChannelMode("STRIPCOLOR", 'S'));
00501                                                                 continue;
00502                                                         case 'V':
00503                                                                 ModeManager::AddChannelMode(new ChannelMode("NOINVITE", 'V'));
00504                                                                 continue;
00505                                                         default:
00506                                                                 ModeManager::AddChannelMode(new ChannelMode("END", modebuf[t]));
00507                                                 }
00508                                         }
00509                                 }
00510                                 else if (capab.find("PREFIX=(") != Anope::string::npos)
00511                                 {
00512                                         Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')'));
00513                                         Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end());
00514                                         unsigned short level = modes.length() - 1;
00515 
00516                                         for (size_t t = 0, end = modes.length(); t < end; ++t)
00517                                         {
00518                                                 switch (modes[t])
00519                                                 {
00520                                                         case 'q':
00521                                                                 ModeManager::AddChannelMode(new ChannelModeStatus("OWNER", 'q', '~', level--));
00522                                                                 continue;
00523                                                         case 'a':
00524                                                                 ModeManager::AddChannelMode(new ChannelModeStatus("PROTECT", 'a', '&', level--));
00525                                                                 continue;
00526                                                         case 'o':
00527                                                                 ModeManager::AddChannelMode(new ChannelModeStatus("OP", 'o', '@', level--));
00528                                                                 continue;
00529                                                         case 'h':
00530                                                                 ModeManager::AddChannelMode(new ChannelModeStatus("HALFOP", 'h', '%', level--));
00531                                                                 continue;
00532                                                         case 'v':
00533                                                                 ModeManager::AddChannelMode(new ChannelModeStatus("VOICE", 'v', '+', level--));
00534                                                                 continue;
00535                                                         default:
00536                                                                 ModeManager::AddChannelMode(new ChannelModeStatus("END", modes[t], chars[t], level--));
00537                                                 }
00538                                         }
00539                                 }
00540                                 else if (capab.find("MAXMODES=") != Anope::string::npos)
00541                                 {
00542                                         Anope::string maxmodes(capab.begin() + 9, capab.end());
00543                                         IRCD->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3;
00544                                 }
00545                         }
00546                 }
00547                 else if (params[0].equals_cs("END"))
00548                 {
00549                         if (!has_globopsmod)
00550                         {
00551                                 UplinkSocket::Message() << "ERROR :m_globops is not loaded. This is required by Anope";
00552                                 Anope::QuitReason = "ERROR: Remote server does not have the m_globops module loaded, and this is required.";
00553                                 Anope::Quitting = true;
00554                                 return;
00555                         }
00556                         if (!has_servicesmod)
00557                         {
00558                                 UplinkSocket::Message() << "ERROR :m_services is not loaded. This is required by Anope";
00559                                 Anope::QuitReason = "ERROR: Remote server does not have the m_services module loaded, and this is required.";
00560                                 Anope::Quitting = true;
00561                                 return;
00562                         }
00563                         if (!has_hidechansmod)
00564                         {
00565                                 UplinkSocket::Message() << "ERROR :m_hidechans.so is not loaded. This is required by Anope";
00566                                 Anope::QuitReason = "ERROR: Remote server deos not have the m_hidechans module loaded, and this is required.";
00567                                 Anope::Quitting = true;
00568                                 return;
00569                         }
00570                         if (!IRCD->CanSVSHold)
00571                                 Log() << "SVSHOLD missing, Usage disabled until module is loaded.";
00572                         if (!has_chghostmod)
00573                                 Log() << "CHGHOST missing, Usage disabled until module is loaded.";
00574                         if (!has_chgidentmod)
00575                                 Log() << "CHGIDENT missing, Usage disabled until module is loaded.";
00576                 }
00577 
00578                 Message::Capab::Run(source, params);
00579         }
00580 };
00581 
00582 struct IRCDMessageChgIdent : IRCDMessage
00583 {
00584         IRCDMessageChgIdent(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 2) { }
00585 
00586         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00587         {
00588                 User *u = User::Find(params[0]);
00589                 if (!u)
00590                 {
00591                         Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0];
00592                         return;
00593                 }
00594 
00595                 u->SetIdent(params[1]);
00596         }
00597 };
00598 
00599 struct IRCDMessageChgName : IRCDMessage
00600 {
00601         IRCDMessageChgName(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00602 
00603         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00604         {
00605                 source.GetUser()->SetRealname(params[0]);
00606         }
00607 };
00608 
00609 struct IRCDMessageEndBurst : IRCDMessage
00610 {
00611         IRCDMessageEndBurst(Module *creator) : IRCDMessage(creator, "ENDBURST", 0) { }
00612 
00613         void Run(MessageSource &, const std::vector<Anope::string> &params) anope_override
00614         {
00615                 Me->GetLinks().front()->Sync(true);
00616         }
00617 };
00618 
00619 struct IRCDMessageFHost : IRCDMessage
00620 {
00621         IRCDMessageFHost(Module *creator, const Anope::string &n) : IRCDMessage(creator, n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00622 
00623         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00624         {
00625                 source.GetUser()->SetDisplayedHost(params[0]);
00626         }
00627 };
00628 
00629 struct IRCDMessageFJoin : IRCDMessage
00630 {
00631         IRCDMessageFJoin(Module *creator) : IRCDMessage(creator, "FJOIN", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00632 
00633         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00634         {
00635                 std::list<Message::Join::SJoinUser> users;
00636 
00637                 spacesepstream sep(params[params.size() - 1]);
00638                 Anope::string buf;
00639 
00640                 while (sep.GetToken(buf))
00641                 {
00642                         Message::Join::SJoinUser sju;
00643 
00644                         /* Loop through prefixes */
00645                         for (char ch; (ch = ModeManager::GetStatusChar(buf[0]));)
00646                         {
00647                                 ChannelMode *cm = ModeManager::FindChannelModeByChar(ch);
00648                                 buf.erase(buf.begin());
00649 
00650                                 if (!cm)
00651                                 {
00652                                         Log() << "Received unknown mode prefix " << ch << " in FJOIN string";
00653                                         continue;
00654                                 }
00655 
00656                                 sju.first.modes.insert(cm->name);
00657                         }
00658                         /* Erase the , */
00659                         buf.erase(buf.begin());
00660 
00661                         sju.second = User::Find(buf);
00662                         if (!sju.second)
00663                         {
00664                                 Log(LOG_DEBUG) << "FJOIN for nonexistant user " << buf << " on " << params[0];
00665                                 continue;
00666                         }
00667 
00668                 }
00669 
00670                 time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime;
00671                 Message::Join::SJoin(source, params[0], ts, "", users);
00672         }
00673 };
00674 
00675 struct IRCDMessageFMode : IRCDMessage
00676 {
00677         IRCDMessageFMode(Module *creator) : IRCDMessage(creator, "FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00678 
00679         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00680         {
00681                 /* :source FMODE #test 12345678 +nto foo */
00682 
00683                 Channel *c = Channel::Find(params[0]);
00684                 if (!c)
00685                         return;
00686                 time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0;
00687 
00688                 /* TS's are equal now, so we can proceed with parsing */
00689                 // For fun, modes sometimes get sent without a mode prefix
00690                 Anope::string modes = "+" + params[2];
00691                 for (unsigned n = 3; n < params.size(); ++n)
00692                         modes += " " + params[n];
00693 
00694                 c->SetModesInternal(source, modes, ts);
00695         }
00696 };
00697 
00698 struct IRCDMessageFTopic : IRCDMessage
00699 {
00700         IRCDMessageFTopic(Module *creator) : IRCDMessage(creator, "FTOPIC", 4) { }
00701 
00702         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00703         {
00704                 Channel *c = Channel::Find(params[0]);
00705                 if (c)
00706                         c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime);
00707         }
00708 };
00709 
00710 struct IRCDMessageIdle : IRCDMessage
00711 {
00712         IRCDMessageIdle(Module *creator) : IRCDMessage(creator, "IDLE", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00713 
00714         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00715         {
00716                 const BotInfo *bi = BotInfo::Find(params[0]);
00717                 UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << Anope::StartTime << " " << (bi ? Anope::CurTime - bi->lastmsg : 0);
00718         }
00719 };
00720 
00721 struct IRCDMessageMode : IRCDMessage
00722 {
00723         IRCDMessageMode(Module *creator) : IRCDMessage(creator, "MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00724 
00725         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00726         {
00727                 if (IRCD->IsChannelValid(params[0]))
00728                 {
00729                         Channel *c = Channel::Find(params[0]);
00730                         time_t ts;
00731 
00732                         try
00733                         {
00734                                 ts = convertTo<time_t>(params[2]);
00735                         }
00736                         catch (const ConvertException &)
00737                         {
00738                                 ts = 0;
00739                         }
00740 
00741                         if (c)
00742                                 c->SetModesInternal(source, params[1], ts);
00743                 }
00744                 else
00745                 {
00746                         User *u = User::Find(params[0]);
00747                         if (u)
00748                                 u->SetModesInternal("%s", params[1].c_str());
00749                 }
00750         }
00751 };
00752 
00753 struct IRCDMessageNick : IRCDMessage
00754 {
00755         ServiceReference<NickServService> NSService;
00756 
00757         IRCDMessageNick(Module *creator) : IRCDMessage(creator, "NICK", 1), NSService("NickServService", "NickServ") { SetFlag(IRCDMESSAGE_SOFT_LIMIT); }
00758 
00759         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00760         {
00761                 if (params.size() == 8 && source.GetServer())
00762                 {
00763                         time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : Anope::CurTime;
00764 
00765                         User *user = new User(params[1], params[4], params[2], params[3], params[6], source.GetServer(), params[7], ts, params[5]);
00766                         if (NSService)
00767                         {
00768                                 NickAlias *na = NickAlias::Find(user->nick);
00769                                 Anope::string *svidbuf = na ? na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("authenticationtoken") : NULL;
00770                                 if (na && svidbuf && *svidbuf == params[0])
00771                                         NSService->Login(user, na);
00772                         }
00773                 }
00774                 else if (params.size() == 1 && source.GetUser())
00775                         source.GetUser()->ChangeNick(params[0]);
00776         }
00777 };
00778 
00779 struct IRCDMessageOperType : IRCDMessage
00780 {
00781         IRCDMessageOperType(Module *creator) : IRCDMessage(creator, "OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); }
00782 
00783         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00784         {
00785                 /* opertype is equivalent to mode +o because servers
00786                    dont do this directly */
00787                 User *u = source.GetUser();
00788                 if (!u->HasMode("OPER"))
00789                         u->SetModesInternal("+o");
00790         }
00791 };
00792 
00793 struct IRCDMessageRSQuit : IRCDMessage
00794 {
00795         IRCDMessageRSQuit(Module *creator) : IRCDMessage(creator, "RSQUIT", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
00796 
00797         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00798         {
00799                 if (params.empty() || params.size() > 3)
00800                         return;
00801 
00802                 Server *s;
00803                 /* Horrible workaround to an insp bug (#) in how RSQUITs are sent - mark */
00804                 if (params.size() > 1 && Config->ServerName.equals_cs(params[0]))
00805                         s = Server::Find(params[1]);
00806                 else
00807                         s = Server::Find(params[0]);
00808 
00809                 source.GetServer()->Delete(source.GetServer()->GetName() + " " + (s ? s->GetName() : "<unknown>"));
00810         }
00811 };
00812 
00813 struct IRCDMessageServer : IRCDMessage
00814 {
00815         IRCDMessageServer(Module *creator) : IRCDMessage(creator, "SERVER", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); }
00816 
00817         void Run(MessageSource &source, const std::vector<Anope::string> &params) anope_override
00818         {
00819                 unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0;
00820                 new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[2]);
00821         }
00822 };
00823 
00824 class ProtoInspIRCd : public Module
00825 {
00826         InspIRCdProto ircd_proto;
00827 
00828         /* Core message handlers */
00829         Message::Away message_away;
00830         Message::Error message_error;
00831         Message::Join message_join;
00832         Message::Kick message_kick;
00833         Message::Kill message_kill;
00834         Message::MOTD message_motd;
00835         Message::Part message_part;
00836         Message::Ping message_ping;
00837         Message::Privmsg message_privmsg;
00838         Message::Quit message_quit;
00839         Message::SQuit message_squit;
00840         Message::Stats message_stats;
00841         Message::Time message_time;
00842         Message::Topic message_topic;
00843         Message::Version message_version;
00844 
00845         /* Our message handlers */
00846         IRCDMessageCapab message_capab;
00847         IRCDMessageChgIdent message_chgident, message_setident;
00848         IRCDMessageChgName message_chgname, message_setname;
00849         IRCDMessageEndBurst message_endburst;
00850         IRCDMessageFHost message_fhost, message_sethost;
00851         IRCDMessageFJoin message_fjoin;
00852         IRCDMessageFMode message_fmode;
00853         IRCDMessageFTopic message_ftopic;
00854         IRCDMessageIdle message_idle;
00855         IRCDMessageMode message_mode;
00856         IRCDMessageNick message_nick;
00857         IRCDMessageOperType message_opertype;
00858         IRCDMessageRSQuit message_rsquit;
00859         IRCDMessageServer message_server;
00860 
00861         void AddModes()
00862         {
00863                 ModeManager::AddUserMode(new UserMode("CALLERID", 'g'));
00864                 ModeManager::AddUserMode(new UserMode("HELPOP", 'h'));
00865                 ModeManager::AddUserMode(new UserMode("INVIS", 'i'));
00866                 ModeManager::AddUserMode(new UserMode("OPER", 'o'));
00867                 ModeManager::AddUserMode(new UserMode("REGISTERED", 'r'));
00868                 ModeManager::AddUserMode(new UserMode("WALLOPS", 'w'));
00869                 ModeManager::AddUserMode(new UserMode("CLOAK", 'x'));
00870         }
00871 
00872  public:
00873         ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL),
00874                 ircd_proto(this),
00875                 message_away(this), message_error(this), message_join(this), message_kick(this), message_kill(this),
00876                 message_motd(this), message_part(this), message_ping(this), message_privmsg(this), message_quit(this),
00877                 message_squit(this), message_stats(this), message_time(this), message_topic(this), message_version(this),
00878 
00879                 message_capab(this), message_chgident(this, "CHGIDENT"), message_setident(this, "SETIDENT"),
00880                 message_chgname(this, "CHGNAME"), message_setname(this, "SETNAME"), message_endburst(this),
00881                 message_fhost(this, "FHOST"), message_sethost(this, "SETHOST"), message_fjoin(this),
00882                 message_fmode(this), message_ftopic(this), message_idle(this), message_mode(this),
00883                 message_nick(this), message_opertype(this), message_rsquit(this), message_server(this)
00884         {
00885                 this->SetAuthor("Anope");
00886 
00887                 Servers::Capab.insert("NOQUIT");
00888 
00889                 this->AddModes();
00890 
00891                 ModuleManager::Attach(I_OnUserNickChange, this);
00892         }
00893 
00894         void OnUserNickChange(User *u, const Anope::string &) anope_override
00895         {
00896                 u->RemoveModeInternal(ModeManager::FindUserModeByName("REGISTERED"));
00897         }
00898 };
00899 
00900 MODULE_INIT(ProtoInspIRCd)