diff options
| author | Adam <Adam@anope.org> | 2012-10-01 01:56:57 -0400 |
|---|---|---|
| committer | Adam <Adam@anope.org> | 2012-10-01 01:56:57 -0400 |
| commit | 89428a9d1032e3c2a6e397629a32862b3e58d708 (patch) | |
| tree | d507904b3fa1cc084f0f3e688c839bcdd47f79d7 /modules | |
| parent | b937d6310d9a7c0e2434200306b63d513cb2ae61 (diff) | |
Cleanup of all of the protocol modules, rewrote message handling system to be a bit more C++ ish
Diffstat (limited to 'modules')
28 files changed, 1905 insertions, 2053 deletions
diff --git a/modules/commands/bs_bot.cpp b/modules/commands/bs_bot.cpp index 0b45ee71c..de7fa1128 100644 --- a/modules/commands/bs_bot.cpp +++ b/modules/commands/bs_bot.cpp @@ -218,11 +218,8 @@ class CommandBSBot : public Command } /* The new nick is really different, so we remove the Q line for the old nick. */ - if (ircd->sqline) - { - XLine x(bi->nick); - ircdproto->SendSQLineDel(&x); - } + XLine x_del(bi->nick); + ircdproto->SendSQLineDel(&x_del); /* Add a Q line for the new nick */ XLine x(nick, "Reserved for services"); diff --git a/modules/commands/cs_seen.cpp b/modules/commands/cs_seen.cpp index 289988867..ce88efa44 100644 --- a/modules/commands/cs_seen.cpp +++ b/modules/commands/cs_seen.cpp @@ -376,9 +376,9 @@ class CSSeen : public Module UpdateUser(u, PART, u->nick, "", channel, msg); } - void OnUserKicked(Channel *c, User *target, const Anope::string &source, const Anope::string &msg) anope_override + void OnUserKicked(Channel *c, User *target, MessageSource &source, const Anope::string &msg) anope_override { - UpdateUser(target, KICK, target->nick, source, c->name, msg); + UpdateUser(target, KICK, target->nick, source.GetSource(), c->name, msg); } private: diff --git a/modules/commands/hs_on.cpp b/modules/commands/hs_on.cpp index 91fcaf10e..d02dd7dfe 100644 --- a/modules/commands/hs_on.cpp +++ b/modules/commands/hs_on.cpp @@ -27,6 +27,8 @@ class CommandHSOn : public Command User *u = source.GetUser(); if (!u) return; + else if (!ircdproto->CanSetVHost) + return; // HostServ wouldn't even be loaded at this point const NickAlias *na = findnick(u->nick); if (na && u->Account() == na->nc && na->HasVhost()) @@ -37,13 +39,9 @@ class CommandHSOn : public Command source.Reply(_("Your vhost of \002%s\002 is now activated."), na->GetVhostHost().c_str()); Log(LOG_COMMAND, source, this) << "to enable their vhost of " << (!na->GetVhostIdent().empty() ? na->GetVhostIdent() + "@" : "") << na->GetVhostHost(); ircdproto->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost()); - if (ircd->vhost) - u->vhost = na->GetVhostHost(); - if (ircd->vident) - { - if (!na->GetVhostIdent().empty()) - u->SetVIdent(na->GetVhostIdent()); - } + u->vhost = na->GetVhostHost(); + if (ircdproto->CanSetVIdent && !na->GetVhostIdent().empty()) + u->SetVIdent(na->GetVhostIdent()); u->UpdateHost(); } else diff --git a/modules/commands/hs_request.cpp b/modules/commands/hs_request.cpp index f4b710b7f..94b181f51 100644 --- a/modules/commands/hs_request.cpp +++ b/modules/commands/hs_request.cpp @@ -121,7 +121,7 @@ class CommandHSRequest : public Command source.Reply(HOST_SET_IDENTTOOLONG, Config->UserLen); return; } - else if (!ircd->vident) + else if (!ircdproto->CanSetVIdent) { source.Reply(HOST_NO_VIDENT); return; @@ -354,6 +354,9 @@ class HSRequest : public Module { this->SetAuthor("Anope"); + if (!ircdproto || !ircdproto->CanSetVHost) + throw ModuleException("Your IRCd does not support vhosts"); + Implementation i[] = { I_OnReload }; ModuleManager::Attach(i, this, sizeof(i) / sizeof(Implementation)); diff --git a/modules/commands/hs_set.cpp b/modules/commands/hs_set.cpp index b2509bcea..2189f2483 100644 --- a/modules/commands/hs_set.cpp +++ b/modules/commands/hs_set.cpp @@ -55,7 +55,7 @@ class CommandHSSet : public Command if (!user.empty()) { - if (!ircd->vident) + if (!ircdproto->CanSetVIdent) { source.Reply(HOST_NO_VIDENT); return; @@ -156,7 +156,7 @@ class CommandHSSetAll : public Command if (!user.empty()) { - if (!ircd->vident) + if (!ircdproto->CanSetVIdent) { source.Reply(HOST_NO_VIDENT); return; diff --git a/modules/commands/ns_cert.cpp b/modules/commands/ns_cert.cpp index da3cb2aa1..a06dd1a3a 100644 --- a/modules/commands/ns_cert.cpp +++ b/modules/commands/ns_cert.cpp @@ -225,7 +225,7 @@ class NSCert : public Module { this->SetAuthor("Anope"); - if (!ircd || !ircd->certfp) + if (!ircdproto || !ircdproto->CanCertFP) throw ModuleException("Your IRCd does not support ssl client certificates"); Implementation i[] = { I_OnFingerprint }; diff --git a/modules/commands/ns_info.cpp b/modules/commands/ns_info.cpp index b3b734a39..5daf2357e 100644 --- a/modules/commands/ns_info.cpp +++ b/modules/commands/ns_info.cpp @@ -102,7 +102,7 @@ class CommandNSInfo : public Command { if (na->HasVhost()) { - if (ircd->vident && !na->GetVhostIdent().empty()) + if (ircdproto->CanSetVIdent && !na->GetVhostIdent().empty()) info[_("VHost")] = na->GetVhostIdent() + "@" + na->GetVhostHost(); else info[_("VHost")] = na->GetVhostHost(); diff --git a/modules/commands/os_defcon.cpp b/modules/commands/os_defcon.cpp index 741eb9d43..1d684bc27 100644 --- a/modules/commands/os_defcon.cpp +++ b/modules/commands/os_defcon.cpp @@ -323,14 +323,6 @@ class OSDefcon : public Module Log() << "DefConChanModes must lock mode +l as well to lock mode +L"; } - - /* Some ircd we can't set NOKNOCK without INVITE */ - /* So check if we need there is a NOKNOCK MODE and that we need INVITEONLY */ - if (ircd->knock_needs_i && (cm = ModeManager::FindChannelModeByName(CMODE_NOKNOCK)) && DConfig.DefConModesOn.HasFlag(cm->Name) && !DConfig.DefConModesOn.HasFlag(CMODE_INVITE)) - { - DConfig.DefConModesOn.UnsetFlag(CMODE_NOKNOCK); - Log() << "DefConChanModes must lock mode +i as well to lock mode +K"; - } } public: @@ -437,7 +429,7 @@ class OSDefcon : public Module return EVENT_CONTINUE; } - EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override + EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelModeName Name, const Anope::string ¶m) anope_override { ChannelMode *cm = ModeManager::FindChannelModeByName(Name); @@ -451,7 +443,7 @@ class OSDefcon : public Module return EVENT_CONTINUE; } - EventReturn OnChannelModeUnset(Channel *c, User *setter, ChannelModeName Name, const Anope::string &) anope_override + EventReturn OnChannelModeUnset(Channel *c, MessageSource &, ChannelModeName Name, const Anope::string &) anope_override { ChannelMode *cm = ModeManager::FindChannelModeByName(Name); diff --git a/modules/commands/os_forbid.cpp b/modules/commands/os_forbid.cpp index 4862d5ea9..5f1d1d0ed 100644 --- a/modules/commands/os_forbid.cpp +++ b/modules/commands/os_forbid.cpp @@ -278,7 +278,7 @@ class OSForbid : public Module ForbidData *d = this->forbidService.FindForbid(c->name, FT_CHAN); if (bi != NULL && d != NULL) { - if (ircd->chansqline) + if (ircdproto->CanSQLineChannel) { XLine x(c->name, bi->nick, Anope::CurTime + Config->CSInhabit, d->reason); ircdproto->SendSQLine(NULL, &x); diff --git a/modules/commands/os_jupe.cpp b/modules/commands/os_jupe.cpp index 34c28a864..cfe917c13 100644 --- a/modules/commands/os_jupe.cpp +++ b/modules/commands/os_jupe.cpp @@ -37,7 +37,7 @@ class CommandOSJupe : public Command Anope::string rbuf = "Juped by " + source.GetNick() + (!reason.empty() ? ": " + reason : ""); if (server) ircdproto->SendSquit(server, rbuf); - Server *juped_server = new Server(Me, jserver, 1, rbuf, ircd->ts6 ? ts6_sid_retrieve() : "", SERVER_JUPED); + Server *juped_server = new Server(Me, jserver, 1, rbuf, ts6_sid_retrieve(), SERVER_JUPED); ircdproto->SendServer(juped_server); Log(LOG_ADMIN, source, this) << "on " << jserver << " (" << rbuf << ")"; diff --git a/modules/commands/os_oline.cpp b/modules/commands/os_oline.cpp index a468281e0..ccf053f7e 100644 --- a/modules/commands/os_oline.cpp +++ b/modules/commands/os_oline.cpp @@ -72,7 +72,7 @@ class OSOLine : public Module { this->SetAuthor("Anope"); - if (!ircd || !ircd->omode) + if (!ircdproto || !ircdproto->CanSVSO) throw ModuleException("Your IRCd does not support OMODE."); } diff --git a/modules/commands/os_stats.cpp b/modules/commands/os_stats.cpp index 7b593e421..dd5bf9ee0 100644 --- a/modules/commands/os_stats.cpp +++ b/modules/commands/os_stats.cpp @@ -84,7 +84,7 @@ class CommandOSStats : public Command else source.Reply(_("Default AKILL expiry time: \002No expiration\002")); } - if (ircd->snline && snlines) + if (ircdproto->CanSNLine && snlines) { /* SNLINEs */ source.Reply(_("Current number of SNLINEs: \002%d\002"), snlines->GetCount()); @@ -104,7 +104,7 @@ class CommandOSStats : public Command else source.Reply(_("Default SNLINE expiry time: \002No expiration\002")); } - if (ircd->sqline && sqlines) + if (ircdproto->CanSQLine && sqlines) { /* SQLINEs */ source.Reply(_("Current number of SQLINEs: \002%d\002"), sqlines->GetCount()); diff --git a/modules/commands/os_svsnick.cpp b/modules/commands/os_svsnick.cpp index aeaa38a59..4c6329acb 100644 --- a/modules/commands/os_svsnick.cpp +++ b/modules/commands/os_svsnick.cpp @@ -81,7 +81,7 @@ class OSSVSNick : public Module { this->SetAuthor("Anope"); - if (!ircd || !ircd->svsnick) + if (!ircdproto || !ircdproto->CanSVSNick) throw ModuleException("Your IRCd does not support SVSNICK"); } diff --git a/modules/commands/os_sxline.cpp b/modules/commands/os_sxline.cpp index 20e76a94d..8cd3d9f7a 100644 --- a/modules/commands/os_sxline.cpp +++ b/modules/commands/os_sxline.cpp @@ -250,7 +250,7 @@ class CommandOSSNLine : public CommandOSSXLineBase void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!this->xlm() ||! ircd->snline) + if (!this->xlm() || !ircdproto->CanSNLine) { source.Reply(_("Your IRCd does not support SNLINE")); return; @@ -384,18 +384,15 @@ class CommandOSSNLine : public CommandOSSXLineBase { this->xlm()->Send(source.GetUser(), x); - if (!ircd->sglineenforce) - { - Anope::string rreason = "G-Lined: " + reason; + Anope::string rreason = "G-Lined: " + reason; - for (Anope::insensitive_map<User *>::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();) - { - User *user = it->second; - ++it; + for (Anope::insensitive_map<User *>::const_iterator it = UserListByNick.begin(); it != UserListByNick.end();) + { + User *user = it->second; + ++it; - if (!user->HasMode(UMODE_OPER) && user->server != Me && Anope::Match(user->realname, x->Mask, false, true)) - user->Kill(Config->ServerName, rreason); - } + if (!user->HasMode(UMODE_OPER) && user->server != Me && Anope::Match(user->realname, x->Mask, false, true)) + user->Kill(Config->ServerName, rreason); } } @@ -474,7 +471,7 @@ class CommandOSSQLine : public CommandOSSXLineBase void OnAdd(CommandSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (!this->xlm() || !ircd->sqline) + if (!this->xlm() || !ircdproto->CanSQLine) { source.Reply(_("Your IRCd does not support SQLINE")); return; diff --git a/modules/extra/m_chanstats.cpp b/modules/extra/m_chanstats.cpp index ed9a5f444..9d9e9dbd8 100644 --- a/modules/extra/m_chanstats.cpp +++ b/modules/extra/m_chanstats.cpp @@ -365,8 +365,9 @@ class MChanstats : public Module else Log() << "Chanstats: no database connection to " << engine; } - void OnTopicUpdated(Channel *c, User *u, const Anope::string &topic) anope_override + void OnTopicUpdated(Channel *c, const Anope::string &user, const Anope::string &topic) anope_override { + User *u = finduser(user); if (!u || !u->Account() || !c->ci || !c->ci->HasFlag(CI_STATS)) return; query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);"; @@ -374,16 +375,17 @@ class MChanstats : public Module query.setValue("nick", GetDisplay(u)); this->RunQuery(query); } - EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override + EventReturn OnChannelModeSet(Channel *c, MessageSource &setter, ChannelModeName Name, const Anope::string ¶m) anope_override { - this->OnModeChange(c, setter); + this->OnModeChange(c, setter.GetUser()); return EVENT_CONTINUE; } - EventReturn OnChannelModeUnset(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override + EventReturn OnChannelModeUnset(Channel *c, MessageSource &setter, ChannelModeName Name, const Anope::string ¶m) anope_override { - this->OnModeChange(c, setter); + this->OnModeChange(c, setter.GetUser()); return EVENT_CONTINUE; } + private: void OnModeChange(Channel *c, User *u) { if (!u || !u->Account() || !c->ci || !c->ci->HasFlag(CI_STATS)) @@ -394,7 +396,8 @@ class MChanstats : public Module query.setValue("nick", GetDisplay(u)); this->RunQuery(query); } - void OnUserKicked(Channel *c, User *target, const Anope::string &source, const Anope::string &kickmsg) anope_override + public: + void OnUserKicked(Channel *c, User *target, MessageSource &source, const Anope::string &kickmsg) anope_override { if (!c->ci || !c->ci->HasFlag(CI_STATS)) return; @@ -406,7 +409,7 @@ class MChanstats : public Module query = "CALL " + prefix + "chanstats_proc_update(@channel@, @nick@, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);"; query.setValue("channel", c->name); - query.setValue("nick", GetDisplay(finduser(source))); + query.setValue("nick", GetDisplay(source.GetUser())); this->RunQuery(query); } void OnPrivmsg(User *u, Channel *c, Anope::string &msg) anope_override diff --git a/modules/extra/m_proxyscan.cpp b/modules/extra/m_proxyscan.cpp index f7fa3fdad..e6ee4008a 100644 --- a/modules/extra/m_proxyscan.cpp +++ b/modules/extra/m_proxyscan.cpp @@ -94,7 +94,7 @@ class ProxyConnect : public ConnectionSocket } else { - if (ircd->szline) + if (ircdproto->CanSZLine) ircdproto->SendSZLine(NULL, x); else ircdproto->SendAkill(NULL, x); diff --git a/modules/extra/webcpanel/webcpanel.cpp b/modules/extra/webcpanel/webcpanel.cpp index 4970845cd..bb65387f2 100644 --- a/modules/extra/webcpanel/webcpanel.cpp +++ b/modules/extra/webcpanel/webcpanel.cpp @@ -73,7 +73,7 @@ class ModuleWebCPanel : public Module s.subsections.push_back(ss); provider->RegisterPage(&this->nickserv_info); - if (ircd && ircd->certfp) + if (ircdproto && ircdproto->CanCertFP) { ss.name = "SSL Certificates"; ss.url = "/nickserv/cert"; diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 73955149d..8aeee39c8 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -13,34 +13,40 @@ #include "module.h" -IRCDVar myIrcd = { - "Bahamut 1.8.x", /* ircd name */ - "+", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 0, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 1, /* Chan SQlines */ - 1, /* Quit on Kill */ - 0, /* vidents */ - 1, /* svshold */ - 1, /* time stamp on mode */ - 0, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 0, /* ts6 */ - "$", /* TLD Prefix for Global */ - 6, /* Max number of modes we can send per line */ - 0 /* IRCd sends a SSL users certificate fingerprint */ -}; +class ChannelModeFlood : public ChannelModeParam +{ + public: + ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } + bool IsValid(const Anope::string &value) const anope_override + { + try + { + Anope::string rest; + 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()) + return true; + } + catch (const ConvertException &) { } + + return false; + } +}; class BahamutIRCdProto : public IRCDProto { + public: + BahamutIRCdProto() : IRCDProto("Bahamut 1.8.x") + { + DefaultPseudoclientModes = "+"; + CanSVSNick = true; + CanSNLine = true; + CanSQLine = true; + CanSQLineChannel = true; + CanSZLine = true; + CanSVSHold = true; + MaxModes = 60; + } + void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) anope_override { if (Capab.count("TSMODE") > 0) @@ -62,6 +68,16 @@ class BahamutIRCdProto : public IRCDProto UplinkSocket::Message(Me) << "SVSMODE " << u->nick << " " << u->timestamp << " " << buf; } + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } + /* SVSHOLD - set */ void SendSVSHold(const Anope::string &nick) anope_override { @@ -290,46 +306,82 @@ class BahamutIRCdProto : public IRCDProto } }; -class BahamutIRCdMessage : public IRCdMessage +struct IRCDMessageBurst : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() > 2 && (params[0][0] == '#' || params[0][0] == '&')) - do_cmode(source, params[0], params[2], params[1]); - else if (params.size() > 1) - do_umode(params[0], params[1]); + IRCDMessageBurst() : IRCDMessage("BURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* If we found a server with the given source, that one just + * finished bursting. If there was no source, then our uplink + * server finished bursting. -GD + */ + Server *s = source.GetServer(); + if (!s) + s = Me->GetLinks().front(); + if (s) + s->Sync(true); return true; } +}; - /* - ** NICK - new - ** source = NULL - ** parv[0] = nickname - ** parv[1] = hopcount - ** parv[2] = timestamp - ** parv[3] = modes - ** parv[4] = username - ** parv[5] = hostname - ** parv[6] = server - ** parv[7] = servicestamp - ** parv[8] = IP - ** parv[9] = info - ** NICK - change - ** source = oldnick - ** parv[0] = new nickname - ** parv[1] = hopcount - */ - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() != 2) +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode(const Anope::string &n) : IRCDMessage(n, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (params.size() > 2 && ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts = Anope::CurTime; + try + { + ts = convertTo<time_t>(params[1]); + } + catch (const ConvertException &) { } + + if (c) + c->SetModesInternal(source, params[2], ts); + } + else { - /* Currently bahamut has no ipv6 support */ - sockaddrs ip; - ip.ntop(AF_INET, params[8].c_str()); + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + + return true; + } +}; + +/* + ** NICK - new + ** source = NULL + ** parv[0] = nickname + ** parv[1] = hopcount + ** parv[2] = timestamp + ** parv[3] = modes + ** parv[4] = username + ** parv[5] = hostname + ** parv[6] = server + ** parv[7] = servicestamp + ** parv[8] = IP + ** parv[9] = info + ** NICK - change + ** source = oldnick + ** parv[0] = new nickname + ** parv[1] = hopcount + */ +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - User *user = do_nick(source, params[0], params[4], params[5], params[6], params[9], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, ip.addr(), "", "", params[3]); + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (params.size() == 10) + { + User *user = new User(params[0], params[4], params[5], "", params[8], source.GetServer(), params[9], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[3]); if (user && nickserv) { const NickAlias *na; @@ -345,35 +397,29 @@ class BahamutIRCdMessage : public IRCdMessage } } else - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); + source.GetUser()->ChangeNick(params[0]); return true; } +}; - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); - return true; - } +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - bool OnTopic(const Anope::string &, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - + unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[2]); return true; } +}; - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +struct IRCDMessageSJoin : IRCDMessage +{ + IRCDMessageSJoin() : IRCDMessage("SJOIN", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[1]); time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; @@ -403,7 +449,7 @@ class BahamutIRCdMessage : public IRCdMessage modes += " " + params[i]; if (!modes.empty()) modes.erase(modes.begin()); - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } /* For some reason, bahamut will send a SJOIN from the user joining a channel @@ -411,28 +457,24 @@ class BahamutIRCdMessage : public IRCdMessage */ if (!c->HasFlag(CH_SYNCING) && params.size() == 2) { - User *u = finduser(source); - if (!u) - Log(LOG_DEBUG) << "SJOIN for nonexistant user " << source << " on " << c->name; - else - { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); + User *u = source.GetUser(); - /* Add the user to the channel */ - c->JoinUser(u); + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1, true); + /* Add the user to the channel */ + c->JoinUser(u); - /* Check to see if modules want the user to join, if they do - * check to see if they are allowed to join (CheckKick will kick/ban them) - * Don't trigger OnJoinChannel event then as the user will be destroyed - */ - if (MOD_RESULT == EVENT_STOP && (!c->ci || !c->ci->CheckKick(u))) - { - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); - } + /* Now set whatever modes this user is allowed to have on the channel */ + chan_set_correct_modes(u, c, 1, true); + + /* Check to see if modules want the user to join, if they do + * check to see if they are allowed to join (CheckKick will kick/ban them) + * Don't trigger OnJoinChannel event then as the user will be destroyed + */ + if (MOD_RESULT == EVENT_STOP && (!c->ci || !c->ci->CheckKick(u))) + { + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); } } else @@ -476,7 +518,7 @@ class BahamutIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -504,53 +546,48 @@ class BahamutIRCdMessage : public IRCdMessage } }; -bool event_burst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - - if (params.empty()) - { - /* for future use - start burst */ - } - else - { - /* If we found a server with the given source, that one just - * finished bursting. If there was no source, then our uplink - * server finished bursting. -GD - */ - if (!s) - s = Me->GetLinks().front(); - if (s) - s->Sync(true); - } - return true; -} - -class ChannelModeFlood : public ChannelModeParam +struct IRCDMessageTopic : IRCDMessage { - public: - ChannelModeFlood(char modeChar, bool minusNoArg) : ChannelModeParam(CMODE_FLOOD, modeChar, minusNoArg) { } + IRCDMessageTopic() : IRCDMessage("TOPIC", 4) { } - bool IsValid(const Anope::string &value) const anope_override + bool Run(MessageSource &, const std::vector<Anope::string> ¶ms) anope_override { - try - { - Anope::string rest; - 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()) - return true; - } - catch (const ConvertException &) { } - - return false; + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); + return true; } }; class ProtoBahamut : public Module { - Message message_svsmode, message_burst; - BahamutIRCdProto ircd_proto; - BahamutIRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + CoreIRCDMessageWhois core_message_whois; + + /* Our message handlers */ + IRCDMessageBurst message_burst; + IRCDMessageMode message_mode, message_svsmode; + IRCDMessageNick message_nick; + IRCDMessageServer message_server; + IRCDMessageSJoin message_sjoin; + IRCDMessageTopic message_topic; void AddModes() { @@ -591,26 +628,15 @@ class ProtoBahamut : public Module public: ProtoBahamut(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_svsmode("SVSMODE", OnMode), message_burst("BURST", event_burst) + message_mode("MODE"), message_svsmode("SVSMODE") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - this->AddModes(); ModuleManager::Attach(I_OnUserNickChange, this); } - ~ProtoBahamut() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - void OnUserNickChange(User *u, const Anope::string &) anope_override { u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED)); diff --git a/modules/protocol/inspircd-ts6.h b/modules/protocol/inspircd-ts6.h index 0ce5be921..f0af01cc9 100644 --- a/modules/protocol/inspircd-ts6.h +++ b/modules/protocol/inspircd-ts6.h @@ -47,7 +47,30 @@ class InspIRCdTS6Proto : public IRCDProto UplinkSocket::Message(Me) << "CHGHOST " << nick << " " << vhost; } - public: + protected: + InspIRCdTS6Proto(const Anope::string &name) : IRCDProto(name) + { + DefaultPseudoclientModes = "+I"; + CanSVSNick = true; + CanSetVHost = true; + CanSetVIdent = true; + CanSQLine = true; + CanSZLine = true; + CanSVSHold = true; + CanCertFP = true; + RequiresID = true; + MaxModes = 20; + } + + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } void SendAkillDel(const XLine *x) anope_override { @@ -225,7 +248,7 @@ class InspIRCdTS6Proto : public IRCDProto SendServer(Me); UplinkSocket::Message(Me) << "BURST"; Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Config->ServerName << " :" << ircd->name << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); + UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Config->ServerName << " :" << ircdproto->GetProtocolName() << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); } /* SVSHOLD - set */ @@ -319,83 +342,37 @@ class InspIRCdTS6Proto : public IRCDProto } }; -class InspircdIRCdMessage : public IRCdMessage +struct IRCDMessageEndburst : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[2], params[1]); - else - { - /* InspIRCd lets opers change another - users modes, we have to kludge this - as it slightly breaks RFC1459 - */ - User *u = finduser(source); - // This can happen with server-origin modes. - if (!u) - u = finduser(params[0]); - // if it's still null, drop it like fire. - // most likely situation was that server introduced a nick which we subsequently akilled - if (!u) - return true; + IRCDMessageEndburst() : IRCDMessage("ENDBURST", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - do_umode(u->nick, params[1]); - } - - return true; - } - - virtual bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override = 0; - - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - do_nick(source, params[0], "", "", "", "", 0, "", "", "", ""); - return true; - } - - bool OnPrivmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - /* Ignore privmsgs from the server, which can happen. */ - if (Server::Find(source) != NULL) - return true; + Server *s = source.GetServer(); - return IRCdMessage::OnPrivmsg(source, params); - } + Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - /* - * [Nov 04 00:08:46.308435 2009] debug: Received: SERVER irc.inspircd.com pass 0 964 :Testnet Central! - * 0: name - * 1: pass - * 2: hops - * 3: numeric - * 4: desc - */ - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - do_server(source, params[0], Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0, params[4], params[3]); + s->Sync(true); return true; } +}; - bool OnTopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - Channel *c = findchan(params[0]); - - if (!c) - { - Log() << "TOPIC " << params[1] << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : ""), Anope::CurTime); +struct IRCDMessageFHost : IRCDMessage +{ + IRCDMessageFHost(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->SetDisplayedHost(params[0]); return true; } +}; - virtual bool OnCapab(const Anope::string &, const std::vector<Anope::string> &) anope_override = 0; +struct IRCDMessageFJoin : IRCDMessage +{ + IRCDMessageFJoin() : IRCDMessage("FJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[0]); time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; @@ -425,7 +402,7 @@ class InspircdIRCdMessage : public IRCdMessage if (!modes.empty()) modes.erase(modes.begin()); /* Set the modes internally */ - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } spacesepstream sep(params[params.size() - 1]); @@ -468,7 +445,7 @@ class InspircdIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -495,33 +472,268 @@ class InspircdIRCdMessage : public IRCdMessage } }; -bool event_idle(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageFMode : IRCDMessage +{ + IRCDMessageFMode() : IRCDMessage("FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* :source FMODE #test 12345678 +nto foo */ + + Anope::string modes = params[2]; + for (unsigned n = 3; n < params.size(); ++n) + modes += " " + params[n]; + + Channel *c = findchan(params[0]); + time_t ts; + + try + { + ts = convertTo<time_t>(params[1]); + } + catch (const ConvertException &) + { + ts = Anope::CurTime; + } + + if (c) + c->SetModesInternal(source, modes, ts); + + return true; + } +}; + +struct IRCDMessageFTopic : IRCDMessage +{ + IRCDMessageFTopic() : IRCDMessage("FTOPIC", 4) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* :source FTOPIC channel ts setby :topic */ + + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); + + return true; + } +}; + +struct IRCDMessageIdle : IRCDMessage +{ + IRCDMessageIdle() : IRCDMessage("IDLE", 1) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + const BotInfo *bi = findbot(params[0]); + if (bi) + UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << start_time << " " << (Anope::CurTime - bi->lastmsg); + return true; + } +}; + +/* + * source = numeric of the sending server + * params[0] = uuid + * params[1] = metadata name + * params[2] = data + */ +struct IRCDMessageMetadata : IRCDMessage +{ + IRCDMessageMetadata() : IRCDMessage("METADATA", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (params[1].equals_cs("accountname")) + { + User *u = finduser(params[0]); + NickCore *nc = findcore(params[2]); + if (u && nc) + { + u->Login(nc); + + const NickAlias *user_na = findnick(u->nick); + if (!Config->NoNicknameOwnership && nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + } + + /* + * possible incoming ssl_cert messages: + * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...> + * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0) + */ + else if (params[1].equals_cs("ssl_cert")) + { + User *u = finduser(params[0]); + if (!u) + return true; + std::string data = params[2].c_str(); + size_t pos1 = data.find(' ') + 1; + size_t pos2 = data.find(' ', pos1); + if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes. + { + u->fingerprint = data.substr(pos1, pos2 - pos1); + FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); + } + } + return true; + } +}; + +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode() : IRCDMessage("MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts; + + try + { + ts = convertTo<time_t>(params[1]); + } + catch (const ConvertException &) + { + ts = Anope::CurTime; + } + + if (c) + c->SetModesInternal(source, params[2], ts); + } + else + { + /* InspIRCd lets opers change another + users modes, we have to kludge this + as it slightly breaks RFC1459 + */ + User *u = source.GetUser(); + // This can happen with server-origin modes. + if (!u) + u = finduser(params[0]); + // if it's still null, drop it like fire. + // most likely situation was that server introduced a nick which we subsequently akilled + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + + return true; + } +}; + +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->ChangeNick(params[0]); + return true; + } +}; + +struct IRCDMessageOperType : IRCDMessage +{ + IRCDMessageOperType() : IRCDMessage("OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* opertype is equivalent to mode +o because servers + dont do this directly */ + User *u = source.GetUser(); + if (!u->HasMode(UMODE_OPER)) + u->SetModesInternal("+o"); + + return true; + } +}; + +struct IRCDMessageRSQuit : IRCDMessage { - const BotInfo *bi = findbot(params[0]); - if (bi) - UplinkSocket::Message(bi) << "IDLE " << source << " " << start_time << " " << (Anope::CurTime - bi->lastmsg); - return true; -} + IRCDMessageRSQuit() : IRCDMessage("RSQUIT", 1) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + Server *s = Server::Find(params[0]); + if (!s) + return true; + + /* On InspIRCd we must send a SQUIT when we recieve RSQUIT for a server we have juped */ + if (s->HasFlag(SERVER_JUPED)) + UplinkSocket::Message(Me) << "SQUIT " << s->GetSID() << " :" << (params.size() > 1 ? params[1].c_str() : ""); + + FOREACH_MOD(I_OnServerQuit, OnServerQuit(s)); + + s->Delete(s->GetName() + " " + s->GetUplink()->GetName()); + + return true; + } +}; -bool event_time(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageServer : IRCDMessage { - if (params.size() < 2) + IRCDMessageServer() : IRCDMessage("SERVER", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + /* + * [Nov 04 00:08:46.308435 2009] debug: Received: SERVER irc.inspircd.com pass 0 964 :Testnet Central! + * 0: name + * 1: pass + * 2: hops + * 3: numeric + * 4: desc + */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + unsigned int hops = Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[4], params[3]); return true; + } +}; - UplinkSocket::Message(Me) << "TIME " << source << " " << params[1] << " " << Anope::CurTime; - return true; -} +struct IRCDMessageTime : IRCDMessage +{ + IRCDMessageTime() : IRCDMessage("TIME", 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + UplinkSocket::Message(Me) << "TIME " << source.GetSource() << " " << params[1] << " " << Anope::CurTime; + return true; + } +}; -bool event_rsquit(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageUID : IRCDMessage { - /* On InspIRCd we must send a SQUIT when we recieve RSQUIT for a server we have juped */ - Server *s = Server::Find(params[0]); - if (s && s->HasFlag(SERVER_JUPED)) - UplinkSocket::Message(Me) << "SQUIT " << s->GetSID() << " :" << (params.size() > 1 ? params[1].c_str() : ""); + IRCDMessageUID() : IRCDMessage("UID", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + /* + * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell <w00t@inspircd.org> + * 0: uid + * 1: ts + * 2: nick + * 3: host + * 4: dhost + * 5: ident + * 6: ip + * 7: signon + * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname! + * last: realname + */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + time_t ts = convertTo<time_t>(params[1]); - ircdmessage->OnSQuit(source, params); + Anope::string modes = params[8]; + for (unsigned i = 9; i < params.size() - 1; ++i) + modes += " " + params[i]; - return true; -} + User *u = new User(params[2], params[5], params[3], params[4], params[6], source.GetServer(), params[params.size() - 1], ts, modes, params[0]); + if (u->server->IsSynced() && nickserv) + nickserv->Validate(u); + return true; + } +}; diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index 7470d61aa..1eba8321f 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -13,31 +13,6 @@ #include "module.h" -IRCDVar myIrcd = { - "InspIRCd 1.1", /* ircd name */ - "+I", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 1, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 0, /* time stamp on mode */ - 1, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 0, /* ts6 */ - "$", /* TLD Prefix for Global */ - 20, /* Max number of modes we can send per line */ - 0 /* IRCd sends a SSL users certificate fingerprint */ -}; - static bool has_servicesmod = false; static bool has_globopsmod = false; static bool has_svsholdmod = false; @@ -45,40 +20,60 @@ static bool has_chghostmod = false; static bool has_chgidentmod = false; static bool has_hidechansmod = false; -/* CHGHOST */ -void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) +class InspIRCdProto : public IRCDProto { - const BotInfo *bi = findbot(Config->OperServ); - if (has_chghostmod) + public: + InspIRCdProto() : IRCDProto("InspIRCd 1.1") { - if (nick.empty() || vhost.empty()) - return; - UplinkSocket::Message(bi) << "CHGHOST " << nick << " " << vhost; + DefaultPseudoclientModes = "+I"; + CanSVSNick = true; + CanSetVHost = true; + CanSetVIdent = true; + CanSNLine = true; + CanSQLine = true; + CanSZLine = true; + CanSVSHold = true; + CanSVSO = true; + MaxModes = 20; } - else + private: + + Anope::string current_pass; + + void inspircd_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent) { - if (bi) - ircdproto->SendGlobops(bi, "CHGHOST not loaded!"); + if (has_chgidentmod) + { + if (nick.empty() || vIdent.empty()) + return; + UplinkSocket::Message(findbot(Config->OperServ)) << "CHGIDENT " << nick << " " << vIdent; + } + else + Log() << "CHGIDENT not loaded!"; } -} -bool event_idle(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - const BotInfo *bi = findbot(params[0]); - UplinkSocket::Message(bi) << "IDLE " << source << " " << start_time << " " << (bi ? Anope::CurTime - bi->lastmsg : 0); - return true; -} + void inspircd_cmd_chghost(const Anope::string &nick, const Anope::string &vhost) + { + if (has_chghostmod) + { + if (nick.empty() || vhost.empty()) + return; + UplinkSocket::Message(findbot(Config->OperServ)) << "CHGHOST " << nick << " " << vhost; + } + else + Log() << "CHGHOST not loaded!"; + } -static Anope::string currentpass; + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } -/* PASS */ -void inspircd_cmd_pass(const Anope::string &pass) -{ - currentpass = pass; -} + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } -class InspIRCdProto : public IRCDProto -{ void SendAkillDel(const XLine *x) anope_override { if (x->IsRegex() || x->HasNickOrReal()) @@ -159,12 +154,18 @@ class InspIRCdProto : public IRCDProto UplinkSocket::Message(Me) << "ADDLINE G " << x->Mask << " " << x->By << " " << Anope::CurTime << " " << timeleft << " :" << x->GetReason(); } - void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) anope_override + void SendSVSKillInternal(const BotInfo *source, User *user, const Anope::string &buf) anope_override { if (source) + { UplinkSocket::Message(source) << "KILL " << user->nick << " :" << buf; + user->KillInternal(source->nick, buf); + } else + { UplinkSocket::Message(Me) << "KILL " << user->nick << " :" << buf; + user->KillInternal(Me->GetName(), buf); + } } void SendNumericInternal(int numeric, const Anope::string &dest, const Anope::string &buf) anope_override @@ -206,7 +207,7 @@ class InspIRCdProto : public IRCDProto /* SERVER services-dev.chatspike.net password 0 :Description here */ void SendServer(const Server *server) anope_override { - UplinkSocket::Message(Me) << "SERVER " << server->GetName() << " " << currentpass << " " << server->GetHops() << " :" << server->GetDescription(); + UplinkSocket::Message(Me) << "SERVER " << server->GetName() << " " << current_pass << " " << server->GetHops() << " :" << server->GetDescription(); } /* JOIN */ @@ -259,24 +260,11 @@ class InspIRCdProto : public IRCDProto void SendConnect() anope_override { - inspircd_cmd_pass(Config->Uplinks[CurrentUplink]->password); + current_pass = Config->Uplinks[CurrentUplink]->password; SendServer(Me); UplinkSocket::Message() << "BURST"; Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << ircd->name << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); - } - - /* CHGIDENT */ - void inspircd_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent) - { - if (has_chgidentmod) - { - if (nick.empty() || vIdent.empty()) - return; - UplinkSocket::Message(findbot(Config->OperServ)) << "CHGIDENT " << nick << " " << vIdent; - } - else - Log() << "CHGIDENT not loaded!"; + UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << this->GetProtocolName() << " - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); } /* SVSHOLD - set */ @@ -355,73 +343,11 @@ class ChannelModeFlood : public ChannelModeParam } }; -class InspircdIRCdMessage : public IRCdMessage +struct IRCDMessageCapab : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() < 2) - return true; - - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[1], params[2]); - else - do_umode(params[0], params[1]); - - return true; - } - - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() == 8) - { - time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; - - User *user = do_nick("", params[1], params[4], params[2], source, params[7], ts, params[6], params[3], "", params[5]); - if (user && nickserv) - { - user->SetCloakedHost(params[3]); - - NickAlias *na = findnick(user->nick); - Anope::string *svidbuf = na ? na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("authenticationtoken") : NULL; - if (na && svidbuf && *svidbuf == params[0]) - { - NickCore *nc = na->nc; - user->Login(nc); - if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false) - user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - else if (nickserv) - nickserv->Validate(user); - } - } - else if (params.size() == 1) - do_nick(source, params[0], "", "", "", "", 0, "", "", "", ""); - return true; - } - - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); - return true; - } - - bool OnTopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - Channel *c = findchan(params[0]); - - if (!c) - { - Log() << "TOPIC " << (params.size() > 1 ? params[1] : "") << " for nonexistent channel " << params[0]; - return true; - } + IRCDMessageCapab() : IRCDMessage("CAPAB", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : ""), Anope::CurTime); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &, const std::vector<Anope::string> ¶ms) anope_override { if (params[0].equals_cs("START")) { @@ -433,7 +359,7 @@ class InspircdIRCdMessage : public IRCdMessage has_chgidentmod = false; has_hidechansmod = false; } - else if (params[0].equals_cs("MODULES")) + else if (params[0].equals_cs("MODULES") && params.size() > 1) { if (params[1].find("m_globops.so") != Anope::string::npos) has_globopsmod = true; @@ -448,7 +374,7 @@ class InspircdIRCdMessage : public IRCdMessage if (params[1].find("m_hidechans.so") != Anope::string::npos) has_hidechansmod = true; } - else if (params[0].equals_cs("CAPABILITIES")) + else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -614,7 +540,7 @@ class InspircdIRCdMessage : public IRCdMessage else if (capab.find("MAXMODES=") != Anope::string::npos) { Anope::string maxmodes(capab.begin() + 9, capab.end()); - ircd->maxmodes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; + ircdproto->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; } } } @@ -647,15 +573,69 @@ class InspircdIRCdMessage : public IRCdMessage Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) Log() << "CHGIDENT missing, Usage disabled until module is loaded."; - ircd->svshold = has_svsholdmod; + ircdproto->CanSVSHold = has_svsholdmod; } - IRCdMessage::OnCapab(source, params); + return true; + } +}; + +struct IRCDMessageChgIdent : IRCDMessage +{ + IRCDMessageChgIdent(const Anope::string &n) : IRCDMessage(n, 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (!u) + { + Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; + return true; + } + + u->SetIdent(params[1]); + return true; + } +}; + +struct IRCDMessageChgName : IRCDMessage +{ + IRCDMessageChgName(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->SetRealname(params[0]); + return true; + } +}; + +struct IRCDMessageEndBurst : IRCDMessage +{ + IRCDMessageEndBurst() : IRCDMessage("ENDBURST", 0) { } + bool Run(MessageSource &, const std::vector<Anope::string> ¶ms) anope_override + { + Me->GetLinks().front()->Sync(true); return true; } +}; + +struct IRCDMessageFHost : IRCDMessage +{ + IRCDMessageFHost(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->SetDisplayedHost(params[0]); + return true; + } +}; + +struct IRCDMessageFJoin : IRCDMessage +{ + IRCDMessageFJoin() : IRCDMessage("FJOIN", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[0]); time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; @@ -719,7 +699,7 @@ class InspircdIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -746,206 +726,209 @@ class InspircdIRCdMessage : public IRCdMessage } }; -bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageFMode : IRCDMessage { - /* :source FTOPIC channel ts setby :topic */ - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) + IRCDMessageFMode() : IRCDMessage("FMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log() << "TOPIC for nonexistant channel " << params[0]; - return true; - } + /* :source FMODE #test 12345678 +nto foo */ - c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); + Channel *c = findchan(params[0]); + if (!c) + return true; + time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - return true; -} + /* TS's are equal now, so we can proceed with parsing */ + // For fun, modes sometimes get sent without a mode prefix + Anope::string modes = "+" + params[2]; + for (unsigned n = 3; n < params.size(); ++n) + modes += " " + params[n]; -bool event_opertype(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* opertype is equivalent to mode +o because servers - dont do this directly */ - User *u = finduser(source); - if (u && !u->HasMode(UMODE_OPER)) - { - std::vector<Anope::string> newparams; - newparams.push_back(source); - newparams.push_back("+o"); - return ircdmessage->OnMode(source, newparams); - } - else + c->SetModesInternal(source, modes, ts); return true; -} + } +}; -bool event_fmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageFTopic : IRCDMessage { - /* :source FMODE #test 12345678 +nto foo */ - if (params.size() < 3) - return true; + IRCDMessageFTopic() : IRCDMessage("FTOPIC", 4) { } - Channel *c = findchan(params[0]); - /* Checking the TS for validity to avoid desyncs */ - if (c) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - if (c->creation_time > ts) - { - /* Our TS is bigger, we should lower it */ - c->creation_time = ts; - c->Reset(); - } - else if (c->creation_time < ts) - /* The TS we got is bigger, we should ignore this message. */ - return true; - } - else - /* Got FMODE for a non-existing channel */ - return true; - - /* TS's are equal now, so we can proceed with parsing */ - std::vector<Anope::string> newparams; // channel, modes, ts - newparams.push_back(params[0]); - // For fun, modes sometimes get sent without a mode prefix - Anope::string modes = "+" + params[2]; - for (unsigned n = 3; n < params.size(); ++n) - modes += " " + params[n]; - newparams.push_back(modes); - newparams.push_back(params[1]); - - return ircdmessage->OnMode(source, newparams); -} + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); -bool event_rsquit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.empty() || params.size() > 3) return true; + } +}; - std::vector<Anope::string> p; - /* Horrible workaround to an insp bug (#) in how RSQUITs are sent - mark */ - if (params.size() > 1 && Config->ServerName.equals_cs(params[0])) - p.push_back(params[1]); - else - p.push_back(params[0]); - - ircdmessage->OnSQuit(source, p); - - return true; -} - -bool event_setname(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageIdle : IRCDMessage { - if (params.empty()) - return true; + IRCDMessageIdle() : IRCDMessage("IDLE", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "SETNAME for nonexistent user " << source; + const BotInfo *bi = findbot(params[0]); + UplinkSocket::Message(bi) << "IDLE " << source.GetSource() << " " << start_time << " " << (bi ? Anope::CurTime - bi->lastmsg : 0); return true; } +}; - u->SetRealname(params[0]); - return true; -} - -bool event_chgname(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageMode : IRCDMessage { - if (params.size() < 2) - return true; + IRCDMessageMode() : IRCDMessage("MODE", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "FNAME for nonexistent user " << source; + if (ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts; + + try + { + ts = convertTo<time_t>(params[2]); + } + catch (const ConvertException &) + { + ts = Anope::CurTime; + } + + if (c) + c->SetModesInternal(source, params[1], ts); + } + else + { + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + return true; } +}; - u->SetRealname(params[0]); - return true; -} - -bool event_setident(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageNick : IRCDMessage { - if (!params.empty()) - return true; + IRCDMessageNick() : IRCDMessage("NICK", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "SETIDENT for nonexistent user " << source; + if (params.size() == 8 && source.GetServer()) + { + time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : Anope::CurTime; + + User *user = new User(params[1], params[4], params[2], params[3], params[6], source.GetServer(), params[7], ts, params[5]); + if (nickserv) + { + NickAlias *na = findnick(user->nick); + Anope::string *svidbuf = na ? na->nc->GetExt<ExtensibleItemClass<Anope::string> *>("authenticationtoken") : NULL; + if (na && svidbuf && *svidbuf == params[0]) + { + NickCore *nc = na->nc; + user->Login(nc); + if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false) + user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + else if (nickserv) + nickserv->Validate(user); + } + } + else if (params.size() == 1 && source.GetUser()) + source.GetUser()->ChangeNick(params[0]); + return true; } +}; - u->SetIdent(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageOperType : IRCDMessage { - if (params.size() < 2) - return true; + IRCDMessageOperType() : IRCDMessage("OPERTYPE", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_USER); } - User *u = finduser(params[0]); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; + /* opertype is equivalent to mode +o because servers + dont do this directly */ + User *u = source.GetUser(); + if (!u->HasMode(UMODE_OPER)) + u->SetModesInternal("+o"); + return true; } +}; - u->SetIdent(params[1]); - return true; -} - -bool event_sethost(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageRSQuit : IRCDMessage { - if (params.empty()) - return true; + IRCDMessageRSQuit() : IRCDMessage("RSQUIT", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - User *u = finduser(source); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "SETHOST for nonexistent user " << source; - return true; - } + if (params.empty() || params.size() > 3) + return true; - u->SetDisplayedHost(params[0]); - return true; -} + Server *s; + /* Horrible workaround to an insp bug (#) in how RSQUITs are sent - mark */ + if (params.size() > 1 && Config->ServerName.equals_cs(params[0])) + s = Server::Find(params[1]); + else + s = Server::Find(params[0]); + source.GetServer()->Delete(source.GetServer()->GetName() + " " + source.GetServer()->GetUplink()->GetName()); -bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.empty()) return true; + } +}; - User *u = finduser(source); - if (!u) +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "FHOST for nonexistent user " << source; + unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[2]); return true; } - - u->SetDisplayedHost(params[0]); - return true; -} - -bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Me->GetLinks().front()->Sync(true); - return true; -} +}; class ProtoInspIRCd : public Module { - Message message_endburst, message_rsquit, message_svsmode, message_chghost, message_chgident, message_chgname, - message_sethost, message_setident, message_setname, message_fmode, message_ftopic, message_opertype, - message_idle, message_fjoin; - InspIRCdProto ircd_proto; - InspircdIRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + + /* Our message handlers */ + IRCDMessageCapab message_capab; + IRCDMessageChgIdent message_chgident, message_setident; + IRCDMessageChgName message_chgname, message_setname; + IRCDMessageEndBurst message_endburst; + IRCDMessageFHost message_fhost, message_sethost; + IRCDMessageFJoin message_fjoin; + IRCDMessageFMode message_fmode; + IRCDMessageFTopic message_ftopic; + IRCDMessageIdle message_idle; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessageOperType message_opertype; + IRCDMessageRSQuit message_rsquit; + IRCDMessageServer message_server; void AddModes() { @@ -960,20 +943,12 @@ class ProtoInspIRCd : public Module public: ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_endburst("ENDBURST", event_endburst), message_rsquit("RSQUIT", event_rsquit), - message_svsmode("SVSMODE", OnMode), message_chghost("CHGHOST", event_chghost), - message_chgident("CHGIDENT", event_chgident), message_chgname("CHGNAME", event_chgname), - message_sethost("SETHOST", event_sethost), message_setident("SETIDENT", event_setident), - message_setname("SETNAME", event_setname), message_fmode("FMODE", event_fmode), - message_ftopic("FTOPIC", event_ftopic), message_opertype("OPERTYPE", event_opertype), - message_idle("IDLE", event_idle), message_fjoin("FJOIN", OnSJoin) + message_chgident("CHGIDENT"), message_setident("SETIDENT"), + message_chgname("CHGNAME"), message_setname("SETNAME"), + message_fhost("FHOST"), message_sethost("SETHOST") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - Capab.insert("NOQUIT"); this->AddModes(); diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index e20e9c87d..c780e8299 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -20,250 +20,15 @@ static bool has_chgidentmod = false; static bool has_rlinemod = false; #include "inspircd-ts6.h" -IRCDVar myIrcd = { - "InspIRCd 1.2", /* ircd name */ - "+I", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 0, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 0, /* time stamp on mode */ - 0, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 1, /* ts6 */ - "$", /* TLD Prefix for Global */ - 20, /* Max number of modes we can send per line */ - 1, /* IRCd sends a SSL users certificate fingerprint */ -}; - static bool has_servicesmod = false; static bool has_svsholdmod = false; static bool has_hidechansmod = false; -bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :source FTOPIC channel ts setby :topic */ - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log(LOG_DEBUG) << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); - - return true; -} - -bool event_opertype(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* opertype is equivalent to mode +o because servers - dont do this directly */ - User *u = finduser(source); - if (u && !u->HasMode(UMODE_OPER)) - { - std::vector<Anope::string> newparams; - newparams.push_back(source); - newparams.push_back("+o"); - return ircdmessage->OnMode(source, newparams); - } - - return true; -} - -bool event_fmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :source FMODE #test 12345678 +nto foo */ - if (params.size() < 3) - return true; - - Channel *c = findchan(params[0]); - if (!c) - return true; - - /* Checking the TS for validity to avoid desyncs */ - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - if (c->creation_time > ts) - { - /* Our TS is bigger, we should lower it */ - c->creation_time = ts; - c->Reset(); - } - else if (c->creation_time < ts) - /* The TS we got is bigger, we should ignore this message. */ - return true; - - /* TS's are equal now, so we can proceed with parsing */ - std::vector<Anope::string> newparams; - newparams.push_back(params[0]); - newparams.push_back(params[1]); - Anope::string modes = params[2]; - for (unsigned n = 3; n < params.size(); ++n) - modes += " " + params[n]; - newparams.push_back(modes); - - return ircdmessage->OnMode(source, newparams); -} - -bool event_setname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETNAME for nonexistent user " << source; - return true; - } - else if (params.empty()) - return true; - - u->SetRealname(params[0]); - return true; -} - -bool event_chgname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FNAME for nonexistent user " << source; - return true; - } - else if (params.empty()) - return true; - - u->SetRealname(params[0]); - return true; -} - -bool event_setident(const Anope::string &source, const std::vector<Anope::string> ¶ms) +class InspIRCd12Proto : public InspIRCdTS6Proto { - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "SETIDENT for nonexistent user " << source; - return true; - } - - u->SetIdent(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(params[0]); - - if (!u) - { - Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; - return true; - } - - u->SetIdent(params[1]); - return true; -} - -bool event_sethost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "SETHOST for nonexistent user " << source; - return true; - } - - u->SetDisplayedHost(params[0]); - return true; -} - - -bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FHOST for nonexistent user " << source; - return true; - } - - u->SetDisplayedHost(params[0]); - return true; -} - - -/* - * source = numeric of the sending server - * params[0] = uuid - * params[1] = metadata name - * params[2] = data - */ -bool event_metadata(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 3) - return true; - else if (params[1].equals_cs("accountname")) - { - User *u = finduser(params[0]); - NickCore *nc = findcore(params[2]); - if (u && nc) - { - u->Login(nc); - - const NickAlias *user_na = findnick(u->nick); - if (!Config->NoNicknameOwnership && nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - } - - /* - * possible incoming ssl_cert messages: - * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...> - * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0) - */ - else if (params[1].equals_cs("ssl_cert")) - { - User *u = finduser(params[0]); - if (!u) - return true; - std::string data = params[2].c_str(); - size_t pos1 = data.find(' ') + 1; - size_t pos2 = data.find(' ', pos1); - if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes. - { - u->fingerprint = data.substr(pos1, pos2 - pos1); - FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); - } - } - return true; -} - -bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - - if (!s) - throw CoreException("Got ENDBURST without a source"); - - Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - - s->Sync(true); - return true; -} + public: + InspIRCd12Proto() : InspIRCdTS6Proto("InspIRCd 1.2") { } +}; class InspIRCdExtBan : public ChannelModeList { @@ -316,37 +81,11 @@ class InspIRCdExtBan : public ChannelModeList } }; -class Inspircd12IRCdMessage : public InspircdIRCdMessage +struct IRCDMessageCapab : IRCDMessage { - public: - /* - * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell <w00t@inspircd.org> - * 0: uid - * 1: ts - * 2: nick - * 3: host - * 4: dhost - * 5: ident - * 6: ip - * 7: signon - * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname! - * last: realname - */ - bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - time_t ts = convertTo<time_t>(params[1]); + IRCDMessageCapab() : IRCDMessage("CAPAB", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - Anope::string modes = params[8]; - for (unsigned i = 9; i < params.size() - 1; ++i) - modes += " " + params[i]; - User *user = do_nick("", params[2], params[5], params[3], source, params[params.size() - 1], ts, params[6], params[4], params[0], modes); - if (user && user->server->IsSynced() && nickserv) - nickserv->Validate(user); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { if (params[0].equals_cs("START")) { @@ -358,7 +97,7 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage has_chgidentmod = false; has_hidechansmod = false; } - else if (params[0].equals_cs("MODULES")) + else if (params[0].equals_cs("MODULES") && params.size() > 1) { if (params[1].find("m_globops.so") != Anope::string::npos) has_globopsmod = true; @@ -373,11 +112,11 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage if (params[1].find("m_hidechans.so") != Anope::string::npos) has_hidechansmod = true; if (params[1].find("m_servprotect.so") != Anope::string::npos) - ircd->pseudoclient_mode = "+Ik"; + ircdproto->DefaultPseudoclientModes = "+Ik"; if (params[1].find("m_rline.so") != Anope::string::npos) has_rlinemod = true; } - else if (params[0].equals_cs("CAPABILITIES")) + else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -643,7 +382,7 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage else if (capab.find("MAXMODES=") != Anope::string::npos) { Anope::string maxmodes(capab.begin() + 9, capab.end()); - ircd->maxmodes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; + ircdproto->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; } } } @@ -676,43 +415,97 @@ class Inspircd12IRCdMessage : public InspircdIRCdMessage Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) Log() << "CHGIDENT missing, Usage disabled until module is loaded."; - ircd->svshold = has_svsholdmod; + ircdproto->CanSVSHold = has_svsholdmod; } - IRCdMessage::OnCapab(source, params); + return true; + } +}; + +struct IRCDMessageChgIdent : IRCDMessage +{ + IRCDMessageChgIdent() : IRCDMessage("CHGIDENT", 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetIdent(params[1]); + return true; + } +}; + +struct IRCDMessageChgName : IRCDMessage +{ + IRCDMessageChgName(const Anope::string &n) : IRCDMessage(n, 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->SetRealname(params[0]); + return true; + } +}; + +struct IRCDMessageSetIdent : IRCDMessage +{ + IRCDMessageSetIdent() : IRCDMessage("SETIDENT", 0) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->SetIdent(params[0]); return true; } }; class ProtoInspIRCd : public Module { - Message message_endburst, message_time, - message_rsquit, message_svsmode, message_fhost, - message_chgident, message_fname, message_sethost, message_setident, message_setname, message_fjoin, message_fmode, - message_ftopic, message_opertype, message_idle, message_metadata; - - InspIRCdTS6Proto ircd_proto; - Inspircd12IRCdMessage ircd_message; + InspIRCd12Proto ircd_proto; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + + /* inspircd-ts6.h message handlers */ + IRCDMessageEndburst message_endburst; + IRCDMessageFHost message_fhost, message_sethost; + IRCDMessageFJoin message_sjoin; + IRCDMessageFMode message_fmode; + IRCDMessageFTopic message_ftopic; + IRCDMessageIdle message_idle; + IRCDMessageMetadata message_metadata; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessageOperType message_opertype; + IRCDMessageRSQuit message_rsquit; + IRCDMessageServer message_server; + IRCDMessageTime message_time; + IRCDMessageUID message_uid; + + /* Our message handlers */ + IRCDMessageChgIdent message_chgident; + IRCDMessageChgName message_setname, message_chgname; + IRCDMessageCapab message_capab; + IRCDMessageSetIdent message_setident; public: ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_endburst("ENDBURST", event_endburst), - message_time("TIME", event_time), message_rsquit("RSQUIT", event_rsquit), - message_svsmode("SVSMODE", OnMode), message_fhost("FHOST", event_chghost), - message_chgident("CHGIDENT", event_chgident), message_fname("FNAME", event_chgname), - message_sethost("SETHOST", event_sethost), message_setident("SETIDENT", event_setident), - message_setname("SETNAME", event_setname), message_fjoin("FJOIN", OnSJoin), - message_fmode("FMODE", event_fmode), message_ftopic("FTOPIC", event_ftopic), - message_opertype("OPERTYPE", event_opertype), message_idle("IDLE", event_idle), - message_metadata("METADATA", event_metadata) + message_fhost("FHOST"), message_sethost("SETHOST"), + message_setname("SETNAME"), message_chgname("FNAME") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - Capab.insert("NOQUIT"); Implementation i[] = { I_OnUserNickChange, I_OnServerSync }; @@ -729,14 +522,6 @@ class ProtoInspIRCd : public Module it->second->GenerateUID(); } - ~ProtoInspIRCd() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - - void OnUserNickChange(User *u, const Anope::string &) anope_override { /* InspIRCd 1.2 doesn't set -r on nick change, remove -r here. Note that if we have to set +r later diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index b1352959c..25d0c9333 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -20,255 +20,23 @@ static bool has_globopsmod = true; // Not a typo static bool has_rlinemod = false; #include "inspircd-ts6.h" -IRCDVar myIrcd = { - "InspIRCd 2.0", /* ircd name */ - "+I", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 0, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 0, /* time stamp on mode */ - 0, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 1, /* ts6 */ - "$", /* TLD Prefix for Global */ - 20, /* Max number of modes we can send per line */ - 1, /* IRCd sends a SSL users certificate fingerprint */ -}; - static bool has_servicesmod = false; static bool has_svsholdmod = false; -class InspIRCdProto : public InspIRCdTS6Proto +class InspIRCd20Proto : public InspIRCdTS6Proto { + public: + InspIRCd20Proto() : InspIRCdTS6Proto("InspIRCd 2.0") { } + void SendConnect() anope_override { UplinkSocket::Message() << "CAPAB START 1202"; UplinkSocket::Message() << "CAPAB CAPABILITIES :PROTOCOL=1202"; UplinkSocket::Message() << "CAPAB END"; - SendServer(Me); - UplinkSocket::Message(Me) << "BURST"; - Module *enc = ModuleManager::FindFirstOf(ENCRYPTION); - UplinkSocket::Message(Me) << "VERSION :Anope-" << Anope::Version() << " " << Me->GetName() << " :" << ircd->name <<" - (" << (enc ? enc->name : "unknown") << ") -- " << Anope::VersionBuildString(); + InspIRCdTS6Proto::SendConnect(); } }; -bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :source FTOPIC channel ts setby :topic */ - if (params.size() < 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log(LOG_DEBUG) << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[2], params[3], Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime); - - return true; -} - -bool event_opertype(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* opertype is equivalent to mode +o because servers - dont do this directly */ - User *u = finduser(source); - if (u && !u->HasMode(UMODE_OPER)) - { - std::vector<Anope::string> newparams; - newparams.push_back(source); - newparams.push_back("+o"); - return ircdmessage->OnMode(source, newparams); - } - return true; -} - -bool event_fmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :source FMODE #test 12345678 +nto foo */ - if (params.size() < 3) - return true; - - Channel *c = findchan(params[0]); - if (!c) - return true; - - /* Checking the TS for validity to avoid desyncs */ - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - if (c->creation_time > ts) - { - /* Our TS is bigger, we should lower it */ - c->creation_time = ts; - c->Reset(); - } - else if (c->creation_time < ts) - /* The TS we got is bigger, we should ignore this message. */ - return true; - - /* TS's are equal now, so we can proceed with parsing */ - std::vector<Anope::string> newparams; - newparams.push_back(params[0]); - newparams.push_back(params[1]); - Anope::string modes = params[2]; - for (unsigned n = 3; n < params.size(); ++n) - modes += " " + params[n]; - newparams.push_back(modes); - - return ircdmessage->OnMode(source, newparams); -} - -bool event_chgname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FNAME for nonexistent user " << source; - return true; - } - else if (params.empty()) - return true; - - u->SetRealname(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FIDENT for nonexistent user " << source; - return true; - } - - u->SetIdent(params[0]); - return true; -} - -bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - if (!u) - { - Log(LOG_DEBUG) << "FHOST for nonexistent user " << source; - return true; - } - - u->SetDisplayedHost(params[0]); - return true; -} - - -/* - * source = numeric of the sending server - * params[0] = uuid - * params[1] = metadata name - * params[2] = data - */ -bool event_metadata(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 3) - return true; - else if (params[1].equals_cs("accountname")) - { - User *u = finduser(params[0]); - NickCore *nc = findcore(params[2]); - if (u && nc) - { - u->Login(nc); - - const NickAlias *user_na = findnick(u->nick); - if (!Config->NoNicknameOwnership && nickserv && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - } - - /* - * possible incoming ssl_cert messages: - * Received: :409 METADATA 409AAAAAA ssl_cert :vTrSe c38070ce96e41cc144ed6590a68d45a6 <...> <...> - * Received: :409 METADATA 409AAAAAC ssl_cert :vTrSE Could not get peer certificate: error:00000000:lib(0):func(0):reason(0) - */ - else if (params[1].equals_cs("ssl_cert")) - { - User *u = finduser(params[0]); - if (!u) - return true; - std::string data = params[2].c_str(); - size_t pos1 = data.find(' ') + 1; - size_t pos2 = data.find(' ', pos1); - if ((pos2 - pos1) >= 32) // inspircd supports md5 and sha1 fingerprint hashes -> size 32 or 40 bytes. - { - u->fingerprint = data.substr(pos1, pos2 - pos1); - FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); - } - } - return true; -} - -bool event_encap(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 2 || Server::Find(params[0]) != Me) - return true; - - if (params[1] == "CHGIDENT" && params.size() > 3) - { - User *u = finduser(params[2]); - if (!u || u->server != Me) - return true; - - u->SetIdent(params[3]); - UplinkSocket::Message(u) << "FIDENT " << params[3]; - } - else if (params[1] == "CHGHOST" && params.size() > 3) - { - User *u = finduser(params[2]); - if (!u || u->server != Me) - return true; - - u->SetDisplayedHost(params[3]); - UplinkSocket::Message(u) << "FHOST " << params[3]; - } - else if (params[1] == "CHGNAME" && params.size() > 3) - { - User *u = finduser(params[2]); - if (!u || u->server != Me) - return true; - - u->SetRealname(params[3]); - UplinkSocket::Message(u) << "FNAME " << params[3]; - } - - return true; -} - -bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - - if (!s) - throw CoreException("Got ENDBURST without a source"); - - Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - - s->Sync(true); - return true; -} - class InspIRCdExtBan : public ChannelModeList { public: @@ -342,37 +110,11 @@ class InspIRCdExtBan : public ChannelModeList } }; -class Inspircd20IRCdMessage : public InspircdIRCdMessage +struct IRCDMessageCapab : IRCDMessage { - public: - /* - * [Nov 03 22:09:58.176252 2009] debug: Received: :964 UID 964AAAAAC 1225746297 w00t2 localhost testnet.user w00t 127.0.0.1 1225746302 +iosw +ACGJKLNOQcdfgjklnoqtx :Robin Burchell <w00t@inspircd.org> - * 0: uid - * 1: ts - * 2: nick - * 3: host - * 4: dhost - * 5: ident - * 6: ip - * 7: signon - * 8+: modes and params -- IMPORTANT, some modes (e.g. +s) may have parameters. So don't assume a fixed position of realname! - * last: realname - */ - bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; + IRCDMessageCapab() : IRCDMessage("CAPAB", 1) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - Anope::string modes = params[8]; - for (unsigned i = 9; i < params.size() - 1; ++i) - modes += Anope::string(" ") + params[i]; - User *user = do_nick("", params[2], params[5], params[3], source, params[params.size() - 1], ts, params[6], params[4], params[0], modes); - if (user && user->server->IsSynced() && nickserv) - nickserv->Validate(user); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { if (params[0].equals_cs("START")) { @@ -390,7 +132,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage has_chghostmod = false; has_chgidentmod = false; } - else if (params[0].equals_cs("CHANMODES")) + else if (params[0].equals_cs("CHANMODES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -490,7 +232,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage Log() << "Unrecognized mode string in CAPAB CHANMODES: " << capab; } } - if (params[0].equals_cs("USERMODES")) + if (params[0].equals_cs("USERMODES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -528,7 +270,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage else if (modename.equals_cs("servprotect")) { um = new UserMode(UMODE_PROTECTED, modechar[0]); - ircd->pseudoclient_mode = "+Ik"; // XXX + ircdproto->DefaultPseudoclientModes += "k"; } else if (modename.equals_cs("showwhois")) um = new UserMode(UMODE_WHOIS, modechar[0]); @@ -547,7 +289,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage Log() << "Unrecognized mode string in CAPAB USERMODES: " << capab; } } - else if (params[0].equals_cs("MODULES")) + else if (params[0].equals_cs("MODULES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string module; @@ -559,12 +301,12 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage else if (module.find("m_rline.so") == 0) { has_rlinemod = true; - if (!Config->RegexEngine.empty() && Config->RegexEngine != module.substr(11)) + if (!Config->RegexEngine.empty() && module.length() > 11 && Config->RegexEngine != module.substr(11)) Log() << "Warning: InspIRCd is using regex engine " << module.substr(11) << ", but we have " << Config->RegexEngine << ". This may cause inconsistencies."; } } } - else if (params[0].equals_cs("MODSUPPORT")) + else if (params[0].equals_cs("MODSUPPORT") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string module; @@ -579,7 +321,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage has_chgidentmod = true; } } - else if (params[0].equals_cs("CAPABILITIES")) + else if (params[0].equals_cs("CAPABILITIES") && params.size() > 1) { spacesepstream ssep(params[1]); Anope::string capab; @@ -643,7 +385,7 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage else if (capab.find("MAXMODES=") != Anope::string::npos) { Anope::string maxmodes(capab.begin() + 9, capab.end()); - ircd->maxmodes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; + ircdproto->MaxModes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; } else if (capab.find("PREFIX=") != Anope::string::npos) { @@ -688,10 +430,49 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage Log() << "CHGHOST missing, Usage disabled until module is loaded."; if (!has_chgidentmod) Log() << "CHGIDENT missing, Usage disabled until module is loaded."; - ircd->svshold = has_svsholdmod; + ircdproto->CanSVSHold = has_svsholdmod; } - IRCdMessage::OnCapab(source, params); + return true; + } +}; + +struct IRCDMessageEncap : IRCDMessage +{ + IRCDMessageEncap() : IRCDMessage("ENCAP", 4) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (Anope::Match(Me->GetSID(), params[0]) == false) + return true; + + if (params[1] == "CHGIDENT") + { + User *u = finduser(params[2]); + if (!u || u->server != Me) + return true; + + u->SetIdent(params[3]); + UplinkSocket::Message(u) << "FIDENT " << params[3]; + } + else if (params[1] == "CHGHOST") + { + User *u = finduser(params[2]); + if (!u || u->server != Me) + return true; + + u->SetDisplayedHost(params[3]); + UplinkSocket::Message(u) << "FHOST " << params[3]; + } + else if (params[1] == "CHGNAME") + { + User *u = finduser(params[2]); + if (!u || u->server != Me) + return true; + + u->SetRealname(params[3]); + UplinkSocket::Message(u) << "FNAME " << params[3]; + } return true; } @@ -699,31 +480,50 @@ class Inspircd20IRCdMessage : public InspircdIRCdMessage class ProtoInspIRCd : public Module { - Message message_endburst, message_time, - message_rsquit, message_svsmode, message_fhost, - message_chgident, message_fname, message_fjoin, message_fmode, - message_ftopic, message_opertype, message_idle, message_metadata, - message_encap; - - InspIRCdProto ircd_proto; - Inspircd20IRCdMessage ircd_message; + InspIRCd20Proto ircd_proto; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + + /* inspircd-ts6.h message handlers */ + IRCDMessageEndburst message_endburst; + IRCDMessageFHost message_fhost; + IRCDMessageFJoin message_sjoin; + IRCDMessageFMode message_fmode; + IRCDMessageFTopic message_ftopic; + IRCDMessageIdle message_idle; + IRCDMessageMetadata message_metadata; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessageOperType message_opertype; + IRCDMessageRSQuit message_rsquit; + IRCDMessageServer message_server; + IRCDMessageTime message_time; + IRCDMessageUID message_uid; + + /* Our message handlers */ + IRCDMessageCapab message_capab; + IRCDMessageEncap message_encap; + public: ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_endburst("ENDBURST", event_endburst), - message_time("TIME", event_time), message_rsquit("RSQUIT", event_rsquit), - message_svsmode("SVSMODE", OnMode), message_fhost("FHOST", event_chghost), - message_chgident("FIDENT", event_chgident), message_fname("FNAME", event_chgname), - message_fjoin("FJOIN", OnSJoin), - message_fmode("FMODE", event_fmode), message_ftopic("FTOPIC", event_ftopic), - message_opertype("OPERTYPE", event_opertype), message_idle("IDLE", event_idle), - message_metadata("METADATA", event_metadata), message_encap("ENCAP", event_encap) + message_fhost("FHOST") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - Capab.insert("NOQUIT"); Implementation i[] = { I_OnUserNickChange, I_OnServerSync, I_OnChannelCreate, I_OnChanRegistered, I_OnDelChan, I_OnMLock, I_OnUnMLock }; @@ -740,13 +540,6 @@ class ProtoInspIRCd : public Module it->second->GenerateUID(); } - ~ProtoInspIRCd() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - void OnUserNickChange(User *u, const Anope::string &) anope_override { u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED)); diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index 5debfa5dc..1ef8adab9 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -11,35 +11,36 @@ #include "module.h" -static Anope::string TS6UPLINK; - -IRCDVar myIrcd = { - "hybrid-7.2.3+plexus-3.0.1", /* ircd name */ - "+oi", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 0, /* Supports SZlines */ - 0, /* Join 2 Message */ - 1, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 1, /* time stamp on mode */ - 1, /* UMODE */ - 0, /* O:LINE */ - 0, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 1, /* ts6 */ - "$$", /* TLD Prefix for Global */ - 4, /* Max number of modes we can send per line */ - 1, /* IRCd sends a SSL users certificate fingerprint */ -}; +static Anope::string UplinkSID; class PlexusProto : public IRCDProto { + public: + PlexusProto() : IRCDProto("hybrid-7.2.3+plexus-3.0.1") + { + DefaultPseudoclientModes = "+oiU"; + CanSVSNick = true; + CanSetVHost = true; + CanSetVIdent = true; + CanSNLine = true; + CanSQLine = true; + CanSQLineChannel = true; + CanSVSHold = true; + CanCertFP = true; + RequiresID = true; + MaxModes = 4; + } + + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $$" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $$" << dest->GetName() << " :" << msg; + } + void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf) anope_override { UplinkSocket::Message(source) << "OPERWALL :" << buf; @@ -236,108 +237,202 @@ class PlexusProto : public IRCDProto } }; -class PlexusIRCdMessage : public IRCdMessage +struct IRCDMessageBMask : IRCDMessage { - public: - /* - * params[0] = ts - * params[1] = channel - */ - bool OnJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + IRCDMessageBMask() : IRCDMessage("BMASK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params.size() < 2) - return IRCdMessage::OnJoin(source, params); - do_join(source, params[1], params[0]); + /* :42X BMASK 1106409026 #ircops b :*!*@*.aol.com */ + /* 0 1 2 3 */ + Channel *c = findchan(params[1]); + + if (c) + { + ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), + *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), + *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); + + Anope::string bans = params[3]; + int count = myNumToken(bans, ' '), i; + for (i = 0; i < count; ++i) + { + Anope::string b = myStrGetToken(bans, ' ', i); + if (ban && params[2].equals_cs("b")) + c->SetModeInternal(source, ban, b); + else if (except && params[2].equals_cs("e")) + c->SetModeInternal(source, except, b); + if (invex && params[2].equals_cs("I")) + c->SetModeInternal(source, invex, b); + } + } + + return true; + } +}; + +struct IRCDMessageEncap : IRCDMessage +{ + IRCDMessageEncap() : IRCDMessage("ENCAP", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* + * Received: :dev.anope.de ENCAP * SU DukePyrolator DukePyrolator + * params[0] = * + * params[1] = SU + * params[2] = nickname + * params[3] = account + */ + if (params[1].equals_cs("SU")) + { + User *u = finduser(params[2]); + const NickAlias *user_na = findnick(params[2]); + NickCore *nc = findcore(params[3]); + if (u && nc) + { + u->Login(nc); + if (!Config->NoNicknameOwnership && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + } + + /* + * Received: :dev.anope.de ENCAP * CERTFP DukePyrolator :3F122A9CC7811DBAD3566BF2CEC3009007C0868F + * params[0] = * + * params[1] = CERTFP + * params[2] = nickname + * params[3] = fingerprint + */ + else if (params[1].equals_cs("CERTFP")) + { + User *u = finduser(params[2]); + if (u) + { + u->fingerprint = params[3]; + FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); + } + } + return true; + } +}; + +struct IRCDMessageEOB : IRCDMessage +{ + IRCDMessageEOB() : IRCDMessage("EOB", 0) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetServer()->Sync(true); return true; } +}; - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +struct IRCDMessageJoin : CoreIRCDMessageJoin +{ + IRCDMessageJoin() : CoreIRCDMessageJoin("JOIN") { } + + /* + * params[0] = ts + * params[1] = channel + */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { if (params.size() < 2) return true; - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[2], params[1]); - else - do_umode(params[0], params[1]); + std::vector<Anope::string> p = params; + p.erase(p.begin()); - return true; + return CoreIRCDMessageJoin::Run(source, p); } +}; - /* - TS6 - params[0] = nick - params[1] = hop - params[2] = ts - params[3] = modes - params[4] = user - params[5] = host - params[6] = IP - params[7] = UID - params[8] = services stamp - params[9] = realhost - params[10] = info - */ - bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode() : IRCDMessage("MODE", 3) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - /* An IP of 0 means the user is spoofed */ - Anope::string ip = params[6]; - if (ip == "0") - ip.clear(); - User *user = do_nick("", params[0], params[4], params[9], source, params[10], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, ip, params[5], params[7], params[3]); - if (nickserv && user && user->server->IsSynced()) - nickserv->Validate(user); + if (ircdproto->IsChannelValid(params[0])) + { + // 0 = channel, 1 = ts, 2 = modes + Channel *c = findchan(params[0]); + time_t ts = Anope::CurTime; + try + { + ts = convertTo<time_t>(params[1]); + } + catch (const ConvertException &) { } + + if (c) + c->SetModesInternal(source, params[2], ts); + } + else + { + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } return true; } +}; + +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 2) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); + source.GetUser()->ChangeNick(params[0]); return true; } +}; + +struct IRCDMessagePass : IRCDMessage +{ + IRCDMessagePass() : IRCDMessage("PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params[1].equals_cs("1")) - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], TS6UPLINK); - else - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); + UplinkSID = params[3]; return true; } +}; - /* - TS6 - params[0] = nick - params[1] = hop - params[2] = ts - params[3] = modes - params[4] = user - params[5] = host - params[6] = IP - params[7] = UID - params[8] = services stamp - params[9] = realhost - params[10] = info - */ - bool OnTopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; + // Servers other then our immediate uplink are introduced via SID + if (params[1] != "1") return true; - } + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], 1, params[2], UplinkSID); + return true; + } +}; - if (params.size() == 4) - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - else - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : "")); +struct IRCDMessageSID : IRCDMessage +{ + IRCDMessageSID() : IRCDMessage("SID", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + /* :42X SID trystan.nomadirc.net 2 43X :ircd-plexus test server */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + unsigned int hops = params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[3], params[2]); return true; } +}; + +struct IRCDMessageSJoin : IRCDMessage +{ + IRCDMessageSJoin() : IRCDMessage("SJOIN", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[1]); time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; @@ -367,7 +462,7 @@ class PlexusIRCdMessage : public IRCdMessage if (!modes.empty()) modes.erase(modes.begin()); /* Set the modes internally */ - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } spacesepstream sep(params[params.size() - 1]); @@ -409,7 +504,7 @@ class PlexusIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -436,155 +531,144 @@ class PlexusIRCdMessage : public IRCdMessage } }; -bool event_tburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTBurst : IRCDMessage { - // :rizon.server TBURST 1298674830 #lol 1298674833 Adam!Adam@i.has.a.spoof :lol - if (params.size() < 4) - return true; - - Channel *c = findchan(params[1]); + IRCDMessageTBurst() : IRCDMessage("TBURST", 5) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - if (!c) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log() << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; - return true; - } - else if (c->creation_time < convertTo<time_t>(params[0])) - return true; - - Anope::string setter = myStrGetToken(params[3], '!', 0); - time_t topic_time = Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime; - c->ChangeTopicInternal(setter, params.size() > 4 ? params[4] : "", topic_time); + // 0 1 2 3 4 + // :rizon.server TBURST 1298674830 #lol 1298674833 Adam!Adam@i.has.a.spoof :lol + // chan ts topic ts - return true; -} + Channel *c = findchan(params[1]); -bool event_sid(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :42X SID trystan.nomadirc.net 2 43X :ircd-plexus test server */ - Server *s = Server::Find(source); + try + { + if (!c || c->creation_time < convertTo<time_t>(params[0])) + return true; + } + catch (const ConvertException &) + { + return true; + } - do_server(s->GetName(), params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[3], params[2]); - return true; -} + Anope::string setter = myStrGetToken(params[3], '!', 0); + time_t topic_time = Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime; + c->ChangeTopicInternal(setter, params.size() > 4 ? params[4] : "", topic_time); -bool event_mode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 2) return true; + } +}; - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[2], params[1]); - else - do_umode(params[0], params[1]); - return true; -} - -bool event_tmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTMode : IRCDMessage { - if (params[1][0] == '#') + IRCDMessageTMode() : IRCDMessage("TMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { + time_t ts = Anope::CurTime; + try + { + ts = convertTo<time_t>(params[0]); + } + catch (const ConvertException &) { } + Channel *c = findchan(params[1]); Anope::string modes = params[2]; for (unsigned i = 3; i < params.size(); ++i) modes += " " + params[i]; - do_cmode(source, params[1], modes, params[0]); - } - return true; -} -bool event_pass(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - TS6UPLINK = params[3]; - return true; -} + if (c) + c->SetModesInternal(source, modes, ts); -bool event_bmask(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :42X BMASK 1106409026 #ircops b :*!*@*.aol.com */ - /* 0 1 2 3 */ - Channel *c = findchan(params[1]); - - if (c) - { - ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), - *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), - *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); - Anope::string bans = params[3]; - int count = myNumToken(bans, ' '), i; - for (i = 0; i <= count - 1; ++i) - { - Anope::string b = myStrGetToken(bans, ' ', i); - if (ban && params[2].equals_cs("b")) - c->SetModeInternal(NULL, ban, b); - else if (except && params[2].equals_cs("e")) - c->SetModeInternal(NULL, except, b); - if (invex && params[2].equals_cs("I")) - c->SetModeInternal(NULL, invex, b); - } + return true; } - return true; -} +}; -bool event_encap(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTopic : IRCDMessage { - if (params.size() < 4) - return true; - /* - * Received: :dev.anope.de ENCAP * SU DukePyrolator DukePyrolator - * params[0] = * - * params[1] = SU - * params[2] = nickname - * params[3] = account - */ - else if (params[1].equals_cs("SU")) + IRCDMessageTopic() : IRCDMessage("TOPIC", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - User *u = finduser(params[2]); - const NickAlias *user_na = findnick(params[2]); - NickCore *nc = findcore(params[3]); - if (u && nc) - { - u->Login(nc); - if (!Config->NoNicknameOwnership && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } + Channel *c = findchan(params[0]); + if (!c) + return true; + + c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); + return true; } +}; + +struct IRCDMessageUID : IRCDMessage +{ + IRCDMessageUID() : IRCDMessage("UID", 11) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } /* - * Received: :dev.anope.de ENCAP * CERTFP DukePyrolator :3F122A9CC7811DBAD3566BF2CEC3009007C0868F - * params[0] = * - * params[1] = CERTFP - * params[2] = nickname - * params[3] = fingerprint - */ - else if (params[1].equals_cs("CERTFP")) + params[0] = nick + params[1] = hop + params[2] = ts + params[3] = modes + params[4] = user + params[5] = host + params[6] = IP + params[7] = UID + params[8] = services stamp + params[9] = realhost + params[10] = info + */ + // :42X UID Adam 1 1348535644 +aow Adam 192.168.0.5 192.168.0.5 42XAAAAAB 0 192.168.0.5 :Adam + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - User *u = finduser(params[2]); - if (u) - { - u->fingerprint = params[3]; - FOREACH_MOD(I_OnFingerprint, OnFingerprint(u)); - } - } - return true; -} + /* An IP of 0 means the user is spoofed */ + Anope::string ip = params[6]; + if (ip == "0") + ip.clear(); -bool event_eob(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - if (s) - s->Sync(true); + User *user = new User(params[0], params[4], params[9], params[5], ip, source.GetServer(), params[10], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[3], params[7]); + if (user && user->server->IsSynced() && nickserv) + nickserv->Validate(user); - return true; -} + return true; + } +}; class ProtoPlexus : public Module { - Message message_tmode, message_bmask, message_pass, - message_tb, message_sid, message_encap, - message_eob; - PlexusProto ircd_proto; - PlexusIRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + CoreIRCDMessageWhois core_message_whois; + + /* Our message handlers */ + IRCDMessageBMask message_bmask; + IRCDMessageEncap message_encap; + IRCDMessageEOB message_eob; + IRCDMessageJoin message_join; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessagePass message_pass; + IRCDMessageServer message_server; + IRCDMessageSID message_sid; + IRCDMessageSJoin message_sjoin; + IRCDMessageTBurst message_tburst; + IRCDMessageTMode message_tmode; + IRCDMessageTopic message_topic; + IRCDMessageUID message_uid; void AddModes() { @@ -605,6 +689,7 @@ class ProtoPlexus : public Module ModeManager::AddUserMode(new UserMode(UMODE_PRIV, 'p')); ModeManager::AddUserMode(new UserMode(UMODE_REGISTERED, 'r')); ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x')); + ModeManager::AddUserMode(new UserMode(UMODE_PROTECTED, 'U')); /* b/e/I */ ModeManager::AddChannelMode(new ChannelModeList(CMODE_BAN, 'b')); @@ -629,8 +714,8 @@ class ProtoPlexus : public Module ModeManager::AddChannelMode(new ChannelMode(CMODE_NONOTICE, 'N')); ModeManager::AddChannelMode(new ChannelModeOper('O')); ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, 'R')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, 'S')); + ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, 'c')); ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, 'i')); ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, 'm')); @@ -642,18 +727,10 @@ class ProtoPlexus : public Module } public: - ProtoPlexus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_tmode("TMODE", event_tmode), message_bmask("BMASK", event_bmask), - message_pass("PASS", event_pass), message_tb("TBURST", event_tburst), - message_sid("SID", event_sid), message_encap("ENCAP", event_encap), - message_eob("EOB", event_eob) + ProtoPlexus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL) { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - this->AddModes(); Implementation i[] = { I_OnServerSync }; @@ -670,13 +747,6 @@ class ProtoPlexus : public Module it->second->GenerateUID(); } - ~ProtoPlexus() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - void OnServerSync(Server *s) anope_override { if (nickserv) diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index 1054c0b8c..017af4e3f 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -11,35 +11,31 @@ #include "module.h" -static Anope::string TS6UPLINK; - -IRCDVar myIrcd = { - "Ratbox 2.0+", /* ircd name */ - "+oiS", /* Modes used by pseudoclients */ - 0, /* SVSNICK */ - 0, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 0, /* Supports SZlines */ - 1, /* Join 2 Message */ - 1, /* Chan SQlines */ - 0, /* Quit on Kill */ - 0, /* vidents */ - 0, /* svshold */ - 0, /* time stamp on mode */ - 0, /* UMODE */ - 0, /* O:LINE */ - 0, /* No Knock requires +i */ - 0, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 1, /* ts6 */ - "$$", /* TLD Prefix for Global */ - 4, /* Max number of modes we can send per line */ - 0, /* IRCd sends a SSL users certificate fingerprint */ -}; +static Anope::string UplinkSID; class RatboxProto : public IRCDProto { + public: + RatboxProto() : IRCDProto("Ratbox 3.0+") + { + DefaultPseudoclientModes = "+oiS"; + CanSNLine = true; + CanSQLine = true; + CanSZLine = true; + RequiresID = true; + MaxModes = 4; + } + + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $$" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $$" << dest->GetName() << " :" << msg; + } + void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf) anope_override { UplinkSocket::Message(source) << "OPERWALL :" << buf; @@ -140,21 +136,13 @@ class RatboxProto : public IRCDProto QS - Can handle quit storm removal EX - Can do channel +e exemptions CHW - Can do channel wall @# - LL - Can do lazy links IE - Can do invite exceptions - EOB - Can do EOB message - KLN - Can do KLINE message GLN - Can do GLINE message - HUB - This server is a HUB - UID - Can do UIDs - ZIP - Can do ZIPlinks - ENC - Can do ENCrypted links - KNOCK - supports KNOCK - TBURST - supports TBURST - PARA - supports invite broadcasting for +p - ENCAP - ? + KNOCK - supports KNOCK + TB - supports topic burst + ENCAP - supports ENCAP */ - UplinkSocket::Message() << "CAPAB :QS EX CHW IE KLN GLN KNOCK TB UNKLN CLUSTER ENCAP TS6"; + UplinkSocket::Message() << "CAPAB :QS EX CHW IE GLN TB ENCAP"; /* Make myself known to myself in the serverlist */ SendServer(Me); /* @@ -224,93 +212,185 @@ class RatboxProto : public IRCDProto } }; -class RatboxIRCdMessage : public IRCdMessage +struct IRCDMessageBMask : IRCDMessage { - public: + IRCDMessageBMask() : IRCDMessage("BMASK", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* :42X BMASK 1106409026 #ircops b :*!*@*.aol.com */ + /* 0 1 2 3 */ + Channel *c = findchan(params[1]); + + if (c) + { + ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), + *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), + *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); + + Anope::string bans = params[3]; + int count = myNumToken(bans, ' '), i; + for (i = 0; i < count; ++i) + { + Anope::string b = myStrGetToken(bans, ' ', i); + if (ban && params[2].equals_cs("b")) + c->SetModeInternal(source, ban, b); + else if (except && params[2].equals_cs("e")) + c->SetModeInternal(source, except, b); + if (invex && params[2].equals_cs("I")) + c->SetModeInternal(source, invex, b); + } + } + + return true; + } +}; + +struct IRCDMessageEncap : IRCDMessage +{ + IRCDMessageEncap() : IRCDMessage("ENCAP", 3) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + // Debug: Received: :00BAAAAAB ENCAP * LOGIN Adam + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (params[1] == "LOGIN") + { + User *u = source.GetUser(); + + NickCore *nc = findcore(params[2]); + if (!nc) + return true; + u->Login(nc); + + const NickAlias *user_na = findnick(u->nick); + if (!Config->NoNicknameOwnership && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) + u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + + return true; + } +}; + +struct IRCDMessageJoin : CoreIRCDMessageJoin +{ + IRCDMessageJoin() : CoreIRCDMessageJoin("JOIN") { } + /* * params[0] = ts * params[1] = channel + * params[2] = modes */ - bool OnJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { if (params.size() < 2) - return IRCdMessage::OnJoin(source, params); - do_join(source, params[1], params[0]); - return true; + return true; + + std::vector<Anope::string> p = params; + p.erase(p.begin()); + + return CoreIRCDMessageJoin::Run(source, p); } +}; + +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode() : IRCDMessage("MODE", 3) { } - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params.size() < 2) - return true; + if (ircdproto->IsChannelValid(params[0])) + { + // 0 = channel, 1 = ts, 2 = modes + Channel *c = findchan(params[0]); + time_t ts = Anope::CurTime; + try + { + ts = convertTo<time_t>(params[1]); + } + catch (const ConvertException &) { } - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[2], params[1]); + if (c) + c->SetModesInternal(source, params[2], ts); + } else - do_umode(params[0], params[1]); + { + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } return true; } +}; - bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - /* Source is always the server */ - User *user = do_nick("", params[0], params[4], params[5], source, params[8], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[6], "*", params[7], params[3]); - if (user && user->server->IsSynced() && nickserv) - nickserv->Validate(user); +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetUser()->ChangeNick(params[0]); return true; } +}; - /* - params[0] = nick - params[1] = hop - params[2] = ts - params[3] = modes - params[4] = user - params[5] = host - params[6] = IP - params[7] = UID - params[8] = info - */ - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); +struct IRCDMessagePass : IRCDMessage +{ + IRCDMessagePass() : IRCDMessage("PASS", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + UplinkSID = params[3]; return true; } +}; + +struct IRCDMessagePong : IRCDMessage +{ + IRCDMessagePong() : IRCDMessage("PONG", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - if (params[1].equals_cs("1")) - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], TS6UPLINK); - else - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); - ircdproto->SendPing(Config->ServerName, params[0]); + source.GetServer()->Sync(false); return true; } +}; - bool OnTopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + // SERVER hades.arpa 1 :ircd-ratbox test server + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; + // Servers other then our immediate uplink are introduced via SID + if (params[1] != "1") return true; - } + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], 1, params[2], UplinkSID); + ircdproto->SendPing(Config->ServerName, params[0]); + return true; + } +}; - if (params.size() == 4) - { - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - } - else - { - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : "")); - } +struct IRCDMessageSID : IRCDMessage +{ + IRCDMessageSID() : IRCDMessage("SID", 4) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* :42X SID trystan.nomadirc.net 2 43X :ircd-ratbox test server */ + unsigned int hops = params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, params[3], params[2]); + ircdproto->SendPing(Config->ServerName, params[0]); return true; } +}; + +struct IRCDMessageSjoin : IRCDMessage +{ + IRCDMessageSjoin() : IRCDMessage("SJOIN", 2) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[1]); time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; @@ -340,7 +420,7 @@ class RatboxIRCdMessage : public IRCdMessage if (!modes.empty()) modes.erase(modes.begin()); /* Set the modes internally */ - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } spacesepstream sep(params[params.size() - 1]); @@ -382,7 +462,7 @@ class RatboxIRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -409,120 +489,99 @@ class RatboxIRCdMessage : public IRCdMessage } }; -bool event_tburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTBurst : IRCDMessage { - if (params.size() != 4) - return true; - - Anope::string setter = myStrGetToken(params[2], '!', 0); - time_t topic_time = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime; - Channel *c = findchan(params[0]); + IRCDMessageTBurst() : IRCDMessage("TBURST", 4) { } - if (!c) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log() << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(setter, params.size() > 3 ? params[3] : "", topic_time); - - return true; -} - -bool event_kick(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 2) - do_kick(source, params[0], params[1], params[2]); - return true; -} + Anope::string setter = myStrGetToken(params[2], '!', 0); + time_t topic_time = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : Anope::CurTime; + Channel *c = findchan(params[0]); -bool event_sid(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :42X SID trystan.nomadirc.net 2 43X :ircd-ratbox test server */ - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[3], params[2]); - ircdproto->SendPing(Config->ServerName, params[0]); - return true; -} - -// Debug: Received: :00BAAAAAB ENCAP * LOGIN Adam -bool event_encap(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 2 && params[1] == "LOGIN") - { - User *u = finduser(source); - NickCore *nc = findcore(params[2]); - if (!u || !nc) + if (!c) return true; - u->Login(nc); - const NickAlias *user_na = findnick(u->nick); - if (!Config->NoNicknameOwnership && user_na && user_na->nc == nc && user_na->nc->HasFlag(NI_UNCONFIRMED) == false) - u->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } + c->ChangeTopicInternal(setter, params[3], topic_time); - return true; -} + return true; + } +}; -bool event_pong(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTMode : IRCDMessage { - Server *s = Server::Find(source); - if (s) - s->Sync(false); - return true; -} + IRCDMessageTMode() : IRCDMessage("TMODE", 3) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } -bool event_tmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params[1][0] == '#') + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { + time_t ts = Anope::CurTime; + try + { + ts = convertTo<time_t>(params[0]); + } + catch (const ConvertException &) { } + Channel *c = findchan(params[1]); Anope::string modes = params[2]; for (unsigned i = 3; i < params.size(); ++i) modes += " " + params[i]; - do_cmode(source, params[1], modes, params[0]); + + if (c) + c->SetModesInternal(source, modes, ts); + + return true; } - return true; -} +}; -bool event_pass(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageUID : IRCDMessage { - TS6UPLINK = params[3]; - return true; -} + IRCDMessageUID() : IRCDMessage("UID", 9) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } -bool event_bmask(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - /* :42X BMASK 1106409026 #ircops b :*!*@*.aol.com */ - /* 0 1 2 3 */ - Channel *c = findchan(params[1]); - - if (c) - { - ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), - *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), - *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); - Anope::string bans = params[3]; - int count = myNumToken(bans, ' '), i; - for (i = 0; i <= count - 1; ++i) - { - Anope::string b = myStrGetToken(bans, ' ', i); - if (ban && params[2].equals_cs("b")) - c->SetModeInternal(NULL, ban, b); - else if (except && params[2].equals_cs("e")) - c->SetModeInternal(NULL, except, b); - if (invex && params[2].equals_cs("I")) - c->SetModeInternal(NULL, invex, b); - } + // :42X UID Adam 1 1348535644 +aow Adam 192.168.0.5 192.168.0.5 42XAAAAAB :Adam + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + /* Source is always the server */ + User *user = new User(params[0], params[4], params[5], "", params[6], source.GetServer(), params[8], params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, params[3], params[7]); + if (user && user->server->IsSynced() && nickserv) + nickserv->Validate(user); + + return true; } - return true; -} +}; class ProtoRatbox : public Module { - Message message_kick, message_tmode, message_bmask, message_pass, message_tb, message_sid, message_encap, - message_pong; - RatboxProto ircd_proto; - RatboxIRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + + /* Our message handlers */ + IRCDMessageBMask message_bmask; + IRCDMessageEncap message_encap; + IRCDMessageJoin message_join; + IRCDMessageMode message_mode; + IRCDMessageNick message_nick; + IRCDMessagePass message_pass; + IRCDMessagePong message_pong; + IRCDMessageServer message_server; + IRCDMessageSID message_sid; + IRCDMessageSjoin message_sjoin; + IRCDMessageTBurst message_tburst; + IRCDMessageTMode message_tmode; + IRCDMessageUID message_uid; void AddModes() { @@ -554,18 +613,10 @@ class ProtoRatbox : public Module } public: - ProtoRatbox(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_kick("KICK", event_kick), message_tmode("TMODE", event_tmode), - message_bmask("BMASK", event_bmask), message_pass("PASS", event_pass), - message_tb("TB", event_tburst), message_sid("SID", event_sid), message_encap("ENCAP", event_encap), - message_pong("PONG", event_pong) + ProtoRatbox(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL) { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - this->AddModes(); Implementation i[] = { I_OnServerSync }; @@ -582,14 +633,6 @@ class ProtoRatbox : public Module it->second->GenerateUID(); } - ~ProtoRatbox() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - - void OnServerSync(Server *s) anope_override { if (nickserv) diff --git a/modules/protocol/unreal.cpp b/modules/protocol/unreal.cpp index 51e960fc0..59dd9ddd6 100644 --- a/modules/protocol/unreal.cpp +++ b/modules/protocol/unreal.cpp @@ -13,33 +13,24 @@ #include "module.h" -IRCDVar myIrcd = { - "UnrealIRCd 3.2.x", /* ircd name */ - "+Soiq", /* Modes used by pseudoclients */ - 1, /* SVSNICK */ - 1, /* Vhost */ - 1, /* Supports SNlines */ - 1, /* Supports SQlines */ - 1, /* Supports SZlines */ - 0, /* Join 2 Message */ - 0, /* Chan SQlines */ - 0, /* Quit on Kill */ - 1, /* vidents */ - 1, /* svshold */ - 1, /* time stamp on mode */ - 1, /* O:LINE */ - 1, /* UMODE */ - 1, /* No Knock requires +i */ - 1, /* Can remove User Channel Modes with SVSMODE */ - 0, /* Sglines are not enforced until user reconnects */ - 0, /* ts6 */ - "$", /* TLD Prefix for Global */ - 12, /* Max number of modes we can send per line */ - 0 /* IRCd sends a SSL users certificate fingerprint */ -}; - class UnrealIRCdProto : public IRCDProto { + public: + UnrealIRCdProto() : IRCDProto("UnrealIRCd 3.2.x") + { + DefaultPseudoclientModes = "+Soiq"; + CanSVSNick = true; + CanSetVHost = true; + CanSetVIdent = true; + CanSNLine = true; + CanSQLine = true; + CanSZLine = true; + CanSVSHold = true; + CanSVSO = true; + MaxModes = 12; + } + + private: /* SVSNOOP */ void SendSVSNOOP(const Server *server, bool set) anope_override { @@ -71,6 +62,16 @@ class UnrealIRCdProto : public IRCDProto UplinkSocket::Message(whosets) << ") " << c->name << " " << c->topic_setter << " " << c->topic_time + 1 << " :" << c->topic; } + void SendGlobalNotice(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "NOTICE $" << dest->GetName() << " :" << msg; + } + + void SendGlobalPrivmsg(const BotInfo *bi, const Server *dest, const Anope::string &msg) anope_override + { + UplinkSocket::Message(bi) << "PRIVMSG $" << dest->GetName() << " :" << msg; + } + void SendVhostDel(User *u) anope_override { const BotInfo *bi = findbot(Config->HostServ); @@ -248,9 +249,9 @@ class UnrealIRCdProto : public IRCDProto NS = Config->Numeric Server */ if (!Config->Numeric.empty()) - UplinkSocket::Message() << "PROTOCTL NICKv2 VHP UMODE2 NICKIP TOKEN SJOIN SJOIN2 SJ3 NOQUIT TKLEXT ESVID MLOCK VL"; + UplinkSocket::Message() << "PROTOCTL NICKv2 VHP UMODE2 NICKIP SJOIN SJOIN2 SJ3 NOQUIT TKLEXT ESVID MLOCK VL"; else - UplinkSocket::Message() << "PROTOCTL NICKv2 VHP UMODE2 NICKIP TOKEN SJOIN SJOIN2 SJ3 NOQUIT TKLEXT ESVID MLOCK"; + UplinkSocket::Message() << "PROTOCTL NICKv2 VHP UMODE2 NICKIP SJOIN SJOIN2 SJ3 NOQUIT TKLEXT ESVID MLOCK"; UplinkSocket::Message() << "PASS :" << Config->Uplinks[CurrentUplink]->password; SendServer(Me); } @@ -506,186 +507,11 @@ class ChannelModeUnrealSSL : public ChannelMode } }; -class Unreal32IRCdMessage : public IRCdMessage +struct IRCDMessageCapab : IRCDMessage { - public: - bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() < 2) - return true; - - bool server_source = Server::Find(source) != NULL; - Anope::string modes = params[1]; - for (unsigned i = 2; i < params.size() - (server_source ? 1 : 0); ++i) - modes += " " + params[i]; - - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], modes, server_source ? params[params.size() - 1] : ""); - else - do_umode(params[0], modes); - - return true; - } - - /* - ** NICK - new - ** source = NULL - ** parv[0] = nickname - ** parv[1] = hopcount - ** parv[2] = timestamp - ** parv[3] = username - ** parv[4] = hostname - ** parv[5] = servername - ** if NICK version 1: - ** parv[6] = servicestamp - ** parv[7] = info - ** if NICK version 2: - ** parv[6] = servicestamp - ** parv[7] = umodes - ** parv[8] = virthost, * if none - ** parv[9] = info - ** if NICKIP: - ** parv[9] = ip - ** parv[10] = info - ** - ** NICK - change - ** source = oldnick - ** parv[0] = new nickname - ** parv[1] = hopcount - */ - bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() == 7) - { - /* - <codemastr> that was a bug that is now fixed in 3.2.1 - <codemastr> in some instances it would use the non-nickv2 format - <codemastr> it's sent when a nick collision occurs - - so we have to leave it around for now -TSL - */ - do_nick(source, params[0], params[3], params[4], params[5], params[6], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, "", "*", "", ""); - } - else if (params.size() == 11) - { - Anope::string decoded_ip; - Anope::B64Decode(params[9], decoded_ip); - - sockaddrs ip; - ip.ntop(params[9].length() == 8 ? AF_INET : AF_INET6, decoded_ip.c_str()); - - Anope::string vhost = params[8]; - if (vhost.equals_cs("*")) - vhost.clear(); - - User *user = do_nick(source, params[0], params[3], params[4], params[5], params[10], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, ip.addr(), vhost, "", params[7]); - if (user) - { - const NickAlias *na = NULL; - - if (params[6] == "0") - ; - else if (params[6].is_pos_number_only()) - { - if (convertTo<time_t>(params[6]) == user->timestamp) - na = findnick(user->nick); - } - else - { - na = findnick(params[6]); - } - - if (na) - { - user->Login(na->nc); - if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) - user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - else if (nickserv) - nickserv->Validate(user); - } - } - else if (params.size() != 2) - { - Anope::string vhost = params[8]; - if (vhost.equals_cs("*")) - vhost.clear(); - - /* NON NICKIP */ - User *user = do_nick(source, params[0], params[3], params[4], params[5], params[9], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : 0, "", vhost, "", params[7]); - if (user) - { - const NickAlias *na = NULL; - - if (params[6] == "0") - ; - else if (params[6].is_pos_number_only()) - { - if (convertTo<time_t>(params[6]) == user->timestamp) - na = findnick(user->nick); - } - else - { - na = findnick(params[6]); - } - - if (na) - { - user->Login(na->nc); - if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) - user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); - } - else if (nickserv) - nickserv->Validate(user); - } - } - else - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); - - return true; - } - - bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override - { - if (params[1].equals_cs("1")) - { - Anope::string vl = myStrGetToken(params[2], ' ', 0); - Anope::string upnumeric = myStrGetToken(vl, '-', 2); - Anope::string desc = myStrGetTokenRemainder(params[2], ' ', 1); - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, desc, upnumeric); - } - else - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); + IRCDMessageCapab() : IRCDMessage("PROTOCTL", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } - ircdproto->SendPing(Config->ServerName, params[0]); - - return true; - } - - /* - ** source = sender prefix - ** parv[0] = channel name - ** parv[1] = topic nickname - ** parv[2] = topic time - ** parv[3] = topic text - */ - bool OnTopic(const Anope::string &, const std::vector<Anope::string> ¶ms) anope_override - { - if (params.size() != 4) - return true; - - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - - return true; - } - - bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { for (unsigned i = 0; i < params.size(); ++i) { @@ -832,12 +658,283 @@ class Unreal32IRCdMessage : public IRCdMessage } } - IRCdMessage::OnCapab(source, params); + return true; + } +}; + +struct IRCDMessageChgHost : IRCDMessage +{ + IRCDMessageChgHost() : IRCDMessage("CHGHOST", 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetDisplayedHost(params[1]); + return true; + } +}; + +struct IRCDMessageChgIdent : IRCDMessage +{ + IRCDMessageChgIdent() : IRCDMessage("CHGIDENT", 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetVIdent(params[1]); + return true; + } +}; + +struct IRCDMessageChgName : IRCDMessage +{ + IRCDMessageChgName() : IRCDMessage("CHGNAME", 2) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetRealname(params[1]); + return true; + } +}; + +struct IRCDMessageMode : IRCDMessage +{ + IRCDMessageMode(const Anope::string &mname) : IRCDMessage(mname, 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + bool server_source = source.GetServer() != NULL; + Anope::string modes = params[1]; + for (unsigned i = 2; i < params.size() - (server_source ? 1 : 0); ++i) + modes += " " + params[i]; + + if (ircdproto->IsChannelValid(params[0])) + { + Channel *c = findchan(params[0]); + time_t ts = Anope::CurTime; + try + { + if (server_source) + ts = convertTo<time_t>(params[params.size() - 1]); + } + catch (const ConvertException &) { } + + if (c) + c->SetModesInternal(source, modes, ts); + } + else + { + User *u = finduser(params[0]); + if (u) + u->SetModesInternal("%s", params[1].c_str()); + } + + return true; + } +}; + +/* netinfo + * argv[0] = max global count + * argv[1] = time of end sync + * argv[2] = unreal protocol using (numeric) + * argv[3] = cloak-crc (> u2302) + * argv[4] = free(**) + * argv[5] = free(**) + * argv[6] = free(**) + * argv[7] = ircnet + */ +struct IRCDMessageNetInfo : IRCDMessage +{ + IRCDMessageNetInfo() : IRCDMessage("NETINFO", 8) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + UplinkSocket::Message() << "AO " << maxusercnt << " " << Anope::CurTime << " " << convertTo<int>(params[2]) << " " << params[3] << " 0 0 0 :" << params[7]; + return true; + } +}; + +struct IRCDMessageNick : IRCDMessage +{ + IRCDMessageNick() : IRCDMessage("NICK", 2) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + /* + ** NICK - new + ** source = NULL + ** parv[0] = nickname + ** parv[1] = hopcount + ** parv[2] = timestamp + ** parv[3] = username + ** parv[4] = hostname + ** parv[5] = servername + ** parv[6] = servicestamp + ** parv[7] = umodes + ** parv[8] = virthost, * if none + ** parv[9] = ip + ** parv[10] = info + ** + ** NICK - change + ** source = oldnick + ** parv[0] = new nickname + ** parv[1] = hopcount + */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (params.size() == 11) + { + Anope::string decoded_ip; + Anope::B64Decode(params[9], decoded_ip); + + sockaddrs ip; + ip.ntop(params[9].length() == 8 ? AF_INET : AF_INET6, decoded_ip.c_str()); + + Anope::string vhost = params[8]; + if (vhost.equals_cs("*")) + vhost.clear(); + + time_t user_ts = params[2].is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime; + User *user = new User(params[0], params[3], params[4], vhost, ip.addr(), source.GetServer(), params[10], user_ts, params[7]); + + const NickAlias *na = NULL; + + if (params[6] == "0") + ; + else if (params[6].is_pos_number_only()) + { + if (convertTo<time_t>(params[6]) == user->timestamp) + na = findnick(user->nick); + } + else + { + na = findnick(params[6]); + } + + if (na) + { + user->Login(na->nc); + if (!Config->NoNicknameOwnership && na->nc->HasFlag(NI_UNCONFIRMED) == false && nickserv) + user->SetMode(findbot(Config->NickServ), UMODE_REGISTERED); + } + else if (nickserv) + nickserv->Validate(user); + } + else + source.GetUser()->ChangeNick(params[0]); + return true; } +}; - bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) anope_override +/** This is here because: + * + * If we had three servers, A, B & C linked like so: A<->B<->C + * If Anope is linked to A and B splits from A and then reconnects + * B introduces itself, introduces C, sends EOS for C, introduces Bs clients + * introduces Cs clients, sends EOS for B. This causes all of Cs clients to be introduced + * with their server "not syncing". We now send a PING immediately when receiving a new server + * and then finish sync once we get a pong back from that server. + */ +struct IRCDMessagePong : IRCDMessage +{ + IRCDMessagePong() : IRCDMessage("PONG", 0) { SetFlag(IRCDMESSAGE_SOFT_LIMIT); SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + if (!source.GetServer()->IsSynced()) + source.GetServer()->Sync(false); + return true; + } +}; + +struct IRCDMessageSDesc : IRCDMessage +{ + IRCDMessageSDesc() : IRCDMessage("SDESC", 1) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + source.GetServer()->SetDescription(params[0]); + return true; + } +}; + +struct IRCDMessageSetHost : IRCDMessage +{ + IRCDMessageSetHost() : IRCDMessage("SETHOST", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = source.GetUser(); + + /* When a user sets +x we recieve the new host and then the mode change */ + if (u->HasMode(UMODE_CLOAK)) + u->SetDisplayedHost(params[0]); + else + u->SetCloakedHost(params[0]); + + return true; + } +}; + +struct IRCDMessageSetIdent : IRCDMessage +{ + IRCDMessageSetIdent() : IRCDMessage("SETIDENT", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = source.GetUser(); + u->SetVIdent(params[0]); + return true; + } +}; + +struct IRCDMessageSetName : IRCDMessage +{ + IRCDMessageSetName() : IRCDMessage("STENAME", 1) { } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + User *u = finduser(params[0]); + if (u) + u->SetRealname(params[1]); + return true; + } +}; + +struct IRCDMessageServer : IRCDMessage +{ + IRCDMessageServer() : IRCDMessage("SERVER", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override + { + unsigned int hops = Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0; + + if (params[1].equals_cs("1")) + { + Anope::string vl = myStrGetToken(params[2], ' ', 0); + Anope::string upnumeric = myStrGetToken(vl, '-', 2); + Anope::string desc = myStrGetTokenRemainder(params[2], ' ', 1); + + new Server(source.GetServer() == NULL ? Me : source.GetServer(), params[0], hops, desc); + } + else + new Server(source.GetServer(), params[0], hops, params[2]); + + ircdproto->SendPing(Config->ServerName, params[0]); + + return true; + } +}; + +struct IRCDMessageSJoin : IRCDMessage +{ + IRCDMessageSJoin() : IRCDMessage("SJOIN", 3) { SetFlag(IRCDMESSAGE_REQUIRE_SERVER); SetFlag(IRCDMESSAGE_SOFT_LIMIT); } + + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { Channel *c = findchan(params[1]); time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; @@ -867,7 +964,7 @@ class Unreal32IRCdMessage : public IRCdMessage if (!modes.empty()) modes.erase(modes.begin()); /* Set the modes internally */ - c->SetModesInternal(NULL, modes); + c->SetModesInternal(source, modes); } ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), @@ -878,22 +975,25 @@ class Unreal32IRCdMessage : public IRCdMessage while (sep.GetToken(buf)) { /* Ban */ - if (keep_their_modes && ban && buf[0] == '&') + if (buf[0] == '&') { buf.erase(buf.begin()); - c->SetModeInternal(NULL, ban, buf); + if (keep_their_modes && ban) + c->SetModeInternal(source, ban, buf); } /* Except */ - else if (keep_their_modes && except && buf[0] == '"') + else if (buf[0] == '"') { buf.erase(buf.begin()); - c->SetModeInternal(NULL, except, buf); + if (keep_their_modes && except) + c->SetModeInternal(source, except, buf); } /* Invex */ - else if (keep_their_modes && invex && buf[0] == '\'') + else if (buf[0] == '\'') { buf.erase(buf.begin()); - c->SetModeInternal(NULL, invex, buf); + if (keep_their_modes && invex) + c->SetModeInternal(source, invex, buf); } else { @@ -932,7 +1032,7 @@ class Unreal32IRCdMessage : public IRCdMessage * This will enforce secureops etc on the user */ for (std::list<ChannelMode *>::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) - c->SetModeInternal(NULL, *it, buf); + c->SetModeInternal(source, *it, buf); /* Now set whatever modes this user is allowed to have on the channel */ chan_set_correct_modes(u, c, 1, true); @@ -960,184 +1060,78 @@ class Unreal32IRCdMessage : public IRCdMessage } }; - -/** This is here because: - * - * If we had three servers, A, B & C linked like so: A<->B<->C - * If Anope is linked to A and B splits from A and then reconnects - * B introduces itself, introduces C, sends EOS for C, introduces Bs clients - * introduces Cs clients, sends EOS for B. This causes all of Cs clients to be introduced - * with their server "not syncing". We now send a PING immediately when receiving a new server - * and then finish sync once we get a pong back from that server. - */ -bool event_pong(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - if (s && !s->IsSynced()) - s->Sync(false); - return true; -} - -/* netinfo - * argv[0] = max global count - * argv[1] = time of end sync - * argv[2] = unreal protocol using (numeric) - * argv[3] = cloak-crc (> u2302) - * argv[4] = free(**) - * argv[5] = free(**) - * argv[6] = free(**) - * argv[7] = ircnet - */ -bool event_netinfo(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - UplinkSocket::Message() << "AO " << maxusercnt << " " << Anope::CurTime << " " << convertTo<int>(params[2]) << " " << params[3] << " 0 0 0 :" << params[7]; - return true; -} - -/* Unreal sends USER modes with this */ -/* - umode2 - parv[0] - sender - parv[1] - modes to change -*/ -bool event_umode2(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 1) - return true; - - do_umode(source, params[0]); - return true; -} - - -bool event_setname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - return true; - - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETNAME for nonexistent user " << source; - return true; - } - - u->SetRealname(params[0]); - return true; -} - -bool event_chgname(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 2) - return true; - - User *u = finduser(params[0]); - if (!u) - { - Log(LOG_DEBUG) << "CHGNAME for nonexistent user " << params[0]; - return true; - } - - u->SetRealname(params[1]); - return true; -} - -bool event_setident(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - return true; - - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETIDENT for nonexistent user " << source; - return true; - } - - u->SetVIdent(params[0]); - return true; -} - -bool event_chgident(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageTopic : IRCDMessage { - if (params.size() != 2) - return true; + IRCDMessageTopic() : IRCDMessage("TOPIC", 4) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - User *u = finduser(params[0]); - if (!u) + /* + ** source = sender prefix + ** parv[0] = channel name + ** parv[1] = topic nickname + ** parv[2] = topic time + ** parv[3] = topic text + */ + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "CHGIDENT for nonexistent user " << params[0]; - return true; - } - - u->SetVIdent(params[1]); - return true; -} - -bool event_sethost(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - return true; + Channel *c = findchan(params[0]); + if (c) + c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); - User *u = finduser(source); - if (!u) - { - Log(LOG_DEBUG) << "SETHOST for nonexistent user " << source; return true; } +}; - /* When a user sets +x we recieve the new host and then the mode change */ - if (u->HasMode(UMODE_CLOAK)) - u->SetDisplayedHost(params[0]); - else - u->SetCloakedHost(params[0]); - - return true; -} -bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) +struct IRCDMessageUmode2 : IRCDMessage { - if (params.size() != 2) - return true; + IRCDMessageUmode2() : IRCDMessage("UMODE2", 1) { SetFlag(IRCDMESSAGE_REQUIRE_USER); } - User *u = finduser(params[0]); - if (!u) + bool Run(MessageSource &source, const std::vector<Anope::string> ¶ms) anope_override { - Log(LOG_DEBUG) << "debug: CHGHOST for nonexistent user " << params[0]; + source.GetUser()->SetModesInternal("%s", params[0].c_str()); return true; } - - u->SetDisplayedHost(params[1]); - return true; -} - -bool event_sdesc(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Server *s = Server::Find(source); - - if (s) - s->SetDescription(params[0]); - - return true; -} +}; class ProtoUnreal : public Module { - Message message_away, message_join, message_kick, - message_kill, message_mode, message_nick, message_part, - message_ping, message_pong, message_pong2, message_privmsg, - message_quit, message_server, message_squit, message_topic, - message_svsmode, message_svsmode2, message_svs2mode, message_svs2mode2, message_whois, - message_capab, message_capab2, message_chghost, message_chghost2, message_chgident, message_chgident2, - message_chgname, message_chgname2, message_netinfo, message_netinfo2, message_sethost, message_sethost2, - message_setident, message_setident2, message_setname, message_setname2, message_error, - message_umode2, message_umode22, message_sjoin, message_sdesc, message_sdesc2; - - /* Non-token of these in messages.cpp */ - Message message_stats, message_time, message_version; - UnrealIRCdProto ircd_proto; - Unreal32IRCdMessage ircd_message; + + /* Core message handlers */ + CoreIRCDMessageAway core_message_away; + CoreIRCDMessageCapab core_message_capab; + CoreIRCDMessageError core_message_error; + CoreIRCDMessageJoin core_message_join; + CoreIRCDMessageKill core_message_kill; + CoreIRCDMessageMOTD core_message_motd; + CoreIRCDMessagePart core_message_part; + CoreIRCDMessagePing core_message_ping; + CoreIRCDMessagePrivmsg core_message_privmsg; + CoreIRCDMessageQuit core_message_quit; + CoreIRCDMessageSQuit core_message_squit; + CoreIRCDMessageStats core_message_stats; + CoreIRCDMessageTime core_message_time; + CoreIRCDMessageTopic core_message_topic; + CoreIRCDMessageVersion core_message_version; + CoreIRCDMessageWhois core_message_whois; + + /* Our message handlers */ + IRCDMessageCapab message_capab; + IRCDMessageChgHost message_chghost; + IRCDMessageChgIdent message_chgident; + IRCDMessageChgName message_chgname; + IRCDMessageMode message_mode, message_svsmode, message_svs2mode; + IRCDMessageNetInfo message_netinfo; + IRCDMessageNick message_nick; + IRCDMessagePong message_pong; + IRCDMessageSDesc message_sdesc; + IRCDMessageSetHost message_sethost; + IRCDMessageSetIdent message_setident; + IRCDMessageSetName message_setname; + IRCDMessageServer message_server; + IRCDMessageSJoin message_sjoin; + IRCDMessageTopic message_topic; + IRCDMessageUmode2 message_umode2; void AddModes() { @@ -1179,37 +1173,10 @@ class ProtoUnreal : public Module public: ProtoUnreal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_away("6", OnAway), - message_join("C", OnJoin), - message_kick("H", OnKick), message_kill(".", OnKill), - message_mode("G", OnMode), - message_nick("&", OnNick), message_part("D", OnPart), - message_ping("8", OnPing), message_pong("PONG", event_pong), - message_pong2("9", event_pong), message_privmsg("!", ::OnPrivmsg), - message_quit(",", OnQuit), - message_server("'", OnServer), message_squit("-", OnSQuit), - message_topic(")", OnTopic), message_svsmode("SVSMODE", OnMode), - message_svsmode2("n", OnMode), message_svs2mode("SVS2MODE", OnMode), message_svs2mode2("v", OnMode), - message_whois("#", OnWhois), message_capab("PROTOCTL", OnCapab), - message_capab2("_", OnCapab), message_chghost("CHGHOST", event_chghost), message_chghost2("AL", event_chghost), - message_chgident("CHGIDENT", event_chgident), message_chgident2("AZ", event_chgident), - message_chgname("CHGNAME", event_chgname), message_chgname2("BK", event_chgname), - message_netinfo("NETINFO", event_netinfo), message_netinfo2("AO", event_netinfo), - message_sethost("SETHOST", event_sethost), message_sethost2("AA", event_sethost), - message_setident("SETIDENT", event_setident), message_setident2("AD", event_setident), - message_setname("SETNAME", event_setname), message_setname2("AE", event_setname), - message_error("5", OnError), message_umode2("UMODE2", event_umode2), - message_umode22("|", event_umode2), message_sjoin("~", OnSJoin), - message_sdesc("SDESC", event_sdesc), message_sdesc2("AG", event_sdesc), - - message_stats("2", OnStats), message_time(">", OnTime), message_version("+", OnVersion) + message_mode("MODE"), message_svsmode("SVSMODE"), message_svs2mode("SVS2MODE") { this->SetAuthor("Anope"); - pmodule_ircd_var(&myIrcd); - pmodule_ircd_proto(&this->ircd_proto); - pmodule_ircd_message(&this->ircd_message); - this->AddModes(); Implementation i[] = { I_OnUserNickChange, I_OnChannelCreate, I_OnChanRegistered, I_OnDelChan, I_OnMLock, I_OnUnMLock }; @@ -1217,14 +1184,6 @@ class ProtoUnreal : public Module ModuleManager::SetPriority(this, PRIORITY_FIRST); } - ~ProtoUnreal() - { - pmodule_ircd_var(NULL); - pmodule_ircd_proto(NULL); - pmodule_ircd_message(NULL); - } - - void OnUserNickChange(User *u, const Anope::string &) anope_override { u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED)); diff --git a/modules/pseudoclients/botserv.cpp b/modules/pseudoclients/botserv.cpp index beab46b23..d792f74da 100644 --- a/modules/pseudoclients/botserv.cpp +++ b/modules/pseudoclients/botserv.cpp @@ -199,7 +199,7 @@ class BotServCore : public Module "the following characters: %s"), Config->ChanServ.c_str(), Config->BSFantasyCharacter.c_str()); } - EventReturn OnChannelModeSet(Channel *c, User *setter, ChannelModeName Name, const Anope::string ¶m) anope_override + EventReturn OnChannelModeSet(Channel *c, MessageSource &, ChannelModeName Name, const Anope::string ¶m) anope_override { if (Config->BSSmartJoin && Name == CMODE_BAN && c->ci && c->ci->bi && c->FindUser(c->ci->bi)) { diff --git a/modules/pseudoclients/hostserv.cpp b/modules/pseudoclients/hostserv.cpp index c350903d0..33d183b9a 100644 --- a/modules/pseudoclients/hostserv.cpp +++ b/modules/pseudoclients/hostserv.cpp @@ -20,8 +20,8 @@ class HostServCore : public Module { this->SetAuthor("Anope"); - if (!ircd || !ircd->vhost) - throw ModuleException("Your IRCd does not suppor vhosts"); + if (!ircdproto || !ircdproto->CanSetVHost) + throw ModuleException("Your IRCd does not support vhosts"); const BotInfo *HostServ = findbot(Config->HostServ); if (HostServ == NULL) @@ -36,18 +36,17 @@ class HostServCore : public Module const NickAlias *na = findnick(u->nick); if (!na || !na->HasVhost()) na = findnick(u->Account()->display); - if (!na || !na->HasVhost()) + if (!ircdproto->CanSetVHost || !na || !na->HasVhost()) return; if (u->vhost.empty() || !u->vhost.equals_cs(na->GetVhostHost()) || (!na->GetVhostIdent().empty() && !u->GetVIdent().equals_cs(na->GetVhostIdent()))) { ircdproto->SendVhost(u, na->GetVhostIdent(), na->GetVhostHost()); - if (ircd->vhost) - { - u->vhost = na->GetVhostHost(); - u->UpdateHost(); - } - if (ircd->vident && !na->GetVhostIdent().empty()) + + u->vhost = na->GetVhostHost(); + u->UpdateHost(); + + if (ircdproto->CanSetVIdent && !na->GetVhostIdent().empty()) u->SetVIdent(na->GetVhostIdent()); const BotInfo *bi = findbot(Config->HostServ); diff --git a/modules/pseudoclients/operserv.cpp b/modules/pseudoclients/operserv.cpp index d9fa44597..b02120e91 100644 --- a/modules/pseudoclients/operserv.cpp +++ b/modules/pseudoclients/operserv.cpp @@ -37,7 +37,7 @@ class SGLineManager : public XLineManager { try { - if (!ircd->szline) + if (!ircdproto->CanSZLine) throw SocketException("SZLine is not supported"); else if (x->GetUser() != "*") throw SocketException("Can not ZLine a username"); @@ -236,7 +236,7 @@ class OperServCore : public Module void OnUserNickChange(User *u, const Anope::string &oldnick) anope_override { - if (ircd->sqline && !u->HasMode(UMODE_OPER)) + if (ircdproto->CanSQLine && !u->HasMode(UMODE_OPER)) this->sqlines.CheckAllXLines(u); } |
