diff options
author | Adam <Adam@anope.org> | 2010-12-06 17:06:57 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2010-12-12 19:37:03 -0500 |
commit | aed53dbb47822a79eb9a6b61095ad04ec3d67818 (patch) | |
tree | 72d3210b5609ea2163854d14ec7fb2f48d8b4d12 /modules/protocol | |
parent | a507816701d136a1c22d2f6779d811840d61577c (diff) |
Cleaned up some things, made the protocol modules use some basic inheritance to cut back on their code duplication. More work can be done in the future to remove even more of it.
Diffstat (limited to 'modules/protocol')
-rw-r--r-- | modules/protocol/bahamut.cpp | 512 | ||||
-rw-r--r-- | modules/protocol/inspircd-ts6.h | 413 | ||||
-rw-r--r-- | modules/protocol/inspircd11.cpp | 908 | ||||
-rw-r--r-- | modules/protocol/inspircd12.cpp | 1149 | ||||
-rw-r--r-- | modules/protocol/inspircd20.cpp | 1147 | ||||
-rw-r--r-- | modules/protocol/plexus.cpp | 436 | ||||
-rw-r--r-- | modules/protocol/ratbox.cpp | 449 | ||||
-rw-r--r-- | modules/protocol/unreal32.cpp | 960 |
8 files changed, 2471 insertions, 3503 deletions
diff --git a/modules/protocol/bahamut.cpp b/modules/protocol/bahamut.cpp index 7c0a23112..0dc409b29 100644 --- a/modules/protocol/bahamut.cpp +++ b/modules/protocol/bahamut.cpp @@ -287,366 +287,263 @@ class BahamutIRCdProto : public IRCDProto ircdproto->SendMode(NickServ, u, "+d %d", u->timestamp); } -} ircd_proto; +}; -/* EVENT: SJOIN */ -bool event_sjoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) +class BahamutIRCdMessage : public IRCdMessage { - Channel *c = findchan(params[1]); - time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; - bool keep_their_modes = false; - - if (!c) + public: + bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - c = new Channel(params[1], ts); - c->SetFlag(CH_SYNCING); + if (params.size() < 3) + return true; + + if (params[0][0] == '#' || params[0][0] == '&') + do_cmode(source, params[0], params[2], params[1]); + else + do_umode(source, params[0], params[1]); + + return true; } - /* Our creation time is newer than what the server gave us */ - else if (c->creation_time > ts) + + /* + ** 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) { - c->creation_time = ts; - c->Reset(); + if (params.size() != 2) + { + 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, params[8], "", "", params[3]); + if (user) + { + NickAlias *na; + if (user->timestamp == convertTo<time_t>(params[7]) && (na = findnick(user->nick))) + { + user->Login(na->nc); + user->SetMode(NickServ, UMODE_REGISTERED); + } + else + validate_user(user); + } + } + else + do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); - /* Reset mlock */ - check_modes(c); + return true; } - /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ - else if (ts > c->creation_time) - keep_their_modes = false; - /* If we need to keep their modes, and this SJOIN string contains modes */ - if (keep_their_modes && params.size() >= 4) + bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - /* Set the modes internally */ - Anope::string modes; - for (unsigned i = 2; i < params.size(); ++i) - modes += " " + params[i]; - if (!modes.empty()) - modes.erase(modes.begin()); - c->SetModesInternal(NULL, modes); + do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); + return true; } - /* For a reason unknown to me, bahamut will send a SJOIN from the user joining a channel - * if the channel already existed - */ - if (!c->HasFlag(CH_SYNCING) && params.size() == 2) + bool OnTopic(const Anope::string &, const std::vector<Anope::string> ¶ms) { - User *u = finduser(source); - if (!u) - Log(LOG_DEBUG) << "SJOIN for nonexistant user " << source << " on " << c->name; - else + if (params.size() < 4) + return true; + + Channel *c = findchan(params[0]); + if (!c) { - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, 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; + } - /* Add the user to the channel */ - c->JoinUser(u); + bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) + { + Channel *c = findchan(params[1]); + time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; + bool keep_their_modes = false; - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1); + if (!c) + { + c = new Channel(params[1], ts); + c->SetFlag(CH_SYNCING); + } + /* Our creation time is newer than what the server gave us */ + else if (c->creation_time > ts) + { + c->creation_time = ts; + c->Reset(); + + /* Reset mlock */ + check_modes(c); + } + /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ + else if (ts > c->creation_time) + keep_their_modes = false; - /* 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))) + /* If we need to keep their modes, and this SJOIN string contains modes */ + if (keep_their_modes && params.size() >= 4) + { + /* Set the modes internally */ + Anope::string modes; + for (unsigned i = 2; i < params.size(); ++i) + modes += " " + params[i]; + if (!modes.empty()) + modes.erase(modes.begin()); + c->SetModesInternal(NULL, modes); + } + + /* For some reason, bahamut will send a SJOIN from the user joining a channel + * if the channel already existed + */ + 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 { - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); + + /* Add the user to the channel */ + c->JoinUser(u); + + /* Now set whatever modes this user is allowed to have on the channel */ + chan_set_correct_modes(u, c, 1); + + /* 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 - { - spacesepstream sep(params[params.size() - 1]); - Anope::string buf; - while (sep.GetToken(buf)) + else { - std::list<ChannelMode *> Status; - char ch; - - /* Get prefixes from the nick */ - while ((ch = ModeManager::GetStatusChar(buf[0]))) + spacesepstream sep(params[params.size() - 1]); + Anope::string buf; + while (sep.GetToken(buf)) { - buf.erase(buf.begin()); - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); - if (!cm) + std::list<ChannelMode *> Status; + char ch; + + /* Get prefixes from the nick */ + while ((ch = ModeManager::GetStatusChar(buf[0]))) { - Log() << "Receeved unknown mode prefix " << buf[0] << " in SJOIN string"; - continue; + buf.erase(buf.begin()); + ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); + if (!cm) + { + Log() << "Receeved unknown mode prefix " << buf[0] << " in SJOIN string"; + continue; + } + + if (keep_their_modes) + Status.push_back(cm); } - if (keep_their_modes) - Status.push_back(cm); - } + User *u = finduser(buf); + if (!u) + { + Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name; + continue; + } - User *u = finduser(buf); - if (!u) - { - Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name; - continue; - } + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); + /* Add the user to the channel */ + c->JoinUser(u); - /* Add the user to the channel */ - c->JoinUser(u); + /* Update their status internally on the channel + * 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(*it, buf); - /* Update their status internally on the channel - * 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(*it, buf); + /* Now set whatever modes this user is allowed to have on the channel */ + chan_set_correct_modes(u, c, 1); - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1); + /* 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)) + continue; - /* 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)) - continue; + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); + } + } - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); + /* Channel is done syncing */ + if (c->HasFlag(CH_SYNCING)) + { + /* Unset the syncing flag */ + c->UnsetFlag(CH_SYNCING); + c->Sync(); } - } - /* Channel is done syncing */ - if (c->HasFlag(CH_SYNCING)) - { - /* Unset the syncing flag */ - c->UnsetFlag(CH_SYNCING); - c->Sync(); + return 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 event_nick(const Anope::string &source, const std::vector<Anope::string> ¶ms) +static bool event_xs(BotInfo *bi, const Anope::string &source, const std::vector<Anope::string> ¶ms) { - User *user; - - if (params.size() != 2) + if (!params.empty() && bi) { - 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, params[8], "", "", params[3]); - if (user) - { - NickAlias *na; - if (user->timestamp == convertTo<time_t>(params[7]) && (na = findnick(user->nick))) - { - user->Login(na->nc); - user->SetMode(NickServ, UMODE_REGISTERED); - } - else - validate_user(user); - } + std::vector<Anope::string> p; + p.push_back(bi->nick); + p.push_back(params[0]); + return ircdmessage->OnPrivmsg(source, p); } - else - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); - return true; -} -/* EVENT : CAPAB */ -bool event_capab(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - CapabParse(params); return true; } /* EVENT : OS */ bool event_os(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - if (!params.empty()) - m_privmsg(source, Config->s_OperServ, params[0]); - return true; + return event_xs(OperServ, source, params); } /* EVENT : NS */ bool event_ns(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - if (!params.empty()) - m_privmsg(source, Config->s_NickServ, params[0]); - return true; + return event_xs(NickServ, source, params); } /* EVENT : MS */ bool event_ms(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - if (!params.empty()) - m_privmsg(source, Config->s_MemoServ, params[0]); - return true; + return event_xs(MemoServ, source, params); } /* EVENT : HS */ bool event_hs(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - if (!params.empty()) - m_privmsg(source, Config->s_HostServ, params[0]); - return true; + return event_xs(HostServ, source, params); } /* EVENT : CS */ bool event_cs(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - if (!params.empty()) - m_privmsg(source, Config->s_ChanServ, params[0]); - return true; -} - -bool event_436(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - m_nickcoll(params[0]); - return true; -} - -/* EVENT : SERVER */ -bool event_server(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); - return true; -} - -/* EVENT : PRIVMSG */ -bool event_privmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 1) - m_privmsg(source, params[0], params[1]); - return true; -} - -bool event_part(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_part(source, params[0], params.size() > 1 ? params[1] : ""); - return true; -} - -bool event_whois(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!source.empty() && params.size() > 0) - m_whois(source, params[0]); - return true; -} - -bool event_topic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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 event_squit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 0) - do_squit(source, params[0]); - return true; -} - -bool event_quit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 0) - do_quit(source, params[0]); - return true; -} - -/* EVENT: MODE */ -bool event_mode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 3) - return true; - - if (params[0][0] == '#' || params[0][0] == '&') - do_cmode(source, params[0], params[2], params[1]); - else - do_umode(source, params[0], params[1]); - return true; -} - -/* EVENT: KILL */ -bool event_kill(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 1) - m_kill(params[0], params[1]); - return true; -} - -/* EVENT: KICK */ -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; -} - -/* EVENT: JOIN */ -bool event_join(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() >= 2) - do_join(source, params[0], params[1]); - return true; -} - -/* EVENT: MOTD */ -bool event_motd(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (source.empty()) - return true; - - m_motd(source); - return true; -} - -bool event_away(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (source.empty()) - return true; - m_away(source, !params.empty() ? params[0] : ""); - return true; -} - -bool event_ping(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 1) - return true; - ircdproto->SendPong(params.size() > 1 ? params[1] : Config->ServerName, params[0]); - return true; -} - -bool event_error(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 0) - Log(LOG_DEBUG) << params[0]; - return true; + return event_xs(ChanServ, source, params); } bool event_burst(const Anope::string &source, const std::vector<Anope::string> ¶ms) @@ -719,34 +616,29 @@ static void AddModes() class ProtoBahamut : public Module { - Message message_436, message_away, message_join, message_kick, message_kill, message_mode, message_motd, message_nick, - message_part, message_ping, message_privmsg, message_quit, message_server, message_squit, message_topic, message_whois, - message_svsmode, message_capab, message_cs, message_hs, message_ms, message_ns, message_os, message_sjoin, message_error, - message_burst; + Message message_svsmode, message_cs, message_hs, message_ms, message_ns, message_os, message_burst; + + BahamutIRCdProto ircd_proto; + BahamutIRCdMessage ircd_message; + public: ProtoBahamut(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), - message_436("436", event_436), message_away("AWAY", event_away), message_join("JOIN", event_join), - message_kick("KICK", event_kick), message_kill("KILL", event_kill), message_mode("MODE", event_mode), - message_motd("MOTD", event_motd), message_nick("NICK", event_nick), message_part("PART", event_part), - message_ping("PING", event_ping), message_privmsg("PRIVMSG", event_privmsg), message_quit("QUIT", event_quit), - message_server("SERVER", event_server), message_squit("SQUIT", event_squit), message_topic("TOPIC", event_topic), - message_whois("WHOIS", event_whois), message_svsmode("SVSMODE", event_mode), message_capab("CAPAB", event_capab), - message_cs("CS", event_cs), message_hs("HS", event_hs), message_ms("MS", event_ms), message_ns("NS", event_ns), - message_os("OS", event_os), message_sjoin("SJOIN", event_sjoin), message_error("ERROR", event_error), + message_svsmode("SVSMODE", OnMode), message_cs("CS", event_cs), message_hs("HS", event_hs), + message_ms("MS", event_ms), message_ns("NS", event_ns), message_os("OS", event_os), message_burst("BURST", event_burst) { this->SetAuthor("Anope"); this->SetType(PROTOCOL); - pmodule_ircd_var(myIrcd); - CapabType c[] = { CAPAB_NOQUIT, CAPAB_TSMODE, CAPAB_UNCONNECT, CAPAB_BURST, CAPAB_DKEY, CAPAB_DOZIP }; for (unsigned i = 0; i < 6; ++i) Capab.SetFlag(c[i]); AddModes(); - pmodule_ircd_proto(&ircd_proto); + pmodule_ircd_var(myIrcd); + pmodule_ircd_proto(&this->ircd_proto); + pmodule_ircd_message(&this->ircd_message); ModuleManager::Attach(I_OnUserNickChange, this); } diff --git a/modules/protocol/inspircd-ts6.h b/modules/protocol/inspircd-ts6.h new file mode 100644 index 000000000..1859fff08 --- /dev/null +++ b/modules/protocol/inspircd-ts6.h @@ -0,0 +1,413 @@ +/* Inspircd 1.2+ generic TS6 functions + * + * (C) 2003-2010 Anope Team + * Contact us at team@anope.org + * + * Please read COPYING and README for further details. + * + * Based on the original code of Epona by Lara. + * Based on the original code of Services by Andy Church. + */ + +class InspIRCdTS6Proto : public IRCDProto +{ + private: + void SendChgIdentInternal(const Anope::string &nick, const Anope::string &vIdent) + { + if (!has_chgidentmod) + ircdproto->SendGlobops(OperServ, "CHGIDENT not loaded!"); + else + send_cmd(HostServ ? HostServ->GetUID() : Config->Numeric, "CHGIDENT %s %s", nick.c_str(), vIdent.c_str()); + } + + void SendChgHostInternal(const Anope::string &nick, const Anope::string &vhost) + { + if (!has_chghostmod) + ircdproto->SendGlobops(OperServ, "CHGHOST not loaded!"); + else + send_cmd(HostServ ? HostServ->GetUID() : Config->Numeric, "CHGHOST %s %s", nick.c_str(), vhost.c_str()); + } + + public: + + void SendAkillDel(const XLine *x) + { + send_cmd(OperServ ? OperServ->GetUID() : Config->Numeric, "GLINE %s", x->Mask.c_str()); + } + + void SendTopic(BotInfo *whosets, Channel *c) + { + send_cmd(whosets->GetUID(), "FTOPIC %s %lu %s :%s", c->name.c_str(), static_cast<unsigned long>(c->topic_time + 1), c->topic_setter.c_str(), c->topic.c_str()); + } + + void SendVhostDel(User *u) + { + if (u->HasMode(UMODE_CLOAK)) + this->SendChgHostInternal(u->nick, u->chost); + else + this->SendChgHostInternal(u->nick, u->host); + + if (has_chgidentmod && u->GetIdent() != u->GetVIdent()) + this->SendChgIdentInternal(u->nick, u->GetIdent()); + } + + void SendAkill(const XLine *x) + { + // Calculate the time left before this would expire, capping it at 2 days + time_t timeleft = x->Expires - Anope::CurTime; + if (timeleft > 172800 || !x->Expires) + timeleft = 172800; + send_cmd(OperServ ? OperServ->GetUID() : Config->Numeric, "ADDLINE G %s@%s %s %ld %ld :%s", x->GetUser().c_str(), x->GetHost().c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime), static_cast<long>(timeleft), x->Reason.c_str()); + } + + void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) + { + send_cmd(source ? source->GetUID() : Config->Numeric, "KILL %s :%s", user->GetUID().c_str(), buf.c_str()); + } + + void SendSVSMode(const User *u, int ac, const char **av) + { + this->SendModeInternal(NULL, u, merge_args(ac, av)); + } + + void SendNumericInternal(const Anope::string &source, int numeric, const Anope::string &dest, const Anope::string &buf) + { + send_cmd(Config->Numeric, "PUSH %s ::%s %03d %s %s", dest.c_str(), source.c_str(), numeric, dest.c_str(), buf.c_str()); + } + + void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) + { + send_cmd(source ? source->GetUID() : Config->Numeric, "FMODE %s %u %s", dest->name.c_str(), static_cast<unsigned>(dest->creation_time), buf.c_str()); + } + + void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) + { + if (buf.empty()) + return; + send_cmd(bi ? bi->GetUID() : Config->Numeric, "MODE %s %s", u->GetUID().c_str(), buf.c_str()); + } + + void SendClientIntroduction(const User *u, const Anope::string &modes) + { + send_cmd(Config->Numeric, "UID %s %ld %s %s %s %s 0.0.0.0 %ld %s :%s", u->GetUID().c_str(), static_cast<long>(u->timestamp), u->nick.c_str(), u->host.c_str(), u->host.c_str(), u->GetIdent().c_str(), static_cast<long>(u->my_signon), modes.c_str(), u->realname.c_str()); + } + + void SendKickInternal(const BotInfo *source, const Channel *chan, const User *user, const Anope::string &buf) + { + if (!buf.empty()) + send_cmd(source->GetUID(), "KICK %s %s :%s", chan->name.c_str(), user->GetUID().c_str(), buf.c_str()); + else + send_cmd(source->GetUID(), "KICK %s %s :%s", chan->name.c_str(), user->GetUID().c_str(), user->nick.c_str()); + } + + void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) + { + send_cmd(Config->Numeric, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); + } + + /* SERVER services-dev.chatspike.net password 0 :Description here */ + void SendServer(const Server *server) + { + send_cmd("", "SERVER %s %s %d %s :%s", server->GetName().c_str(), uplink_server ? uplink_server->password.c_str() : "none", server->GetHops(), server->GetSID().c_str(), server->GetDescription().c_str()); + } + + /* JOIN */ + void SendJoin(const BotInfo *user, const Anope::string &channel, time_t chantime) + { + send_cmd(Config->Numeric, "FJOIN %s %ld + :,%s", channel.c_str(), static_cast<long>(chantime), user->GetUID().c_str()); + } + + void SendJoin(BotInfo *user, const ChannelContainer *cc) + { + send_cmd(Config->Numeric, "FJOIN %s %ld +%s :%s,%s", cc->chan->name.c_str(), static_cast<long>(cc->chan->creation_time), cc->chan->GetModes(true, true).c_str(), cc->Status->BuildCharPrefixList().c_str(), user->GetUID().c_str()); + } + + /* UNSQLINE */ + void SendSQLineDel(const XLine *x) + { + send_cmd(Config->Numeric, "DELLINE Q %s", x->Mask.c_str()); + } + + /* SQLINE */ + void SendSQLine(const XLine *x) + { + send_cmd(Config->Numeric, "ADDLINE Q %s %s %ld 0 :%s", x->Mask.c_str(), Config->s_OperServ.c_str(), static_cast<long>(Anope::CurTime), x->Reason.c_str()); + } + + /* SQUIT */ + void SendSquit(const Anope::string &servname, const Anope::string &message) + { + send_cmd(Config->Numeric, "SQUIT %s :%s", servname.c_str(), message.c_str()); + } + + /* Functions that use serval cmd functions */ + + void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) + { + if (!vIdent.empty()) + this->SendChgIdentInternal(u->nick, vIdent); + if (!vhost.empty()) + this->SendChgHostInternal(u->nick, vhost); + } + + void SendConnect() + { + SendServer(Me); + send_cmd(Config->Numeric, "BURST"); + send_cmd(Config->Numeric, "VERSION :Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircd->name, Config->EncModuleList.begin()->c_str(), Anope::Build().c_str()); + } + + /* SVSHOLD - set */ + void SendSVSHold(const Anope::string &nick) + { + send_cmd(NickServ->GetUID(), "SVSHOLD %s %u :Being held for registered user", nick.c_str(), static_cast<unsigned>(Config->NSReleaseTimeout)); + } + + /* SVSHOLD - release */ + void SendSVSHoldDel(const Anope::string &nick) + { + send_cmd(NickServ->GetUID(), "SVSHOLD %s", nick.c_str()); + } + + /* UNSZLINE */ + void SendSZLineDel(const XLine *x) + { + send_cmd(Config->Numeric, "DELLINE Z %s", x->Mask.c_str()); + } + + /* SZLINE */ + void SendSZLine(const XLine *x) + { + send_cmd(Config->Numeric, "ADDLINE Z %s %s %ld 0 :%s", x->Mask.c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime), x->Reason.c_str()); + } + + void SendSVSJoin(const Anope::string &source, const Anope::string &nick, const Anope::string &chan, const Anope::string &) + { + User *u = finduser(nick); + BotInfo *bi = findbot(source); + send_cmd(bi->GetUID(), "SVSJOIN %s %s", u->GetUID().c_str(), chan.c_str()); + } + + void SendSVSPart(const Anope::string &source, const Anope::string &nick, const Anope::string &chan) + { + User *u = finduser(nick); + BotInfo *bi = findbot(source); + send_cmd(bi->GetUID(), "SVSPART %s %s", u->GetUID().c_str(), chan.c_str()); + } + + void SendSWhois(const Anope::string &, const Anope::string &who, const Anope::string &mask) + { + User *u = finduser(who); + + send_cmd(Config->Numeric, "METADATA %s swhois :%s", u->GetUID().c_str(), mask.c_str()); + } + + void SendBOB() + { + send_cmd(Config->Numeric, "BURST %ld", static_cast<long>(Anope::CurTime)); + } + + void SendEOB() + { + send_cmd(Config->Numeric, "ENDBURST"); + } + + void SendGlobopsInternal(BotInfo *source, const Anope::string &buf) + { + if (has_globopsmod) + send_cmd(source ? source->GetUID() : Config->Numeric, "SNONOTICE g :%s", buf.c_str()); + else + send_cmd(source ? source->GetUID() : Config->Numeric, "SNONOTICE A :%s", buf.c_str()); + } + + void SendAccountLogin(const User *u, const NickCore *account) + { + send_cmd(Config->Numeric, "METADATA %s accountname :%s", u->GetUID().c_str(), account->display.c_str()); + } + + void SendAccountLogout(const User *u, const NickCore *account) + { + send_cmd(Config->Numeric, "METADATA %s accountname :", u->GetUID().c_str()); + } + + bool IsNickValid(const Anope::string &nick) + { + /* InspIRCd, like TS6, uses UIDs on collision, so... */ + if (isdigit(nick[0])) + return false; + + return true; + } +}; + +class InspircdIRCdMessage : public IRCdMessage +{ + public: + bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) + { + 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); + User *u2 = finduser(params[0]); + + // This can happen with server-origin modes. + if (!u) + u = u2; + + // if it's still null, drop it like fire. + // most likely situation was that server introduced a nick which we subsequently akilled + if (!u || !u2) + return true; + + do_umode(u->nick, u2->nick, params[1]); + } + + return true; + } + + bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) + { + do_nick(source, params[0], "", "", "", "", 0, "", "", "", ""); + return true; + } + + /* + * [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) + { + do_server(source, params[0], Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0, params[4], params[3]); + return true; + } + + bool OnTopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) + { + 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); + + return true; + } + + virtual bool OnCapab(const Anope::string &, const std::vector<Anope::string> &) = 0; + + bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) + { + Channel *c = findchan(params[0]); + time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; + bool keep_their_modes = true; + + if (!c) + { + c = new Channel(params[0], ts); + c->SetFlag(CH_SYNCING); + } + /* Our creation time is newer than what the server gave us */ + else if (c->creation_time > ts) + { + c->creation_time = ts; + c->Reset(); + + /* Reset mlock */ + check_modes(c); + } + /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ + else if (ts > c->creation_time) + keep_their_modes = false; + + /* If we need to keep their modes, and this FJOIN string contains modes */ + if (keep_their_modes && params.size() >= 3) + { + Anope::string modes; + for (unsigned i = 2; i < params.size() - 1; ++i) + modes += " " + params[i]; + if (!modes.empty()) + modes.erase(modes.begin()); + /* Set the modes internally */ + c->SetModesInternal(NULL, modes); + } + + spacesepstream sep(params[params.size() - 1]); + Anope::string buf; + while (sep.GetToken(buf)) + { + std::list<ChannelMode *> Status; + + /* Loop through prefixes and find modes for them */ + while (buf[0] != ',') + { + ChannelMode *cm = ModeManager::FindChannelModeByChar(buf[0]); + if (!cm) + { + Log() << "Receeved unknown mode prefix " << buf[0] << " in FJOIN string"; + buf.erase(buf.begin()); + continue; + } + + buf.erase(buf.begin()); + if (keep_their_modes) + Status.push_back(cm); + } + buf.erase(buf.begin()); + + User *u = finduser(buf); + if (!u) + { + Log(LOG_DEBUG) << "FJOIN for nonexistant user " << buf << " on " << c->name; + continue; + } + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); + + /* Add the user to the channel */ + c->JoinUser(u); + + /* Update their status internally on the channel + * 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(*it, buf); + + /* Now set whatever modes this user is allowed to have on the channel */ + chan_set_correct_modes(u, c, 1); + + /* 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)) + continue; + + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); + } + + /* Channel is done syncing */ + if (c->HasFlag(CH_SYNCING)) + { + /* Unset the syncing flag */ + c->UnsetFlag(CH_SYNCING); + c->Sync(); + } + + return true; + } +}; + diff --git a/modules/protocol/inspircd11.cpp b/modules/protocol/inspircd11.cpp index f6326a7dc..267ec21f4 100644 --- a/modules/protocol/inspircd11.cpp +++ b/modules/protocol/inspircd11.cpp @@ -13,7 +13,6 @@ #include "services.h" #include "modules.h" -#include "hashcomp.h" IRCDVar myIrcd[] = { {"InspIRCd 1.1", /* ircd name */ @@ -291,7 +290,395 @@ class InspIRCdProto : public IRCDProto u->Account()->Extend("authenticationtoken", new ExtensibleItemRegular<Anope::string>(svidbuf)); } -} ircd_proto; +}; + +class InspircdIRCdMessage : public IRCdMessage +{ + public: + bool OnMode(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[1], params[2]); + else + { + /* InspIRCd lets opers change another + users modes + */ + do_umode(source, params[0], params[1]); + } + + return true; + } + + bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) + { + 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) + { + user->SetCloakedHost(params[3]); + + NickAlias *na = findnick(user->nick); + Anope::string svidbuf; + if (na && na->nc->GetExtRegular("authenticationtoken", svidbuf) && svidbuf == params[0]) + { + user->Login(na->nc); + user->SetMode(NickServ, UMODE_REGISTERED); + } + else + validate_user(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) + { + 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) + { + Channel *c = findchan(params[0]); + + if (!c) + { + Log() << "TOPIC " << (params.size() > 1 ? params[1] : "") << " for nonexistent channel " << params[0]; + return true; + } + + c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : ""), Anope::CurTime); + + return true; + } + + bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) + { + if (params[0].equals_cs("START")) + { + /* reset CAPAB */ + has_servicesmod = false; + has_globopsmod = false; + has_svsholdmod = false; + has_chghostmod = false; + has_chgidentmod = false; + has_hidechansmod = false; + } + else if (params[0].equals_cs("MODULES")) + { + if (params[1].find("m_globops.so") != Anope::string::npos) + has_globopsmod = true; + if (params[1].find("m_services.so") != Anope::string::npos) + has_servicesmod = true; + if (params[1].find("m_svshold.so") != Anope::string::npos) + has_svsholdmod = true; + if (params[1].find("m_chghost.so") != Anope::string::npos) + has_chghostmod = true; + if (params[1].find("m_chgident.so") != Anope::string::npos) + has_chgidentmod = true; + if (params[1].find("m_hidechans.so") != Anope::string::npos) + has_hidechansmod = true; + } + else if (params[0].equals_cs("CAPABILITIES")) + { + spacesepstream ssep(params[1]); + Anope::string capab; + while (ssep.GetToken(capab)) + { + if (capab.find("CHANMODES") != Anope::string::npos) + { + Anope::string modes(capab.begin() + 10, capab.end()); + commasepstream sep(modes); + Anope::string modebuf; + + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + switch (modebuf[t]) + { + case 'b': + ModeManager::AddChannelMode(new ChannelModeBan('b')); + continue; + case 'e': + ModeManager::AddChannelMode(new ChannelModeExcept('e')); + continue; + case 'I': + ModeManager::AddChannelMode(new ChannelModeInvex('I')); + continue; + default: + ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, "", modebuf[t])); + } + } + + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + switch (modebuf[t]) + { + case 'k': + ModeManager::AddChannelMode(new ChannelModeKey('k')); + continue; + default: + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t])); + } + } + + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + switch (modebuf[t]) + { + case 'f': + ModeManager::AddChannelMode(new ChannelModeFlood('f')); + continue; + case 'l': + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, "CMODE_LIMIT", 'l', true)); + continue; + case 'L': + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_REDIRECT, "CMODE_REDIRECT", 'L', true)); + continue; + default: + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t], true)); + } + } + + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + switch (modebuf[t]) + { + case 'i': + ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, "CMODE_INVITE", 'i')); + continue; + case 'm': + ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, "CMODE_MODERATED", 'm')); + continue; + case 'n': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, "CMODE_NOEXTERNAL", 'n')); + continue; + case 'p': + ModeManager::AddChannelMode(new ChannelMode(CMODE_PRIVATE, "CMODE_PRIVATE", 'p')); + continue; + case 's': + ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, "CMODE_SECRET", 's')); + continue; + case 't': + ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, "CMODE_TOPIC", 't')); + continue; + case 'r': + ModeManager::AddChannelMode(new ChannelModeRegistered('r')); + continue; + case 'c': + ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, "CMODE_BLOCKCOLOR", 'c')); + continue; + case 'u': + ModeManager::AddChannelMode(new ChannelMode(CMODE_AUDITORIUM, "CMODE_AUDITORIUM", 'u')); + continue; + case 'z': + ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, "CMODE_SSL", 'z')); + continue; + case 'A': + ModeManager::AddChannelMode(new ChannelMode(CMODE_ALLINVITE, "CMODE_ALLINVITE", 'A')); + continue; + case 'C': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOCTCP, "CMODE_NOCTCP", 'C')); + continue; + case 'G': + ModeManager::AddChannelMode(new ChannelMode(CMODE_FILTER, "CMODE_FILTER", 'G')); + continue; + case 'K': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKNOCK, "CMODE_NOKNOCK", 'K')); + continue; + case 'N': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NONICK, "CMODE_NONICK", 'N')); + continue; + case 'O': + ModeManager::AddChannelMode(new ChannelModeOper('O')); + continue; + case 'Q': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKICK, "CMODE_NOKICK", 'Q')); + continue; + case 'R': + ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, "CMODE_REGISTEREDONLY", 'R')); + continue; + case 'S': + ModeManager::AddChannelMode(new ChannelMode(CMODE_STRIPCOLOR, "CMODE_STRIPCOLOR", 'S')); + continue; + case 'V': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOINVITE, "CMODE_NOINVITE", 'V')); + continue; + default: + ModeManager::AddChannelMode(new ChannelMode(CMODE_END, "", modebuf[t])); + } + } + } + else if (capab.find("PREIX=(") != Anope::string::npos) + { + Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')')); + Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end()); + + for (size_t t = 0, end = modes.length(); t < end; ++t) + { + switch (modes[t]) + { + case 'q': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, "CMODE_OWNER", 'q', '~')); + continue; + case 'a': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, "CMODE_PROTECT", 'a', '&')); + continue; + case 'o': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, "CMODE_OP", 'o', '@')); + continue; + case 'h': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, "CMODE_HALFOP", 'h', '%')); + continue; + case 'v': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, "CMODE_VOICE", 'v', '+')); + continue; + } + } + } + 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; + } + } + } + else if (params[0].equals_cs("END")) + { + if (!has_globopsmod) + { + send_cmd("", "ERROR :m_globops is not loaded. This is required by Anope"); + quitmsg = "ERROR: Remote server does not have the m_globops module loaded, and this is required."; + quitting = true; + return MOD_STOP; + } + if (!has_servicesmod) + { + send_cmd("", "ERROR :m_services is not loaded. This is required by Anope"); + quitmsg = "ERROR: Remote server does not have the m_services module loaded, and this is required."; + quitting = true; + return MOD_STOP; + } + if (!has_hidechansmod) + { + send_cmd("", "ERROR :m_hidechans.so is not loaded. This is required by Anope"); + quitmsg = "ERROR: Remote server deos not have the m_hidechans module loaded, and this is required."; + quitting = true; + return MOD_STOP; + } + if (!has_svsholdmod) + ircdproto->SendGlobops(OperServ, "SVSHOLD missing, Usage disabled until module is loaded."); + if (!has_chghostmod) + ircdproto->SendGlobops(OperServ, "CHGHOST missing, Usage disabled until module is loaded."); + if (!has_chgidentmod) + ircdproto->SendGlobops(OperServ, "CHGIDENT missing, Usage disabled until module is loaded."); + ircd->svshold = has_svsholdmod; + } + + IRCdMessage::OnCapab(source, params); + } + + bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) + { + Channel *c = findchan(params[0]); + time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; + bool keep_their_modes = true; + + if (!c) + { + c = new Channel(params[0], ts); + c->SetFlag(CH_SYNCING); + } + /* Our creation time is newer than what the server gave us */ + else if (c->creation_time > ts) + { + c->creation_time = ts; + c->Reset(); + + /* Reset mlock */ + check_modes(c); + } + /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ + else if (ts > c->creation_time) + keep_their_modes = false; + + spacesepstream sep(params[params.size() - 1]); + Anope::string buf; + while (sep.GetToken(buf)) + { + std::list<ChannelMode *> Status; + char ch; + + /* Loop through prefixes */ + while ((ch = ModeManager::GetStatusChar(buf[0]))) + { + ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); + + if (!cm) + { + Log() << "Received unknown mode prefix " << buf[0] << " in FJOIN string"; + buf.erase(buf.begin()); + continue; + } + + buf.erase(buf.begin()); + if (keep_their_modes) + Status.push_back(cm); + } + + User *u = finduser(buf); + if (!u) + { + Log(LOG_DEBUG) << "FJOIN for nonexistant user " << buf << " on " << c->name; + continue; + } + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); + + /* Add the user to the channel */ + c->JoinUser(u); + + /* Update their status internally on the channel + * 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(*it, buf); + + /* Now set whatever modes this user is allowed to have on the channel */ + chan_set_correct_modes(u, c, 1); + + /* 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)) + continue; + + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); + } + + /* Channel is done syncing */ + if (c->HasFlag(CH_SYNCING)) + { + /* Unset the syncing flag */ + c->UnsetFlag(CH_SYNCING); + c->Sync(); + } + } +}; bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) { @@ -311,34 +698,17 @@ bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> return true; } -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[1], params[2]); - else - { - /* InspIRCd lets opers change another - users modes - */ - do_umode(source, params[0], params[1]); - } - 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 && !is_oper(u)) + if (u && !u->HasMode(UMODE_OPER)) { std::vector<Anope::string> newparams; newparams.push_back(source); newparams.push_back("+o"); - return event_mode(source, newparams); + return ircdmessage->OnMode(source, newparams); } else return true; @@ -380,144 +750,7 @@ bool event_fmode(const Anope::string &source, const std::vector<Anope::string> & } } - return event_mode(source, newparams); -} - -bool event_fjoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Channel *c = findchan(params[0]); - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - bool keep_their_modes = true; - - if (!c) - { - c = new Channel(params[0], ts); - c->SetFlag(CH_SYNCING); - } - /* Our creation time is newer than what the server gave us */ - else if (c->creation_time > ts) - { - c->creation_time = ts; - c->Reset(); - - /* Reset mlock */ - check_modes(c); - } - /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ - else if (ts > c->creation_time) - keep_their_modes = false; - - spacesepstream sep(params[params.size() - 1]); - Anope::string buf; - while (sep.GetToken(buf)) - { - std::list<ChannelMode *> Status; - char ch; - - /* Loop through prefixes */ - while ((ch = ModeManager::GetStatusChar(buf[0]))) - { - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); - - if (!cm) - { - Log() << "Received unknown mode prefix " << buf[0] << " in FJOIN string"; - buf.erase(buf.begin()); - continue; - } - - buf.erase(buf.begin()); - if (keep_their_modes) - Status.push_back(cm); - } - - User *u = finduser(buf); - if (!u) - { - Log(LOG_DEBUG) << "FJOIN for nonexistant user " << buf << " on " << c->name; - continue; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - - /* Add the user to the channel */ - c->JoinUser(u); - - /* Update their status internally on the channel - * 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(*it, buf); - - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1); - - /* 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)) - continue; - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); - } - - /* Channel is done syncing */ - if (c->HasFlag(CH_SYNCING)) - { - /* Unset the syncing flag */ - c->UnsetFlag(CH_SYNCING); - c->Sync(); - } - - return true; -} - -/* Events */ -bool event_ping(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - ircdproto->SendPong(Config->ServerName, params[0]); - return true; -} - -bool event_436(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - m_nickcoll(params[0]); - return true; -} - -bool event_away(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!source.empty()) - m_away(source, !params.empty() ? params[0] : ""); - return true; -} - -/* Taken from hybrid.c, topic syntax is identical */ - -bool event_topic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Channel *c = findchan(params[0]); - - if (!c) - { - Log() << "TOPIC " << (params.size() > 1 ? params[1] : "") << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : ""), Anope::CurTime); - - return true; -} - -bool event_squit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_squit(source, params[0]); - return true; + return ircdmessage->OnMode(source, newparams); } bool event_rsquit(const Anope::string &source, const std::vector<Anope::string> ¶ms) @@ -525,49 +758,15 @@ bool event_rsquit(const Anope::string &source, const std::vector<Anope::string> 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])) - do_squit(source, params[1]); + p.push_back(params[1]); else - do_squit(source, params[0]); - - return true; -} - -bool event_quit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_quit(source, params[0]); - return true; -} - -bool event_kill(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 1) - m_kill(params[0], params[1]); - 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; -} - -bool event_join(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 1) - do_join(source, params[0], params[1]); - return true; -} + p.push_back(params[0]); -bool event_motd(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (source.empty()) - return true; + ircdmessage->OnSQuit(source, p); - m_motd(source); return true; } @@ -652,34 +851,6 @@ bool event_sethost(const Anope::string &source, const std::vector<Anope::string> } -bool event_nick(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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) - { - user->SetCloakedHost(params[3]); - - NickAlias *na = findnick(user->nick); - Anope::string svidbuf; - if (na && na->nc->GetExtRegular("authenticationtoken", svidbuf) && svidbuf == params[0]) - { - user->Login(na->nc); - user->SetMode(NickServ, UMODE_REGISTERED); - } - else - validate_user(user); - } - } - else if (params.size() == 1) - do_nick(source, params[0], "", "", "", "", 0, "", "", "", ""); - return true; -} - - bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) { if (params.empty()) @@ -696,264 +867,6 @@ bool event_chghost(const Anope::string &source, const std::vector<Anope::string> return true; } -/* EVENT: SERVER */ -bool event_server(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[2], ""); - return true; -} - -bool event_privmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 1) - m_privmsg(source, params[0], params[1]); - return true; -} - -bool event_part(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_part(source, params[0], params.size() > 1 ? params[1] : ""); - return true; -} - -bool event_whois(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!source.empty() && !params.empty()) - m_whois(source, params[0]); - return true; -} - -bool event_capab(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params[0].equals_cs("START")) - { - /* reset CAPAB */ - has_servicesmod = false; - has_globopsmod = false; - has_svsholdmod = false; - has_chghostmod = false; - has_chgidentmod = false; - has_hidechansmod = false; - } - else if (params[0].equals_cs("MODULES")) - { - if (params[1].find("m_globops.so") != Anope::string::npos) - has_globopsmod = true; - if (params[1].find("m_services.so") != Anope::string::npos) - has_servicesmod = true; - if (params[1].find("m_svshold.so") != Anope::string::npos) - has_svsholdmod = true; - if (params[1].find("m_chghost.so") != Anope::string::npos) - has_chghostmod = true; - if (params[1].find("m_chgident.so") != Anope::string::npos) - has_chgidentmod = true; - if (params[1].find("m_hidechans.so") != Anope::string::npos) - has_hidechansmod = true; - } - else if (params[0].equals_cs("CAPABILITIES")) - { - spacesepstream ssep(params[1]); - Anope::string capab; - while (ssep.GetToken(capab)) - { - if (capab.find("CHANMODES") != Anope::string::npos) - { - Anope::string modes(capab.begin() + 10, capab.end()); - commasepstream sep(modes); - Anope::string modebuf; - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) - { - case 'b': - ModeManager::AddChannelMode(new ChannelModeBan('b')); - continue; - case 'e': - ModeManager::AddChannelMode(new ChannelModeExcept('e')); - continue; - case 'I': - ModeManager::AddChannelMode(new ChannelModeInvex('I')); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, "", modebuf[t])); - } - } - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) - { - case 'k': - ModeManager::AddChannelMode(new ChannelModeKey('k')); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t])); - } - } - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) - { - case 'f': - ModeManager::AddChannelMode(new ChannelModeFlood('f')); - continue; - case 'l': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, "CMODE_LIMIT", 'l', true)); - continue; - case 'L': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_REDIRECT, "CMODE_REDIRECT", 'L', true)); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t], true)); - } - } - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) - { - case 'i': - ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, "CMODE_INVITE", 'i')); - continue; - case 'm': - ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, "CMODE_MODERATED", 'm')); - continue; - case 'n': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, "CMODE_NOEXTERNAL", 'n')); - continue; - case 'p': - ModeManager::AddChannelMode(new ChannelMode(CMODE_PRIVATE, "CMODE_PRIVATE", 'p')); - continue; - case 's': - ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, "CMODE_SECRET", 's')); - continue; - case 't': - ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, "CMODE_TOPIC", 't')); - continue; - case 'r': - ModeManager::AddChannelMode(new ChannelModeRegistered('r')); - continue; - case 'c': - ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, "CMODE_BLOCKCOLOR", 'c')); - continue; - case 'u': - ModeManager::AddChannelMode(new ChannelMode(CMODE_AUDITORIUM, "CMODE_AUDITORIUM", 'u')); - continue; - case 'z': - ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, "CMODE_SSL", 'z')); - continue; - case 'A': - ModeManager::AddChannelMode(new ChannelMode(CMODE_ALLINVITE, "CMODE_ALLINVITE", 'A')); - continue; - case 'C': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOCTCP, "CMODE_NOCTCP", 'C')); - continue; - case 'G': - ModeManager::AddChannelMode(new ChannelMode(CMODE_FILTER, "CMODE_FILTER", 'G')); - continue; - case 'K': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKNOCK, "CMODE_NOKNOCK", 'K')); - continue; - case 'N': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NONICK, "CMODE_NONICK", 'N')); - continue; - case 'O': - ModeManager::AddChannelMode(new ChannelModeOper('O')); - continue; - case 'Q': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKICK, "CMODE_NOKICK", 'Q')); - continue; - case 'R': - ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, "CMODE_REGISTEREDONLY", 'R')); - continue; - case 'S': - ModeManager::AddChannelMode(new ChannelMode(CMODE_STRIPCOLOR, "CMODE_STRIPCOLOR", 'S')); - continue; - case 'V': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOINVITE, "CMODE_NOINVITE", 'V')); - continue; - default: - ModeManager::AddChannelMode(new ChannelMode(CMODE_END, "", modebuf[t])); - } - } - } - else if (capab.find("PREIX=(") != Anope::string::npos) - { - Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')')); - Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end()); - - for (size_t t = 0, end = modes.length(); t < end; ++t) - { - switch (modes[t]) - { - case 'q': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, "CMODE_OWNER", 'q', '~')); - continue; - case 'a': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, "CMODE_PROTECT", 'a', '&')); - continue; - case 'o': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, "CMODE_OP", 'o', '@')); - continue; - case 'h': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, "CMODE_HALFOP", 'h', '%')); - continue; - case 'v': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, "CMODE_VOICE", 'v', '+')); - continue; - } - } - } - 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; - } - } - } - else if (params[0].equals_cs("END")) - { - if (!has_globopsmod) - { - send_cmd("", "ERROR :m_globops is not loaded. This is required by Anope"); - quitmsg = "ERROR: Remote server does not have the m_globops module loaded, and this is required."; - quitting = true; - return MOD_STOP; - } - if (!has_servicesmod) - { - send_cmd("", "ERROR :m_services is not loaded. This is required by Anope"); - quitmsg = "ERROR: Remote server does not have the m_services module loaded, and this is required."; - quitting = true; - return MOD_STOP; - } - if (!has_hidechansmod) - { - send_cmd("", "ERROR :m_hidechans.so is not loaded. This is required by Anope"); - quitmsg = "ERROR: Remote server deos not have the m_hidechans module loaded, and this is required."; - quitting = true; - return MOD_STOP; - } - if (!has_svsholdmod) - ircdproto->SendGlobops(OperServ, "SVSHOLD missing, Usage disabled until module is loaded."); - if (!has_chghostmod) - ircdproto->SendGlobops(OperServ, "CHGHOST missing, Usage disabled until module is loaded."); - if (!has_chgidentmod) - ircdproto->SendGlobops(OperServ, "CHGIDENT missing, Usage disabled until module is loaded."); - ircd->svshold = has_svsholdmod; - } - - CapabParse(params); - return true; -} - bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) { Me->GetLinks().front()->Sync(true); @@ -982,37 +895,34 @@ static void AddModes() class ProtoInspIRCd : public Module { - Message message_endburst, message_436, message_away, message_join, message_kick, message_kill, message_mode, message_motd, - message_nick, message_capab, message_part, message_ping, message_privmsg, message_quit, message_server, message_squit, - message_rsquit, message_topic, message_whois, message_svsmode, message_chghost, message_chgident, message_chgname, - message_sethost, message_setident, message_setname, message_fjoin, message_fmode, message_ftopic, message_opertype, + 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; + + InspIRCdProto ircd_proto; + InspircdIRCdMessage ircd_message; public: ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), - message_endburst("ENDBURST", event_endburst), message_436("436", event_436), message_away("AWAY", event_away), - message_join("JOIN", event_join), message_kick("KICK", event_kick), message_kill("KILL", event_kill), - message_mode("MODE", event_mode), message_motd("MOTD", event_motd), message_nick("NICK", event_nick), - message_capab("CAPAB", event_capab), message_part("PART", event_part), message_ping("PING", event_ping), - message_privmsg("PRIVMSG", event_privmsg), message_quit("QUIT", event_quit), message_server("SERVER", event_server), - message_squit("SQUIT", event_squit), message_rsquit("RSQUIT", event_rsquit), message_topic("TOPIC", event_topic), - message_whois("WHOIS", event_whois), message_svsmode("SVSMODE", event_mode), message_chghost("CHGHOST", event_chghost), + 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_fjoin("FJOIN", event_fjoin), message_fmode("FMODE", event_fmode), - message_ftopic("FTOPIC", event_ftopic), message_opertype("OPERTYPE", event_opertype), message_idle("IDLE", event_idle) + 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) { this->SetAuthor("Anope"); this->SetType(PROTOCOL); - pmodule_ircd_var(myIrcd); - CapabType c[] = { CAPAB_NOQUIT, CAPAB_SSJ3, CAPAB_NICK2, CAPAB_VL, CAPAB_TLKEXT }; for (unsigned i = 0; i < 5; ++i) Capab.SetFlag(c[i]); AddModes(); - pmodule_ircd_proto(&ircd_proto); + pmodule_ircd_var(myIrcd); + pmodule_ircd_proto(&this->ircd_proto); + pmodule_ircd_message(&this->ircd_message); ModuleManager::Attach(I_OnUserNickChange, this); } diff --git a/modules/protocol/inspircd12.cpp b/modules/protocol/inspircd12.cpp index f93d51b62..cedab07bf 100644 --- a/modules/protocol/inspircd12.cpp +++ b/modules/protocol/inspircd12.cpp @@ -13,7 +13,12 @@ #include "services.h" #include "modules.h" -#include "hashcomp.h" + +/* inspircd-ts6.h uses these */ +static bool has_globopsmod = false; +static bool has_chghostmod = false; +static bool has_chgidentmod = false; +#include "inspircd-ts6.h" IRCDVar myIrcd[] = { {"InspIRCd 1.2", /* ircd name */ @@ -44,10 +49,7 @@ IRCDVar myIrcd[] = { }; static bool has_servicesmod = false; -static bool has_globopsmod = false; static bool has_svsholdmod = false; -static bool has_chghostmod = false; -static bool has_chgidentmod = false; static bool has_hidechansmod = false; /* Previously introduced user during burst */ @@ -73,235 +75,6 @@ bool event_idle(const Anope::string &source, const std::vector<Anope::string> &p return true; } -static Anope::string currentpass; - -/* PASS */ -void inspircd_cmd_pass(const Anope::string &pass) -{ - currentpass = pass; -} - -class InspIRCdProto : public IRCDProto -{ - void SendAkillDel(const XLine *x) - { - send_cmd(OperServ ? OperServ->GetUID() : Config->Numeric, "GLINE %s", x->Mask.c_str()); - } - - void SendTopic(BotInfo *whosets, Channel *c) - { - send_cmd(whosets->GetUID(), "FTOPIC %s %lu %s :%s", c->name.c_str(), static_cast<unsigned long>(c->topic_time + 1), c->topic_setter.c_str(), c->topic.c_str()); - } - - void SendVhostDel(User *u) - { - if (u->HasMode(UMODE_CLOAK)) - inspircd_cmd_chghost(u->nick, u->chost); - else - inspircd_cmd_chghost(u->nick, u->host); - - if (has_chgidentmod && u->GetIdent() != u->GetVIdent()) - inspircd_cmd_chgident(u->nick, u->GetIdent()); - } - - void SendAkill(const XLine *x) - { - // Calculate the time left before this would expire, capping it at 2 days - time_t timeleft = x->Expires - Anope::CurTime; - if (timeleft > 172800 || !x->Expires) - timeleft = 172800; - send_cmd(OperServ ? OperServ->GetUID() : Config->Numeric, "ADDLINE G %s@%s %s %ld %ld :%s", x->GetUser().c_str(), x->GetHost().c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime), static_cast<long>(timeleft), x->Reason.c_str()); - } - - void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) - { - send_cmd(source ? source->GetUID() : Config->Numeric, "KILL %s :%s", user->GetUID().c_str(), buf.c_str()); - } - - void SendSVSMode(const User *u, int ac, const char **av) - { - this->SendModeInternal(NULL, u, merge_args(ac, av)); - } - - void SendNumericInternal(const Anope::string &source, int numeric, const Anope::string &dest, const Anope::string &buf) - { - send_cmd(Config->Numeric, "PUSH %s ::%s %03d %s %s", dest.c_str(), source.c_str(), numeric, dest.c_str(), buf.c_str()); - } - - void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - send_cmd(source ? source->GetUID() : Config->Numeric, "FMODE %s %u %s", dest->name.c_str(), static_cast<unsigned>(dest->creation_time), buf.c_str()); - } - - void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) - { - if (buf.empty()) - return; - send_cmd(bi ? bi->GetUID() : Config->Numeric, "MODE %s %s", u->GetUID().c_str(), buf.c_str()); - } - - void SendClientIntroduction(const User *u, const Anope::string &modes) - { - send_cmd(Config->Numeric, "UID %s %ld %s %s %s %s 0.0.0.0 %ld %s :%s", u->GetUID().c_str(), static_cast<long>(u->timestamp), u->nick.c_str(), u->host.c_str(), u->host.c_str(), u->GetIdent().c_str(), static_cast<long>(u->my_signon), modes.c_str(), u->realname.c_str()); - } - - void SendKickInternal(const BotInfo *source, const Channel *chan, const User *user, const Anope::string &buf) - { - if (!buf.empty()) - send_cmd(source->GetUID(), "KICK %s %s :%s", chan->name.c_str(), user->GetUID().c_str(), buf.c_str()); - else - send_cmd(source->GetUID(), "KICK %s %s :%s", chan->name.c_str(), user->GetUID().c_str(), user->nick.c_str()); - } - - void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - send_cmd(Config->Numeric, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); - } - - /* SERVER services-dev.chatspike.net password 0 :Description here */ - void SendServer(const Server *server) - { - send_cmd("", "SERVER %s %s %d %s :%s", server->GetName().c_str(), currentpass.c_str(), server->GetHops(), server->GetSID().c_str(), server->GetDescription().c_str()); - } - - /* JOIN */ - void SendJoin(const BotInfo *user, const Anope::string &channel, time_t chantime) - { - send_cmd(Config->Numeric, "FJOIN %s %ld + :,%s", channel.c_str(), static_cast<long>(chantime), user->GetUID().c_str()); - } - - void SendJoin(BotInfo *user, const ChannelContainer *cc) - { - send_cmd(Config->Numeric, "FJOIN %s %ld +%s :%s,%s", cc->chan->name.c_str(), static_cast<long>(cc->chan->creation_time), cc->chan->GetModes(true, true).c_str(), cc->Status->BuildCharPrefixList().c_str(), user->GetUID().c_str()); - } - - /* UNSQLINE */ - void SendSQLineDel(const XLine *x) - { - send_cmd(Config->Numeric, "DELLINE Q %s", x->Mask.c_str()); - } - - /* SQLINE */ - void SendSQLine(const XLine *x) - { - send_cmd(Config->Numeric, "ADDLINE Q %s %s %ld 0 :%s", x->Mask.c_str(), Config->s_OperServ.c_str(), static_cast<long>(Anope::CurTime), x->Reason.c_str()); - } - - /* SQUIT */ - void SendSquit(const Anope::string &servname, const Anope::string &message) - { - send_cmd(Config->Numeric, "SQUIT %s :%s", servname.c_str(), message.c_str()); - } - - /* Functions that use serval cmd functions */ - - void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) - { - if (!vIdent.empty()) - inspircd_cmd_chgident(u->nick, vIdent); - if (!vhost.empty()) - inspircd_cmd_chghost(u->nick, vhost); - } - - void SendConnect() - { - inspircd_cmd_pass(uplink_server->password); - SendServer(Me); - send_cmd(Config->Numeric, "BURST"); - send_cmd(Config->Numeric, "VERSION :Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircd->name, Config->EncModuleList.begin()->c_str(), Anope::Build().c_str()); - } - - /* CHGIDENT */ - void inspircd_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent) - { - if (!has_chgidentmod) - ircdproto->SendGlobops(OperServ, "CHGIDENT not loaded!"); - else - send_cmd(HostServ ? HostServ->GetUID() : Config->Numeric, "CHGIDENT %s %s", nick.c_str(), vIdent.c_str()); - } - - /* SVSHOLD - set */ - void SendSVSHold(const Anope::string &nick) - { - send_cmd(NickServ->GetUID(), "SVSHOLD %s %u :Being held for registered user", nick.c_str(), static_cast<unsigned>(Config->NSReleaseTimeout)); - } - - /* SVSHOLD - release */ - void SendSVSHoldDel(const Anope::string &nick) - { - send_cmd(NickServ->GetUID(), "SVSHOLD %s", nick.c_str()); - } - - /* UNSZLINE */ - void SendSZLineDel(const XLine *x) - { - send_cmd(Config->Numeric, "DELLINE Z %s", x->Mask.c_str()); - } - - /* SZLINE */ - void SendSZLine(const XLine *x) - { - send_cmd(Config->Numeric, "ADDLINE Z %s %s %ld 0 :%s", x->Mask.c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime), x->Reason.c_str()); - } - - void SendSVSJoin(const Anope::string &source, const Anope::string &nick, const Anope::string &chan, const Anope::string &) - { - User *u = finduser(nick); - BotInfo *bi = findbot(source); - send_cmd(bi->GetUID(), "SVSJOIN %s %s", u->GetUID().c_str(), chan.c_str()); - } - - void SendSVSPart(const Anope::string &source, const Anope::string &nick, const Anope::string &chan) - { - User *u = finduser(nick); - BotInfo *bi = findbot(source); - send_cmd(bi->GetUID(), "SVSPART %s %s", u->GetUID().c_str(), chan.c_str()); - } - - void SendSWhois(const Anope::string &, const Anope::string &who, const Anope::string &mask) - { - User *u = finduser(who); - - send_cmd(Config->Numeric, "METADATA %s swhois :%s", u->GetUID().c_str(), mask.c_str()); - } - - void SendBOB() - { - send_cmd(Config->Numeric, "BURST %ld", static_cast<long>(Anope::CurTime)); - } - - void SendEOB() - { - send_cmd(Config->Numeric, "ENDBURST"); - } - - void SendGlobopsInternal(BotInfo *source, const Anope::string &buf) - { - if (has_globopsmod) - send_cmd(source ? source->GetUID() : Config->Numeric, "SNONOTICE g :%s", buf.c_str()); - else - send_cmd(source ? source->GetUID() : Config->Numeric, "SNONOTICE A :%s", buf.c_str()); - } - - void SendAccountLogin(const User *u, const NickCore *account) - { - send_cmd(Config->Numeric, "METADATA %s accountname :%s", u->GetUID().c_str(), account->display.c_str()); - } - - void SendAccountLogout(const User *u, const NickCore *account) - { - send_cmd(Config->Numeric, "METADATA %s accountname :", u->GetUID().c_str()); - } - - bool IsNickValid(const Anope::string &nick) - { - /* InspIRCd, like TS6, uses UIDs on collision, so... */ - if (isdigit(nick[0])) - return false; - - return true; - } -} ircd_proto; bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) { @@ -321,44 +94,17 @@ bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> return true; } -bool event_mode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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); - User *u2 = finduser(params[0]); - - // This can happen with server-origin modes. - if (!u) - u = u2; - - // if it's still null, drop it like fire. - // most likely situation was that server introduced a nick which we subsequently akilled - if (!u || !u2) - return true; - - do_umode(u->nick, u2->nick, params[1]); - } - 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 && !is_oper(u)) + if (u && !u->HasMode(UMODE_OPER)) { std::vector<Anope::string> newparams; newparams.push_back(source); newparams.push_back("+o"); - return event_mode(source, newparams); + return ircdmessage->OnMode(source, newparams); } return true; @@ -395,128 +141,7 @@ bool event_fmode(const Anope::string &source, const std::vector<Anope::string> & modes += " " + params[n]; newparams.push_back(modes); - return event_mode(source, newparams); -} - -/* - * [Nov 03 22:31:57.695076 2009] debug: Received: :964 FJOIN #test 1223763723 +BPSnt :,964AAAAAB ,964AAAAAC ,966AAAAAA - * - * 0: name - * 1: channel ts (when it was created, see protocol docs for more info) - * 2: channel modes + params (NOTE: this may definitely be more than one param!) - * last: users - */ -bool event_fjoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Channel *c = findchan(params[0]); - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - bool keep_their_modes = true; - - if (!c) - { - c = new Channel(params[0], ts); - c->SetFlag(CH_SYNCING); - } - /* Our creation time is newer than what the server gave us */ - else if (c->creation_time > ts) - { - c->creation_time = ts; - c->Reset(); - - /* Reset mlock */ - check_modes(c); - } - /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ - else if (ts > c->creation_time) - keep_their_modes = false; - - /* If we need to keep their modes, and this FJOIN string contains modes */ - if (keep_their_modes && params.size() >= 3) - { - Anope::string modes; - for (unsigned i = 2; i < params.size() - 1; ++i) - modes += " " + params[i]; - if (!modes.empty()) - modes.erase(modes.begin()); - /* Set the modes internally */ - c->SetModesInternal(NULL, modes); - } - - spacesepstream sep(params[params.size() - 1]); - Anope::string buf; - while (sep.GetToken(buf)) - { - std::list<ChannelMode *> Status; - - /* Loop through prefixes and find modes for them */ - while (buf[0] != ',') - { - ChannelMode *cm = ModeManager::FindChannelModeByChar(buf[0]); - if (!cm) - { - Log() << "Receeved unknown mode prefix " << buf[0] << " in FJOIN string"; - buf.erase(buf.begin()); - continue; - } - - buf.erase(buf.begin()); - if (keep_their_modes) - Status.push_back(cm); - } - buf.erase(buf.begin()); - - User *u = finduser(buf); - if (!u) - { - Log(LOG_DEBUG) << "FJOIN for nonexistant user " << buf << " on " << c->name; - continue; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - - /* Add the user to the channel */ - c->JoinUser(u); - - /* Update their status internally on the channel - * 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(*it, buf); - - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1); - - /* 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)) - continue; - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); - } - - /* Channel is done syncing */ - if (c->HasFlag(CH_SYNCING)) - { - /* Unset the syncing flag */ - c->UnsetFlag(CH_SYNCING); - c->Sync(); - } - - return true; -} - -/* Events */ -bool event_ping(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() == 1) - ircdproto->SendPong("", params[0]); - else if (params.size() == 2) - ircdproto->SendPong(params[1], params[0]); - - return true; + return ircdmessage->OnMode(source, newparams); } bool event_time(const Anope::string &source, const std::vector<Anope::string> ¶ms) @@ -525,44 +150,6 @@ bool event_time(const Anope::string &source, const std::vector<Anope::string> &p return true; send_cmd(Config->Numeric, "TIME %s %s %ld", source.c_str(), params[1].c_str(), static_cast<long>(Anope::CurTime)); - - /* We handled it, don't pass it on to the core.. - * The core doesn't understand our syntax anyways.. ~ Viper */ - return MOD_STOP; -} - -bool event_436(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - m_nickcoll(params[0]); - return true; -} - -bool event_away(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - m_away(source, !params.empty() ? params[0] : ""); - return true; -} - -/* Taken from hybrid.c, topic syntax is identical */ -bool event_topic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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); - - return true; -} - -bool event_squit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_squit(source, params[0]); return true; } @@ -573,41 +160,8 @@ bool event_rsquit(const Anope::string &source, const std::vector<Anope::string> if (s && s->HasFlag(SERVER_JUPED)) send_cmd(Config->Numeric, "SQUIT %s :%s", s->GetSID().c_str(), params.size() > 1 ? params[1].c_str() : ""); - do_squit(source, params[0]); - - return true; -} - -bool event_quit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_quit(source, params[0]); - return true; -} - -bool event_kill(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(params[0]); - BotInfo *bi = findbot(params[0]); - m_kill(u ? u->nick : (bi ? bi->nick : params[0]), params[1]); - return true; -} + ircdmessage->OnSQuit(source, params); -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; -} - -bool event_join(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_join(source, params[0], (params.size() > 1 ? params[1] : "")); - return true; -} - -bool event_motd(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - m_motd(source); return true; } @@ -680,12 +234,6 @@ bool event_sethost(const Anope::string &source, const std::vector<Anope::string> return true; } -bool event_nick(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_nick(source, params[0], "", "", "", "", 0, "", "", "", ""); - return true; -} - /* * [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 @@ -754,41 +302,6 @@ bool event_chghost(const Anope::string &source, const std::vector<Anope::string> return true; } -/* - * [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 event_server(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_server(source, params[0], Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0, params[4], params[3]); - return true; -} - -bool event_privmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!finduser(source)) - return true; // likely a message from a server, which can happen. - - m_privmsg(source, params[0], params[1]); - return true; -} - -bool event_part(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_part(source, params[0], (params.size() > 1 ? params[1] : "")); - return true; -} - -bool event_whois(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - m_whois(source, params[0]); - return true; -} - bool event_metadata(const Anope::string &source, const std::vector<Anope::string> ¶ms) { if (params.size() < 3) @@ -806,371 +319,375 @@ bool event_metadata(const Anope::string &source, const std::vector<Anope::string return true; } -bool event_capab(const Anope::string &source, const std::vector<Anope::string> ¶ms) +bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - if (params[0].equals_cs("START")) - { - /* reset CAPAB */ - has_servicesmod = false; - has_globopsmod = false; - has_svsholdmod = false; - has_chghostmod = false; - has_chgidentmod = false; - has_hidechansmod = false; - } - else if (params[0].equals_cs("MODULES")) + User *u = prev_u_intro; + Server *s = Server::Find(source); + + if (!s) + throw CoreException("Got ENDBURST without a source"); + + /* Check if the previously introduced user was Id'd for the nickgroup of the nick he s currently using. + * If not, validate the user. ~ Viper*/ + prev_u_intro = NULL; + if (u && !u->server->IsSynced()) { - if (params[1].find("m_globops.so") != Anope::string::npos) - has_globopsmod = true; - if (params[1].find("m_services_account.so") != Anope::string::npos) - has_servicesmod = true; - if (params[1].find("m_svshold.so") != Anope::string::npos) - has_svsholdmod = true; - if (params[1].find("m_chghost.so") != Anope::string::npos) - has_chghostmod = true; - if (params[1].find("m_chgident.so") != Anope::string::npos) - has_chgidentmod = true; - 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"; + NickAlias *na = findnick(u->nick); + + if (!na || na->nc != u->Account()) + { + validate_user(u); + if (u->HasMode(UMODE_REGISTERED)) + u->RemoveMode(NickServ, UMODE_REGISTERED); + } + else + /* Set them +r (to negate a possible -r on the stack) */ + u->SetMode(NickServ, UMODE_REGISTERED); } - else if (params[0].equals_cs("CAPABILITIES")) + + Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); + + s->Sync(true); + return true; +} + +class Inspircd12IRCdMessage : public InspircdIRCdMessage +{ + public: + bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - spacesepstream ssep(params[1]); - Anope::string capab; - while (ssep.GetToken(capab)) + if (params[0].equals_cs("START")) + { + /* reset CAPAB */ + has_servicesmod = false; + has_globopsmod = false; + has_svsholdmod = false; + has_chghostmod = false; + has_chgidentmod = false; + has_hidechansmod = false; + } + else if (params[0].equals_cs("MODULES")) + { + if (params[1].find("m_globops.so") != Anope::string::npos) + has_globopsmod = true; + if (params[1].find("m_services_account.so") != Anope::string::npos) + has_servicesmod = true; + if (params[1].find("m_svshold.so") != Anope::string::npos) + has_svsholdmod = true; + if (params[1].find("m_chghost.so") != Anope::string::npos) + has_chghostmod = true; + if (params[1].find("m_chgident.so") != Anope::string::npos) + has_chgidentmod = true; + 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"; + } + else if (params[0].equals_cs("CAPABILITIES")) { - if (capab.find("CHANMODES") != Anope::string::npos) + spacesepstream ssep(params[1]); + Anope::string capab; + while (ssep.GetToken(capab)) { - Anope::string modes(capab.begin() + 10, capab.end()); - commasepstream sep(modes); - Anope::string modebuf; - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) + if (capab.find("CHANMODES") != Anope::string::npos) { - switch (modebuf[t]) - { - case 'b': - ModeManager::AddChannelMode(new ChannelModeBan('b')); - continue; - case 'e': - ModeManager::AddChannelMode(new ChannelModeExcept('e')); - continue; - case 'I': - ModeManager::AddChannelMode(new ChannelModeInvex('I')); - continue; - /* InspIRCd sends q and a here if they have no prefixes */ - case 'q': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, "CMODE_OWNER", 'q', '@')); - continue; - case 'a': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT , "CMODE_PROTECT", 'a', '@')); - continue; - // XXX list modes needs a bit of a rewrite, we need to be able to support +g here - default: - ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, "", modebuf[t])); - } - } + Anope::string modes(capab.begin() + 10, capab.end()); + commasepstream sep(modes); + Anope::string modebuf; - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) { - case 'k': - ModeManager::AddChannelMode(new ChannelModeKey('k')); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t])); + switch (modebuf[t]) + { + case 'b': + ModeManager::AddChannelMode(new ChannelModeBan('b')); + continue; + case 'e': + ModeManager::AddChannelMode(new ChannelModeExcept('e')); + continue; + case 'I': + ModeManager::AddChannelMode(new ChannelModeInvex('I')); + continue; + /* InspIRCd sends q and a here if they have no prefixes */ + case 'q': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, "CMODE_OWNER", 'q', '@')); + continue; + case 'a': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT , "CMODE_PROTECT", 'a', '@')); + continue; + // XXX mode g + default: + ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, "", modebuf[t])); + } } - } - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) { - case 'F': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_NICKFLOOD, "CMODE_NICKFLOOD", 'F', true)); - continue; - case 'J': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_NOREJOIN, "CMODE_NOREJOIN", 'J', true)); - continue; - case 'L': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_REDIRECT, "CMODE_REDIRECT", 'L', true)); - continue; - case 'f': - ModeManager::AddChannelMode(new ChannelModeFlood('f', true)); - continue; - case 'j': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_JOINFLOOD, "CMODE_JOINFLOOD", 'j', true)); - continue; - case 'l': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, "CMODE_LIMIT", 'l', true)); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t], true)); + switch (modebuf[t]) + { + case 'k': + ModeManager::AddChannelMode(new ChannelModeKey('k')); + continue; + default: + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t])); + } } - } - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - switch (modebuf[t]) + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) { - case 'A': - ModeManager::AddChannelMode(new ChannelMode(CMODE_ALLINVITE, "CMODE_ALLINVITE", 'A')); - continue; - case 'B': - ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCAPS, "CMODE_BLOCKCAPS", 'B')); - continue; - case 'C': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOCTCP, "CMODE_NOCTCP", 'C')); - continue; - case 'D': - ModeManager::AddChannelMode(new ChannelMode(CMODE_DELAYEDJOIN, "CMODE_DELAYEDJOIN", 'D')); - continue; - case 'G': - ModeManager::AddChannelMode(new ChannelMode(CMODE_FILTER, "CMODE_FILTER", 'G')); - continue; - case 'K': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKNOCK, "CMODE_NOKNOCK", 'K')); - continue; - case 'M': - ModeManager::AddChannelMode(new ChannelMode(CMODE_REGMODERATED, "CMODE_REGMODERATED", 'M')); - continue; - case 'N': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NONICK, "CMODE_NONICK", 'N')); - continue; - case 'O': - ModeManager::AddChannelMode(new ChannelModeOper('O')); - continue; - case 'P': - ModeManager::AddChannelMode(new ChannelMode(CMODE_PERM, "CMODE_PERM", 'P')); - continue; - case 'Q': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKICK, "CMODE_NOKICK", 'Q')); - continue; - case 'R': - ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, "CMODE_REGISTEREDONLY", 'R')); - continue; - case 'S': - ModeManager::AddChannelMode(new ChannelMode(CMODE_STRIPCOLOR, "CMODE_STRIPCOLOR", 'S')); - continue; - case 'T': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NONOTICE, "CMODE_NONOTICE", 'T')); - continue; - case 'c': - ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, "CMODE_BLOCKCOLOR", 'c')); - continue; - case 'i': - ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, "CMODE_INVITE", 'i')); - continue; - case 'm': - ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, "CMODE_MODERATED", 'm')); - continue; - case 'n': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, "CMODE_NOEXTERNAL", 'n')); - continue; - case 'p': - ModeManager::AddChannelMode(new ChannelMode(CMODE_PRIVATE, "CMODE_PRIVATE", 'p')); - continue; - case 'r': - ModeManager::AddChannelMode(new ChannelModeRegistered('r')); - continue; - case 's': - ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, "CMODE_SECRET", 's')); - continue; - case 't': - ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, "CMODE_TOPIC", 't')); - continue; - case 'u': - ModeManager::AddChannelMode(new ChannelMode(CMODE_AUDITORIUM, "CMODE_AUDITORIUM", 'u')); - continue; - case 'z': - ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, "CMODE_SSL", 'z')); - continue; - default: - ModeManager::AddChannelMode(new ChannelMode(CMODE_END, "", modebuf[t])); + switch (modebuf[t]) + { + case 'F': + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_NICKFLOOD, "CMODE_NICKFLOOD", 'F', true)); + continue; + case 'J': + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_NOREJOIN, "CMODE_NOREJOIN", 'J', true)); + continue; + case 'L': + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_REDIRECT, "CMODE_REDIRECT", 'L', true)); + continue; + case 'f': + ModeManager::AddChannelMode(new ChannelModeFlood('f', true)); + continue; + case 'j': + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_JOINFLOOD, "CMODE_JOINFLOOD", 'j', true)); + continue; + case 'l': + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, "CMODE_LIMIT", 'l', true)); + continue; + default: + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t], true)); + } } - } - } - else if (capab.find("USERMODES") != Anope::string::npos) - { - Anope::string modes(capab.begin() + 10, capab.end()); - commasepstream sep(modes); - Anope::string modebuf; - while (sep.GetToken(modebuf)) - { + sep.GetToken(modebuf); for (size_t t = 0, end = modebuf.length(); t < end; ++t) { switch (modebuf[t]) { - case 'h': - ModeManager::AddUserMode(new UserMode(UMODE_HELPOP, "UMODE_HELPOP", 'h')); + case 'A': + ModeManager::AddChannelMode(new ChannelMode(CMODE_ALLINVITE, "CMODE_ALLINVITE", 'A')); continue; case 'B': - ModeManager::AddUserMode(new UserMode(UMODE_BOT, "UMODE_BOT", 'B')); + ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCAPS, "CMODE_BLOCKCAPS", 'B')); + continue; + case 'C': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOCTCP, "CMODE_NOCTCP", 'C')); + continue; + case 'D': + ModeManager::AddChannelMode(new ChannelMode(CMODE_DELAYEDJOIN, "CMODE_DELAYEDJOIN", 'D')); continue; case 'G': - ModeManager::AddUserMode(new UserMode(UMODE_FILTER, "UMODE_FILTER", 'G')); + ModeManager::AddChannelMode(new ChannelMode(CMODE_FILTER, "CMODE_FILTER", 'G')); continue; - case 'H': - ModeManager::AddUserMode(new UserMode(UMODE_HIDEOPER, "UMODE_HIDEOPER", 'H')); + case 'K': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKNOCK, "CMODE_NOKNOCK", 'K')); continue; - case 'I': - ModeManager::AddUserMode(new UserMode(UMODE_PRIV, "UMODE_PRIV", 'I')); + case 'M': + ModeManager::AddChannelMode(new ChannelMode(CMODE_REGMODERATED, "CMODE_REGMODERATED", 'M')); + continue; + case 'N': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NONICK, "CMODE_NONICK", 'N')); + continue; + case 'O': + ModeManager::AddChannelMode(new ChannelModeOper('O')); + continue; + case 'P': + ModeManager::AddChannelMode(new ChannelMode(CMODE_PERM, "CMODE_PERM", 'P')); continue; case 'Q': - ModeManager::AddUserMode(new UserMode(UMODE_HIDDEN, "UMODE_HIDDEN", 'Q')); + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKICK, "CMODE_NOKICK", 'Q')); continue; case 'R': - ModeManager::AddUserMode(new UserMode(UMODE_REGPRIV, "UMODE_REGPRIV", 'R')); + ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, "CMODE_REGISTEREDONLY", 'R')); continue; case 'S': - ModeManager::AddUserMode(new UserMode(UMODE_STRIPCOLOR, "UMODE_STRIPCOLOR", 'S')); + ModeManager::AddChannelMode(new ChannelMode(CMODE_STRIPCOLOR, "CMODE_STRIPCOLOR", 'S')); continue; - case 'W': - ModeManager::AddUserMode(new UserMode(UMODE_WHOIS, "UMODE_WHOIS", 'W')); + case 'T': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NONOTICE, "CMODE_NONOTICE", 'T')); continue; case 'c': - ModeManager::AddUserMode(new UserMode(UMODE_COMMONCHANS, "UMODE_COMMONCHANS", 'c')); - continue; - case 'g': - ModeManager::AddUserMode(new UserMode(UMODE_CALLERID, "UMODE_CALLERID", 'g')); + ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, "CMODE_BLOCKCOLOR", 'c')); continue; case 'i': - ModeManager::AddUserMode(new UserMode(UMODE_INVIS, "UMODE_INVIS", 'i')); + ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, "CMODE_INVITE", 'i')); continue; - case 'k': - ModeManager::AddUserMode(new UserMode(UMODE_PROTECTED, "UMODE_PROTECTED", 'k')); + case 'm': + ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, "CMODE_MODERATED", 'm')); continue; - case 'o': - ModeManager::AddUserMode(new UserMode(UMODE_OPER, "UMODE_OPER", 'o')); + case 'n': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, "CMODE_NOEXTERNAL", 'n')); + continue; + case 'p': + ModeManager::AddChannelMode(new ChannelMode(CMODE_PRIVATE, "CMODE_PRIVATE", 'p')); continue; case 'r': - ModeManager::AddUserMode(new UserMode(UMODE_REGISTERED, "UMODE_REGISTERED", 'r')); + ModeManager::AddChannelMode(new ChannelModeRegistered('r')); continue; - case 'w': - ModeManager::AddUserMode(new UserMode(UMODE_WALLOPS, "UMODE_WALLOPS", 'w')); + case 's': + ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, "CMODE_SECRET", 's')); continue; - case 'x': - ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, "UMODE_CLOAK", 'x')); + case 't': + ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, "CMODE_TOPIC", 't')); continue; - case 'd': - ModeManager::AddUserMode(new UserMode(UMODE_DEAF, "UMODE_DEAF", 'd')); + case 'u': + ModeManager::AddChannelMode(new ChannelMode(CMODE_AUDITORIUM, "CMODE_AUDITORIUM", 'u')); + continue; + case 'z': + ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, "CMODE_SSL", 'z')); continue; default: - ModeManager::AddUserMode(new UserMode(UMODE_END, "", modebuf[t])); + ModeManager::AddChannelMode(new ChannelMode(CMODE_END, "", modebuf[t])); } } } - } - else if (capab.find("PREFIX=(") != Anope::string::npos) - { - Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')')); - Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end()); + else if (capab.find("USERMODES") != Anope::string::npos) + { + Anope::string modes(capab.begin() + 10, capab.end()); + commasepstream sep(modes); + Anope::string modebuf; - for (size_t t = 0, end = modes.length(); t < end; ++t) + while (sep.GetToken(modebuf)) + { + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + switch (modebuf[t]) + { + case 'h': + ModeManager::AddUserMode(new UserMode(UMODE_HELPOP, "UMODE_HELPOP", 'h')); + continue; + case 'B': + ModeManager::AddUserMode(new UserMode(UMODE_BOT, "UMODE_BOT", 'B')); + continue; + case 'G': + ModeManager::AddUserMode(new UserMode(UMODE_FILTER, "UMODE_FILTER", 'G')); + continue; + case 'H': + ModeManager::AddUserMode(new UserMode(UMODE_HIDEOPER, "UMODE_HIDEOPER", 'H')); + continue; + case 'I': + ModeManager::AddUserMode(new UserMode(UMODE_PRIV, "UMODE_PRIV", 'I')); + continue; + case 'Q': + ModeManager::AddUserMode(new UserMode(UMODE_HIDDEN, "UMODE_HIDDEN", 'Q')); + continue; + case 'R': + ModeManager::AddUserMode(new UserMode(UMODE_REGPRIV, "UMODE_REGPRIV", 'R')); + continue; + case 'S': + ModeManager::AddUserMode(new UserMode(UMODE_STRIPCOLOR, "UMODE_STRIPCOLOR", 'S')); + continue; + case 'W': + ModeManager::AddUserMode(new UserMode(UMODE_WHOIS, "UMODE_WHOIS", 'W')); + continue; + case 'c': + ModeManager::AddUserMode(new UserMode(UMODE_COMMONCHANS, "UMODE_COMMONCHANS", 'c')); + continue; + case 'g': + ModeManager::AddUserMode(new UserMode(UMODE_CALLERID, "UMODE_CALLERID", 'g')); + continue; + case 'i': + ModeManager::AddUserMode(new UserMode(UMODE_INVIS, "UMODE_INVIS", 'i')); + continue; + case 'k': + ModeManager::AddUserMode(new UserMode(UMODE_PROTECTED, "UMODE_PROTECTED", 'k')); + continue; + case 'o': + ModeManager::AddUserMode(new UserMode(UMODE_OPER, "UMODE_OPER", 'o')); + continue; + case 'r': + ModeManager::AddUserMode(new UserMode(UMODE_REGISTERED, "UMODE_REGISTERED", 'r')); + continue; + case 'w': + ModeManager::AddUserMode(new UserMode(UMODE_WALLOPS, "UMODE_WALLOPS", 'w')); + continue; + case 'x': + ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, "UMODE_CLOAK", 'x')); + continue; + case 'd': + ModeManager::AddUserMode(new UserMode(UMODE_DEAF, "UMODE_DEAF", 'd')); + continue; + default: + ModeManager::AddUserMode(new UserMode(UMODE_END, "", modebuf[t])); + } + } + } + } + else if (capab.find("PREFIX=(") != Anope::string::npos) { - switch (modes[t]) + Anope::string modes(capab.begin() + 8, capab.begin() + capab.find(')')); + Anope::string chars(capab.begin() + capab.find(')') + 1, capab.end()); + + for (size_t t = 0, end = modes.length(); t < end; ++t) { - case 'q': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, "CMODE_OWNER", 'q', chars[t])); - continue; - case 'a': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, "CMODE_PROTECT", 'a', chars[t])); - continue; - case 'o': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, "CMODE_OP", 'o', chars[t])); - continue; - case 'h': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, "CMODE_HALFOP", 'h', chars[t])); - continue; - case 'v': - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, "CMODE_VOICE", 'v', chars[t])); - continue; + switch (modes[t]) + { + case 'q': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OWNER, "CMODE_OWNER", 'q', chars[t])); + continue; + case 'a': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_PROTECT, "CMODE_PROTECT", 'a', chars[t])); + continue; + case 'o': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, "CMODE_OP", 'o', chars[t])); + continue; + case 'h': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_HALFOP, "CMODE_HALFOP", 'h', chars[t])); + continue; + case 'v': + ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, "CMODE_VOICE", 'v', chars[t])); + continue; + } } } + 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; + } } - 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; - } - } - } - else if (params[0].equals_cs("END")) - { - if (!has_globopsmod) - { - send_cmd("", "ERROR :m_globops is not loaded. This is required by Anope"); - quitmsg = "Remote server does not have the m_globops module loaded, and this is required."; - quitting = true; - return MOD_STOP; } - if (!has_servicesmod) + else if (params[0].equals_cs("END")) { - send_cmd("", "ERROR :m_services_account.so is not loaded. This is required by Anope"); - quitmsg = "ERROR: Remote server does not have the m_services_account module loaded, and this is required."; - quitting = true; - return MOD_STOP; - } - if (!has_hidechansmod) - { - send_cmd("", "ERROR :m_hidechans.so is not loaded. This is required by Anope"); - quitmsg = "ERROR: Remote server does not have the m_hidechans module loaded, and this is required."; - quitting = true; - return MOD_STOP; + if (!has_globopsmod) + { + send_cmd("", "ERROR :m_globops is not loaded. This is required by Anope"); + quitmsg = "Remote server does not have the m_globops module loaded, and this is required."; + quitting = true; + return MOD_STOP; + } + if (!has_servicesmod) + { + send_cmd("", "ERROR :m_services_account.so is not loaded. This is required by Anope"); + quitmsg = "ERROR: Remote server does not have the m_services_account module loaded, and this is required."; + quitting = true; + return MOD_STOP; + } + if (!has_hidechansmod) + { + send_cmd("", "ERROR :m_hidechans.so is not loaded. This is required by Anope"); + quitmsg = "ERROR: Remote server does not have the m_hidechans module loaded, and this is required."; + quitting = true; + return MOD_STOP; + } + if (!has_svsholdmod) + ircdproto->SendGlobops(OperServ, "SVSHOLD missing, Usage disabled until module is loaded."); + if (!has_chghostmod) + ircdproto->SendGlobops(OperServ, "CHGHOST missing, Usage disabled until module is loaded."); + if (!has_chgidentmod) + ircdproto->SendGlobops(OperServ, "CHGIDENT missing, Usage disabled until module is loaded."); + ircd->svshold = has_svsholdmod; } - if (!has_svsholdmod) - ircdproto->SendGlobops(OperServ, "SVSHOLD missing, Usage disabled until module is loaded."); - if (!has_chghostmod) - ircdproto->SendGlobops(OperServ, "CHGHOST missing, Usage disabled until module is loaded."); - if (!has_chgidentmod) - ircdproto->SendGlobops(OperServ, "CHGIDENT missing, Usage disabled until module is loaded."); - ircd->svshold = has_svsholdmod; - } - - CapabParse(params); - return true; -} - -bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = prev_u_intro; - Server *s = Server::Find(source); - - if (!s) - throw CoreException("Got ENDBURST without a source"); - - /* Check if the previously introduced user was Id'd for the nickgroup of the nick he s currently using. - * If not, validate the user. ~ Viper*/ - prev_u_intro = NULL; - if (u && !u->server->IsSynced()) - { - NickAlias *na = findnick(u->nick); + IRCdMessage::OnCapab(source, params); - if (!na || na->nc != u->Account()) - { - validate_user(u); - if (u->HasMode(UMODE_REGISTERED)) - u->RemoveMode(NickServ, UMODE_REGISTERED); - } - else - /* Set them +r (to negate a possible -r on the stack) */ - u->SetMode(NickServ, UMODE_REGISTERED); + return true; } - - Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - - s->Sync(true); - return true; -} +}; bool ChannelModeFlood::IsValid(const Anope::string &value) const { @@ -1183,37 +700,37 @@ bool ChannelModeFlood::IsValid(const Anope::string &value) const class ProtoInspIRCd : public Module { - Message message_endburst, message_436, message_away, message_join, message_kick, message_kill, message_mode, message_motd, - message_nick, message_uid, message_capab, message_part, message_ping, message_time, message_privmsg, message_quit, - message_server, message_squit, message_rsquit, message_topic, message_whois, message_svsmode, message_fhost, + Message message_endburst, + message_uid, 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; + public: ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), - message_endburst("ENDBURST", event_endburst), message_436("436", event_436), message_away("AWAY", event_away), - message_join("JOIN", event_join), message_kick("KICK", event_kick), message_kill("KILL", event_kill), - message_mode("MODE", event_mode), message_motd("MOTD", event_motd), message_nick("NICK", event_nick), - message_uid("UID", event_uid), message_capab("CAPAB", event_capab), message_part("PART", event_part), - message_ping("PING", event_ping), message_time("TIME", event_time), message_privmsg("PRIVMSG", event_privmsg), - message_quit("QUIT", event_quit), message_server("SERVER", event_server), message_squit("SQUIT", event_squit), - message_rsquit("RSQUIT", event_rsquit), message_topic("TOPIC", event_topic), message_whois("WHOIS", event_whois), - message_svsmode("SVSMODE", event_mode), message_fhost("FHOST", event_chghost), + message_endburst("ENDBURST", event_endburst), message_uid("UID", event_uid), + 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", event_fjoin), message_fmode("FMODE", event_fmode), - message_ftopic("FTOPIC", event_ftopic), message_opertype("OPERTYPE", event_opertype), message_idle("IDLE", event_idle), + 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) { this->SetAuthor("Anope"); this->SetType(PROTOCOL); - pmodule_ircd_var(myIrcd); - CapabType c[] = { CAPAB_NOQUIT, CAPAB_SSJ3, CAPAB_NICK2, CAPAB_VL, CAPAB_TLKEXT }; for (unsigned i = 0; i < 5; ++i) Capab.SetFlag(c[i]); - pmodule_ircd_proto(&ircd_proto); + pmodule_ircd_var(myIrcd); + pmodule_ircd_proto(&this->ircd_proto); + pmodule_ircd_message(&this->ircd_message); ModuleManager::Attach(I_OnUserNickChange, this); } diff --git a/modules/protocol/inspircd20.cpp b/modules/protocol/inspircd20.cpp index e5abfcdde..bd020891d 100644 --- a/modules/protocol/inspircd20.cpp +++ b/modules/protocol/inspircd20.cpp @@ -13,7 +13,12 @@ #include "services.h" #include "modules.h" -#include "hashcomp.h" + +/* inspircd-ts6.h uses these */ +static bool has_chghostmod = false; +static bool has_chgidentmod = false; +static bool has_globopsmod = true; // Not a typo +#include "inspircd-ts6.h" IRCDVar myIrcd[] = { {"InspIRCd 2.0", /* ircd name */ @@ -45,8 +50,6 @@ IRCDVar myIrcd[] = { static bool has_servicesmod = false; static bool has_svsholdmod = false; -static bool has_chghostmod = false; -static bool has_chgidentmod = false; /* Previously introduced user during burst */ static User *prev_u_intro = NULL; @@ -71,235 +74,18 @@ bool event_idle(const Anope::string &source, const std::vector<Anope::string> &p return true; } -static Anope::string currentpass; - -/* PASS */ -void inspircd_cmd_pass(const Anope::string &pass) -{ - currentpass = pass; -} - -class InspIRCdProto : public IRCDProto +class InspIRCdProto : public InspIRCdTS6Proto { - void SendAkillDel(const XLine *x) - { - send_cmd(OperServ ? OperServ->GetUID() : Config->Numeric, "GLINE %s", x->Mask.c_str()); - } - - void SendTopic(BotInfo *whosets, Channel *c) - { - send_cmd(whosets->GetUID(), "FTOPIC %s %lu %s :%s", c->name.c_str(), static_cast<unsigned long>(c->topic_time + 1), c->topic_setter.c_str(), c->topic.c_str()); - } - - void SendVhostDel(User *u) - { - if (u->HasMode(UMODE_CLOAK)) - inspircd_cmd_chghost(u->nick, u->chost); - else - inspircd_cmd_chghost(u->nick, u->host); - - if (has_chgidentmod && u->GetIdent() != u->GetVIdent()) - inspircd_cmd_chgident(u->nick, u->GetIdent()); - } - - void SendAkill(const XLine *x) - { - // Calculate the time left before this would expire, capping it at 2 days - time_t timeleft = x->Expires - Anope::CurTime; - if (timeleft > 172800 || !x->Expires) - timeleft = 172800; - send_cmd(OperServ ? OperServ->GetUID() : Config->Numeric, "ADDLINE G %s@%s %s %ld %ld :%s", x->GetUser().c_str(), x->GetHost().c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime), static_cast<long>(timeleft), x->Reason.c_str()); - } - - void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) - { - send_cmd(source ? source->GetUID() : Config->Numeric, "KILL %s :%s", user->GetUID().c_str(), buf.c_str()); - } - - void SendSVSMode(const User *u, int ac, const char **av) - { - this->SendModeInternal(NULL, u, merge_args(ac, av)); - } - - void SendNumericInternal(const Anope::string &source, int numeric, const Anope::string &dest, const Anope::string &buf) - { - send_cmd(Config->Numeric, "PUSH %s ::%s %03d %s %s", dest.c_str(), source.c_str(), numeric, dest.c_str(), buf.c_str()); - } - - void SendModeInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - send_cmd(source ? source->GetUID() : Config->Numeric, "FMODE %s %u %s", dest->name.c_str(), static_cast<unsigned>(dest->creation_time), buf.c_str()); - } - - void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) - { - if (buf.empty()) - return; - send_cmd(bi ? bi->GetUID() : Config->Numeric, "MODE %s %s", u->GetUID().c_str(), buf.c_str()); - } - - void SendClientIntroduction(const User *u, const Anope::string &modes) - { - send_cmd(Config->Numeric, "UID %s %ld %s %s %s %s 0.0.0.0 %ld %s :%s", u->GetUID().c_str(), static_cast<long>(u->timestamp), u->nick.c_str(), u->host.c_str(), u->host.c_str(), u->GetIdent().c_str(), static_cast<long>(u->my_signon), modes.c_str(), u->realname.c_str()); - } - - void SendKickInternal(const BotInfo *source, const Channel *chan, const User *user, const Anope::string &buf) - { - if (!buf.empty()) - send_cmd(source->GetUID(), "KICK %s %s :%s", chan->name.c_str(), user->GetUID().c_str(), buf.c_str()); - else - send_cmd(source->GetUID(), "KICK %s %s :%s", chan->name.c_str(), user->GetUID().c_str(), user->nick.c_str()); - } - - void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { - send_cmd(Config->Numeric, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); - } - - /* SERVER services-dev.chatspike.net password 0 :Description here */ - void SendServer(const Server *server) - { - send_cmd("", "SERVER %s %s %d %s :%s", server->GetName().c_str(), currentpass.c_str(), server->GetHops(), server->GetSID().c_str(), server->GetDescription().c_str()); - } - - /* JOIN */ - void SendJoin(const BotInfo *user, const Anope::string &channel, time_t chantime) - { - send_cmd(Config->Numeric, "FJOIN %s %ld + :,%s", channel.c_str(), static_cast<long>(chantime), user->GetUID().c_str()); - } - - void SendJoin(BotInfo *user, const ChannelContainer *cc) - { - send_cmd(Config->Numeric, "FJOIN %s %ld +%s :%s,%s", cc->chan->name.c_str(), static_cast<long>(cc->chan->creation_time), cc->chan->GetModes(true, true).c_str(), cc->Status->BuildCharPrefixList().c_str(), user->GetUID().c_str()); - } - - /* UNSQLINE */ - void SendSQLineDel(const XLine *x) - { - send_cmd(Config->Numeric, "DELLINE Q %s", x->Mask.c_str()); - } - - /* SQLINE */ - void SendSQLine(const XLine *x) - { - send_cmd(Config->Numeric, "ADDLINE Q %s %s %ld 0 :%s", x->Mask.c_str(), Config->s_OperServ.c_str(), static_cast<long>(Anope::CurTime), x->Reason.c_str()); - } - - /* SQUIT */ - void SendSquit(const Anope::string &servname, const Anope::string &message) - { - send_cmd(Config->Numeric, "SQUIT %s :%s", servname.c_str(), message.c_str()); - } - - /* Functions that use serval cmd functions */ - - void SendVhost(User *u, const Anope::string &vIdent, const Anope::string &vhost) - { - if (!vIdent.empty()) - inspircd_cmd_chgident(u->nick, vIdent); - if (!vhost.empty()) - inspircd_cmd_chghost(u->nick, vhost); - } - void SendConnect() { send_cmd("", "CAPAB START 1202"); send_cmd("", "CAPAB CAPABILITIES :PROTOCOL=1202"); send_cmd("", "CAPAB END"); - inspircd_cmd_pass(uplink_server->password); SendServer(Me); send_cmd(Config->Numeric, "BURST"); send_cmd(Config->Numeric, "VERSION :Anope-%s %s :%s - (%s) -- %s", Anope::Version().c_str(), Config->ServerName.c_str(), ircd->name, Config->EncModuleList.begin()->c_str(), Anope::Build().c_str()); } - - /* CHGIDENT */ - void inspircd_cmd_chgident(const Anope::string &nick, const Anope::string &vIdent) - { - if (!has_chgidentmod) - ircdproto->SendGlobops(OperServ, "CHGIDENT not loaded!"); - else - send_cmd(HostServ ? HostServ->GetUID() : Config->Numeric, "CHGIDENT %s %s", nick.c_str(), vIdent.c_str()); - } - - /* SVSHOLD - set */ - void SendSVSHold(const Anope::string &nick) - { - send_cmd(NickServ->GetUID(), "SVSHOLD %s %u :Being held for registered user", nick.c_str(), static_cast<unsigned>(Config->NSReleaseTimeout)); - } - - /* SVSHOLD - release */ - void SendSVSHoldDel(const Anope::string &nick) - { - send_cmd(NickServ->GetUID(), "SVSHOLD %s", nick.c_str()); - } - - /* UNSZLINE */ - void SendSZLineDel(const XLine *x) - { - send_cmd(Config->Numeric, "DELLINE Z %s", x->Mask.c_str()); - } - - /* SZLINE */ - void SendSZLine(const XLine *x) - { - send_cmd(Config->Numeric, "ADDLINE Z %s %s %ld 0 :%s", x->Mask.c_str(), x->By.c_str(), static_cast<long>(Anope::CurTime), x->Reason.c_str()); - } - - void SendSVSJoin(const Anope::string &source, const Anope::string &nick, const Anope::string &chan, const Anope::string &) - { - User *u = finduser(nick); - BotInfo *bi = findbot(source); - send_cmd(bi->GetUID(), "SVSJOIN %s %s", u->GetUID().c_str(), chan.c_str()); - } - - void SendSVSPart(const Anope::string &source, const Anope::string &nick, const Anope::string &chan) - { - User *u = finduser(nick); - BotInfo *bi = findbot(source); - send_cmd(bi->GetUID(), "SVSPART %s %s", u->GetUID().c_str(), chan.c_str()); - } - - void SendSWhois(const Anope::string &, const Anope::string &who, const Anope::string &mask) - { - User *u = finduser(who); - - send_cmd(Config->Numeric, "METADATA %s swhois :%s", u->GetUID().c_str(), mask.c_str()); - } - - void SendBOB() - { - send_cmd(Config->Numeric, "BURST %ld", static_cast<long>(Anope::CurTime)); - } - - void SendEOB() - { - send_cmd(Config->Numeric, "ENDBURST"); - } - - void SendGlobopsInternal(BotInfo *source, const Anope::string &buf) - { - send_cmd(source ? source->GetUID() : Config->Numeric, "SNONOTICE g :%s", buf.c_str()); - } - - void SendAccountLogin(const User *u, const NickCore *account) - { - send_cmd(Config->Numeric, "METADATA %s accountname :%s", u->GetUID().c_str(), account->display.c_str()); - } - - void SendAccountLogout(const User *u, const NickCore *account) - { - send_cmd(Config->Numeric, "METADATA %s accountname :", u->GetUID().c_str()); - } - - bool IsNickValid(const Anope::string &nick) - { - /* InspIRCd, like TS6, uses UIDs on collision, so... */ - if (isdigit(nick[0])) - return false; - - return true; - } -} ircd_proto; +}; bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) { @@ -319,45 +105,18 @@ bool event_ftopic(const Anope::string &source, const std::vector<Anope::string> return true; } -bool event_mode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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); - User *u2 = finduser(params[0]); - - // This can happen with server-origin modes. - if (!u) - u = u2; - - // if it's still null, drop it like fire. - // most likely situation was that server introduced a nick which we subsequently akilled - if (!u || !u2) - return true; - - do_umode(u->nick, u2->nick, params[1]); - } - 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; u = finduser(source); - if (u && !is_oper(u)) + if (u && !u->HasMode(UMODE_OPER)) { std::vector<Anope::string> newparams; newparams.push_back(source); newparams.push_back("+o"); - return event_mode(source, newparams); + return ircdmessage->OnMode(source, newparams); } return true; } @@ -393,128 +152,7 @@ bool event_fmode(const Anope::string &source, const std::vector<Anope::string> & modes += " " + params[n]; newparams.push_back(modes); - return event_mode(source, newparams); -} - -/* - * [Nov 03 22:31:57.695076 2009] debug: Received: :964 FJOIN #test 1223763723 +BPSnt :,964AAAAAB ,964AAAAAC ,966AAAAAA - * - * 0: name - * 1: channel ts (when it was created, see protocol docs for more info) - * 2: channel modes + params (NOTE: this may definitely be more than one param!) - * last: users - */ -bool event_fjoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Channel *c = findchan(params[0]); - time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0; - bool keep_their_modes = true; - - if (!c) - { - c = new Channel(params[0], ts); - c->SetFlag(CH_SYNCING); - } - /* Our creation time is newer than what the server gave us */ - else if (c->creation_time > ts) - { - c->creation_time = ts; - c->Reset(); - - /* Reset mlock */ - check_modes(c); - } - /* Their TS is newer than ours, our modes > theirs, unset their modes */ - else if (ts > c->creation_time) - keep_their_modes = false; - - /* If we need to keep their modes, and this FJOIN string contains modes */ - if (keep_their_modes && params.size() >= 3) - { - Anope::string modes; - for (unsigned i = 2; i < params.size() - 1; ++i) - modes += " " + params[i]; - if (!modes.empty()) - modes.erase(modes.begin()); - /* Set the modes internally */ - c->SetModesInternal(NULL, modes); - } - - spacesepstream sep(params[params.size() - 1]); - Anope::string buf; - while (sep.GetToken(buf)) - { - std::list<ChannelMode *> Status; - - /* Loop through prefixes and find modes for them */ - while (buf[0] != ',') - { - ChannelMode *cm = ModeManager::FindChannelModeByChar(buf[0]); - if (!cm) - { - Log() << "Recieved unknown mode prefix " << buf[0] << " in FJOIN string"; - buf.erase(buf.begin()); - continue; - } - - buf.erase(buf.begin()); - if (keep_their_modes) - Status.push_back(cm); - } - buf.erase(buf.begin()); - - User *u = finduser(buf); - if (!u) - { - Log(LOG_DEBUG) << "FJOIN for nonexistant user " << buf << " on " << c->name; - continue; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - - /* Add the user to the channel */ - c->JoinUser(u); - - /* Update their status internally on the channel - * 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(*it, buf); - - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1); - - /* 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)) - continue; - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); - } - - /* Channel is done syncing */ - if (c->HasFlag(CH_SYNCING)) - { - /* Unset the syncing flag */ - c->UnsetFlag(CH_SYNCING); - c->Sync(); - } - - return true; -} - -/* Events */ -bool event_ping(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() == 1) - ircdproto->SendPong("", params[0]); - else if (params.size() == 2) - ircdproto->SendPong(params[1], params[0]); - - return true; + return ircdmessage->OnMode(source, newparams); } bool event_time(const Anope::string &source, const std::vector<Anope::string> ¶ms) @@ -523,43 +161,6 @@ bool event_time(const Anope::string &source, const std::vector<Anope::string> &p return true; send_cmd(Config->Numeric, "TIME %s %s %ld", source.c_str(), params[1].c_str(), static_cast<long>(Anope::CurTime)); - - /* We handled it, don't pass it on to the core.. - * The core doesn't understand our syntax anyways.. ~ Viper */ - return MOD_STOP; -} - -bool event_436(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - m_nickcoll(params[0]); - return true; -} - -bool event_away(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - m_away(source, !params.empty() ? params[0] : ""); - return true; -} - -/* Taken from hybrid.c, topic syntax is identical */ -bool event_topic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Channel *c = findchan(params[0]); - - if (!c) - { - Log() << "TOPIC " << (params.size() > 1 ? params[1] : "") << " for nonexistent channel " << params[0]; - return true; - } - - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : ""), Anope::CurTime); - - return true; -} - -bool event_squit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_squit(source, params[0]); return true; } @@ -570,43 +171,11 @@ bool event_rsquit(const Anope::string &source, const std::vector<Anope::string> if (s && s->HasFlag(SERVER_JUPED)) send_cmd(Config->Numeric, "SQUIT %s :%s", s->GetSID().c_str(), params.size() > 1 ? params[1].c_str() : ""); - do_squit(source, params[0]); + ircdmessage->OnSQuit(source, params); return true; } -bool event_quit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_quit(source, params[0]); - return true; -} - -bool event_kill(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(params[0]); - BotInfo *bi = findbot(params[0]); - m_kill(u ? u->nick : (bi ? bi->nick : params[0]), params[1]); - return true; -} - -bool event_kick(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_kick(source, params[0], params[1], params[2]); - return true; -} - -bool event_join(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_join(source, params[0], (params.size() > 1 ? params[1] : "")); - return true; -} - -bool event_motd(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - m_motd(source); - return true; -} - bool event_setname(const Anope::string &source, const std::vector<Anope::string> ¶ms) { User *u; @@ -681,12 +250,6 @@ bool event_sethost(const Anope::string &source, const std::vector<Anope::string> return true; } -bool event_nick(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_nick(source, params[0], "", "", "", "", 0, "", "", "", ""); - return true; -} - /* * [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 @@ -754,42 +317,6 @@ bool event_chghost(const Anope::string &source, const std::vector<Anope::string> return true; } -/* - * [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 event_server(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - do_server(source, params[0], Anope::string(params[2]).is_pos_number_only() ? convertTo<unsigned>(params[2]) : 0, params[4], params[3]); - return true; -} - -bool event_privmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!finduser(source)) - return true; // likely a message from a server, which can happen. - - m_privmsg(source, params[0], params[1]); - return true; -} - -bool event_part(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_part(source, params[0], params.size() > 1 ? params[1] : ""); - return true; -} - -bool event_whois(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - m_whois(source, params[0]); - return true; -} - bool event_metadata(const Anope::string &source, const std::vector<Anope::string> ¶ms) { if (params.size() < 3) @@ -807,351 +334,352 @@ bool event_metadata(const Anope::string &source, const std::vector<Anope::string return true; } -bool event_capab(const Anope::string &source, const std::vector<Anope::string> ¶ms) +bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - if (params[0].equals_cs("START")) - { - if (params.size() < 2 || (Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]): 0) < 1202) - { - send_cmd("", "ERROR :Protocol mismatch, no or invalid protocol version given in CAPAB START"); - quitmsg = "Protocol mismatch, no or invalid protocol version given in CAPAB START"; - quitting = true; - return MOD_STOP; - } + User *u = prev_u_intro; + Server *s = Server::Find(source); - /* reset CAPAB */ - has_servicesmod = false; - has_svsholdmod = false; - has_chghostmod = false; - has_chgidentmod = false; - } - else if (params[0].equals_cs("CHANMODES")) - { - spacesepstream ssep(params[1]); - Anope::string capab; + if (!s) + throw CoreException("Got ENDBURST without a source"); - while (ssep.GetToken(capab)) - { - Anope::string modename = capab.substr(0, capab.find('=')); - Anope::string modechar = capab.substr(capab.find('=') + 1); - ChannelMode *cm = NULL; - - if (modename.equals_cs("admin")) - cm = new ChannelModeStatus(CMODE_PROTECT, "CMODE_PROTECT", modechar[1], modechar[0]); - else if (modename.equals_cs("allowinvite")) - cm = new ChannelMode(CMODE_ALLINVITE, "CMODE_ALLINVITE", modechar[0]); - else if (modename.equals_cs("auditorium")) - cm = new ChannelMode(CMODE_AUDITORIUM, "CMODE_AUDITORIUM", modechar[0]); - else if (modename.equals_cs("autoop")) - continue; // XXX Not currently tracked - else if (modename.equals_cs("ban")) - cm = new ChannelModeBan(modechar[0]); - else if (modename.equals_cs("banexception")) - cm = new ChannelModeExcept(modechar[0]); - else if (modename.equals_cs("blockcaps")) - cm = new ChannelMode(CMODE_BLOCKCAPS, "CMODE_BLOCKCAPS", modechar[0]); - else if (modename.equals_cs("blockcolor")) - cm = new ChannelMode(CMODE_BLOCKCOLOR, "CMODE_BLOCKCOLOR", modechar[0]); - else if (modename.equals_cs("c_registered")) - cm = new ChannelModeRegistered(modechar[0]); - else if (modename.equals_cs("censor")) - cm = new ChannelMode(CMODE_FILTER, "CMODE_FILTER", modechar[0]); - else if (modename.equals_cs("delayjoin")) - cm = new ChannelMode(CMODE_DELAYEDJOIN, "CMODE_DELAYEDJOIN", modechar[0]); - else if (modename.equals_cs("delaymsg")) - continue; - else if (modename.equals_cs("exemptchanops")) - continue; // XXX - else if (modename.equals_cs("filter")) - continue; // XXX - else if (modename.equals_cs("flood")) - cm = new ChannelModeFlood(modechar[0], true); - else if (modename.equals_cs("founder")) - cm = new ChannelModeStatus(CMODE_OWNER, "CMODE_OWNER", modechar[1], modechar[0]); - else if (modename.equals_cs("halfop")) - cm = new ChannelModeStatus(CMODE_HALFOP, "CMODE_HALFOP", modechar[1], modechar[0]); - else if (modename.equals_cs("history")) - continue; // XXX - else if (modename.equals_cs("invex")) - cm = new ChannelModeInvex(modechar[0]); - else if (modename.equals_cs("inviteonly")) - cm = new ChannelMode(CMODE_INVITE, "CMODE_INVITE", modechar[0]); - else if (modename.equals_cs("joinflood")) - cm = new ChannelModeParam(CMODE_JOINFLOOD, "CMODE_JOINFLOOD", modechar[0], true); - else if (modename.equals_cs("key")) - cm = new ChannelModeKey(modechar[0]); - else if (modename.equals_cs("kicknorejoin")) - cm = new ChannelModeParam(CMODE_NOREJOIN, "CMODE_NOREJOIN", modechar[0], true); - else if (modename.equals_cs("limit")) - cm = new ChannelModeParam(CMODE_LIMIT, "CMODE_LIMIT", modechar[0], true); - else if (modename.equals_cs("moderated")) - cm = new ChannelMode(CMODE_MODERATED, "CMODE_MODERATED", modechar[0]); - else if (modename.equals_cs("namebase")) - continue; // XXX - else if (modename.equals_cs("nickflood")) - cm = new ChannelModeParam(CMODE_NICKFLOOD, "CMODE_NICKFLOOD", modechar[0], true); - else if (modename.equals_cs("noctcp")) - cm = new ChannelMode(CMODE_NOCTCP, "CMODE_NOCTCP", modechar[0]); - else if (modename.equals_cs("noextmsg")) - cm = new ChannelMode(CMODE_NOEXTERNAL, "CMODE_NOEXTERNAL", modechar[0]); - else if (modename.equals_cs("nokick")) - cm = new ChannelMode(CMODE_NOKICK, "CMODE_NOKICK", modechar[0]); - else if (modename.equals_cs("noknock")) - cm = new ChannelMode(CMODE_NOKNOCK, "CMODE_NOKNOCK", modechar[0]); - else if (modename.equals_cs("nonick")) - cm = new ChannelMode(CMODE_NONICK, "CMODE_NONICK", modechar[0]); - else if (modename.equals_cs("nonotice")) - cm = new ChannelMode(CMODE_NONOTICE, "CMODE_NONOTICE", modechar[0]); - else if (modename.equals_cs("op")) - cm = new ChannelModeStatus(CMODE_OP, "CMODE_OP", modechar[1], modechar[0]); - else if (modename.equals_cs("operonly")) - cm = new ChannelModeOper(modechar[0]); - else if (modename.equals_cs("permanent")) - cm = new ChannelMode(CMODE_PERM, "CMODE_PERM", modechar[0]); - else if (modename.equals_cs("private")) - cm = new ChannelMode(CMODE_PRIVATE, "CMODE_PRIVATE", modechar[0]); - else if (modename.equals_cs("redirect")) - cm = new ChannelModeParam(CMODE_REDIRECT, "CMODE_REDIRECT", modechar[0], true); - else if (modename.equals_cs("reginvite")) - cm = new ChannelMode(CMODE_REGISTEREDONLY, "CMODE_REGISTEREDONLY", modechar[0]); - else if (modename.equals_cs("regmoderated")) - cm = new ChannelMode(CMODE_REGMODERATED, "CMODE_REGMODERATED", modechar[0]); - else if (modename.equals_cs("secret")) - cm = new ChannelMode(CMODE_SECRET, "CMODE_SECRET", modechar[0]); - else if (modename.equals_cs("sslonly")) - cm = new ChannelMode(CMODE_SSL, "CMODE_SSL", modechar[0]); - else if (modename.equals_cs("stripcolor")) - cm = new ChannelMode(CMODE_STRIPCOLOR, "CMODE_STRIPCOLOR", modechar[0]); - else if (modename.equals_cs("topiclock")) - cm = new ChannelMode(CMODE_TOPIC, "CMODE_TOPIC", modechar[0]); - else if (modename.equals_cs("voice")) - cm = new ChannelModeStatus(CMODE_VOICE, "CMODE_VOICE", modechar[1], modechar[0]); - /* Unknown status mode, (customprefix) - add it */ - else if (modechar.length() == 2) - cm = new ChannelModeStatus(CMODE_END, "", modechar[1], modechar[0]); - - if (cm) - ModeManager::AddChannelMode(cm); - else - Log() << "Unrecognized mode string in CAPAB CHANMODES: " << capab; - } - } - if (params[0].equals_cs("USERMODES")) + /* Check if the previously introduced user was Id'd for the nickgroup of the nick he s currently using. + * If not, validate the user. ~ Viper*/ + prev_u_intro = NULL; + if (u && !u->server->IsSynced()) { - spacesepstream ssep(params[1]); - Anope::string capab; + NickAlias *na = findnick(u->nick); - while (ssep.GetToken(capab)) + if (!na || na->nc != u->Account()) { - Anope::string modename = capab.substr(0, capab.find('=')); - Anope::string modechar = capab.substr(capab.find('=') + 1); - UserMode *um = NULL; - - if (modename.equals_cs("bot")) - um = new UserMode(UMODE_BOT, "UMODE_BOT", modechar[0]); - else if (modename.equals_cs("callerid")) - um = new UserMode(UMODE_CALLERID, "UMODE_CALLERID", modechar[0]); - else if (modename.equals_cs("cloak")) - um = new UserMode(UMODE_CLOAK, "UMODE_CLOAK", modechar[0]); - else if (modename.equals_cs("deaf")) - um = new UserMode(UMODE_DEAF, "UMODE_DEAF", modechar[0]); - else if (modename.equals_cs("deaf_commonchan")) - um = new UserMode(UMODE_COMMONCHANS, "UMODE_COMMONCHANS", modechar[0]); - else if (modename.equals_cs("helpop")) - um = new UserMode(UMODE_HELPOP, "UMODE_HELPOP", modechar[0]); - else if (modename.equals_cs("hidechans")) - um = new UserMode(UMODE_PRIV, "UMODE_PRIV", modechar[0]); - else if (modename.equals_cs("hideoper")) - um = new UserMode(UMODE_HIDEOPER, "UMODE_HIDEOPER", modechar[0]); - else if (modename.equals_cs("invisible")) - um = new UserMode(UMODE_INVIS, "UMODE_INVIS", modechar[0]); - else if (modename.equals_cs("invis-oper")) - um = new UserMode(UMODE_INVISIBLE_OPER, "UMODE_INVISIBLE_OPER", modechar[0]); - else if (modename.equals_cs("oper")) - um = new UserMode(UMODE_OPER, "UMODE_OPER", modechar[0]); - else if (modename.equals_cs("regdeaf")) - um = new UserMode(UMODE_REGPRIV, "UMODE_REGPRIV", modechar[0]); - else if (modename.equals_cs("servprotect")) - um = new UserMode(UMODE_PROTECTED, "UMODE_PROTECTED", modechar[0]); - else if (modename.equals_cs("showwhois")) - um = new UserMode(UMODE_WHOIS, "UMODE_WHOIS", modechar[0]); - else if (modename.equals_cs("snomask")) - continue; // XXX - else if (modename.equals_cs("u_censor")) - um = new UserMode(UMODE_FILTER, "UMODE_FILTER", modechar[0]); - else if (modename.equals_cs("u_registered")) - um = new UserMode(UMODE_REGISTERED, "UMODE_REGISTERED", modechar[0]); - else if (modename.equals_cs("u_stripcolor")) - um = new UserMode(UMODE_STRIPCOLOR, "UMODE_STRIPCOLOR", modechar[0]); - else if (modename.equals_cs("wallops")) - um = new UserMode(UMODE_WALLOPS, "UMODE_WALLOPS", modechar[0]); - - if (um) - ModeManager::AddUserMode(um); - else - Log() << "Unrecognized mode string in CAPAB USERMODES: " << capab; + validate_user(u); + if (u->HasMode(UMODE_REGISTERED)) + u->RemoveMode(NickServ, UMODE_REGISTERED); } + else + /* Set them +r (to negate a possible -r on the stack) */ + u->SetMode(NickServ, UMODE_REGISTERED); } - else if (params[0].equals_cs("MODULES")) - { - spacesepstream ssep(params[1]); - Anope::string module; - while (ssep.GetToken(module)) - if (module.equals_cs("m_svshold.so")) - has_svsholdmod = true; - } - else if (params[0].equals_cs("MODSUPPORT")) - { - spacesepstream ssep(params[1]); - Anope::string module; + Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - while (ssep.GetToken(module)) - { - if (module.equals_cs("m_services_account.so")) - has_servicesmod = true; - else if (module.equals_cs("m_chghost.so")) - has_chghostmod = true; - else if (module.equals_cs("m_chgident.so")) - has_chgidentmod = true; - else if (module.equals_cs("m_servprotect.so")) - ircd->pseudoclient_mode = "+Ik"; - } - } - else if (params[0].equals_cs("CAPABILITIES")) + s->Sync(true); + return true; +} + +class Inspircd20IRCdMessage : public InspircdIRCdMessage +{ + public: + bool OnCapab(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - spacesepstream ssep(params[1]); - Anope::string capab; - while (ssep.GetToken(capab)) + if (params[0].equals_cs("START")) { - if (capab.find("CHANMODES") != Anope::string::npos) + if (params.size() < 2 || (Anope::string(params[1]).is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0) < 1202) { - Anope::string modes(capab.begin() + 10, capab.end()); - commasepstream sep(modes); - Anope::string modebuf; - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - if (ModeManager::FindChannelModeByChar(modebuf[t])) - continue; - // XXX list modes needs a bit of a rewrite - ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, "", modebuf[t])); - } - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - if (ModeManager::FindChannelModeByChar(modebuf[t])) - continue; - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t])); - } - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - if (ModeManager::FindChannelModeByChar(modebuf[t])) - continue; - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t], true)); - } - - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - { - if (ModeManager::FindChannelModeByChar(modebuf[t])) - continue; - ModeManager::AddChannelMode(new ChannelMode(CMODE_END, "", modebuf[t])); - } + send_cmd("", "ERROR :Protocol mismatch, no or invalid protocol version given in CAPAB START"); + quitmsg = "Protocol mismatch, no or invalid protocol version given in CAPAB START"; + quitting = true; + return MOD_STOP; } - else if (capab.find("USERMODES") != Anope::string::npos) - { - Anope::string modes(capab.begin() + 10, capab.end()); - commasepstream sep(modes); - Anope::string modebuf; - - sep.GetToken(modebuf); - sep.GetToken(modebuf); - if (sep.GetToken(modebuf)) - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - ModeManager::AddUserMode(new UserModeParam(UMODE_END, "", modebuf[t])); + /* reset CAPAB */ + has_servicesmod = false; + has_svsholdmod = false; + has_chghostmod = false; + has_chgidentmod = false; + } + else if (params[0].equals_cs("CHANMODES")) + { + spacesepstream ssep(params[1]); + Anope::string capab; - if (sep.GetToken(modebuf)) - for (size_t t = 0, end = modebuf.length(); t < end; ++t) - ModeManager::AddUserMode(new UserMode(UMODE_END, "", modebuf[t])); + while (ssep.GetToken(capab)) + { + Anope::string modename = capab.substr(0, capab.find('=')); + Anope::string modechar = capab.substr(capab.find('=') + 1); + ChannelMode *cm = NULL; + + if (modename.equals_cs("admin")) + cm = new ChannelModeStatus(CMODE_PROTECT, "CMODE_PROTECT", modechar[1], modechar[0]); + else if (modename.equals_cs("allowinvite")) + cm = new ChannelMode(CMODE_ALLINVITE, "CMODE_ALLINVITE", modechar[0]); + else if (modename.equals_cs("auditorium")) + cm = new ChannelMode(CMODE_AUDITORIUM, "CMODE_AUDITORIUM", modechar[0]); + else if (modename.equals_cs("autoop")) + continue; // XXX Not currently tracked + else if (modename.equals_cs("ban")) + cm = new ChannelModeBan(modechar[0]); + else if (modename.equals_cs("banexception")) + cm = new ChannelModeExcept(modechar[0]); + else if (modename.equals_cs("blockcaps")) + cm = new ChannelMode(CMODE_BLOCKCAPS, "CMODE_BLOCKCAPS", modechar[0]); + else if (modename.equals_cs("blockcolor")) + cm = new ChannelMode(CMODE_BLOCKCOLOR, "CMODE_BLOCKCOLOR", modechar[0]); + else if (modename.equals_cs("c_registered")) + cm = new ChannelModeRegistered(modechar[0]); + else if (modename.equals_cs("censor")) + cm = new ChannelMode(CMODE_FILTER, "CMODE_FILTER", modechar[0]); + else if (modename.equals_cs("delayjoin")) + cm = new ChannelMode(CMODE_DELAYEDJOIN, "CMODE_DELAYEDJOIN", modechar[0]); + else if (modename.equals_cs("delaymsg")) + continue; + else if (modename.equals_cs("exemptchanops")) + continue; // XXX + else if (modename.equals_cs("filter")) + continue; // XXX + else if (modename.equals_cs("flood")) + cm = new ChannelModeFlood(modechar[0], true); + else if (modename.equals_cs("founder")) + cm = new ChannelModeStatus(CMODE_OWNER, "CMODE_OWNER", modechar[1], modechar[0]); + else if (modename.equals_cs("halfop")) + cm = new ChannelModeStatus(CMODE_HALFOP, "CMODE_HALFOP", modechar[1], modechar[0]); + else if (modename.equals_cs("history")) + continue; // XXX + else if (modename.equals_cs("invex")) + cm = new ChannelModeInvex(modechar[0]); + else if (modename.equals_cs("inviteonly")) + cm = new ChannelMode(CMODE_INVITE, "CMODE_INVITE", modechar[0]); + else if (modename.equals_cs("joinflood")) + cm = new ChannelModeParam(CMODE_JOINFLOOD, "CMODE_JOINFLOOD", modechar[0], true); + else if (modename.equals_cs("key")) + cm = new ChannelModeKey(modechar[0]); + else if (modename.equals_cs("kicknorejoin")) + cm = new ChannelModeParam(CMODE_NOREJOIN, "CMODE_NOREJOIN", modechar[0], true); + else if (modename.equals_cs("limit")) + cm = new ChannelModeParam(CMODE_LIMIT, "CMODE_LIMIT", modechar[0], true); + else if (modename.equals_cs("moderated")) + cm = new ChannelMode(CMODE_MODERATED, "CMODE_MODERATED", modechar[0]); + else if (modename.equals_cs("namebase")) + continue; // XXX + else if (modename.equals_cs("nickflood")) + cm = new ChannelModeParam(CMODE_NICKFLOOD, "CMODE_NICKFLOOD", modechar[0], true); + else if (modename.equals_cs("noctcp")) + cm = new ChannelMode(CMODE_NOCTCP, "CMODE_NOCTCP", modechar[0]); + else if (modename.equals_cs("noextmsg")) + cm = new ChannelMode(CMODE_NOEXTERNAL, "CMODE_NOEXTERNAL", modechar[0]); + else if (modename.equals_cs("nokick")) + cm = new ChannelMode(CMODE_NOKICK, "CMODE_NOKICK", modechar[0]); + else if (modename.equals_cs("noknock")) + cm = new ChannelMode(CMODE_NOKNOCK, "CMODE_NOKNOCK", modechar[0]); + else if (modename.equals_cs("nonick")) + cm = new ChannelMode(CMODE_NONICK, "CMODE_NONICK", modechar[0]); + else if (modename.equals_cs("nonotice")) + cm = new ChannelMode(CMODE_NONOTICE, "CMODE_NONOTICE", modechar[0]); + else if (modename.equals_cs("op")) + cm = new ChannelModeStatus(CMODE_OP, "CMODE_OP", modechar[1], modechar[0]); + else if (modename.equals_cs("operonly")) + cm = new ChannelModeOper(modechar[0]); + else if (modename.equals_cs("permanent")) + cm = new ChannelMode(CMODE_PERM, "CMODE_PERM", modechar[0]); + else if (modename.equals_cs("private")) + cm = new ChannelMode(CMODE_PRIVATE, "CMODE_PRIVATE", modechar[0]); + else if (modename.equals_cs("redirect")) + cm = new ChannelModeParam(CMODE_REDIRECT, "CMODE_REDIRECT", modechar[0], true); + else if (modename.equals_cs("reginvite")) + cm = new ChannelMode(CMODE_REGISTEREDONLY, "CMODE_REGISTEREDONLY", modechar[0]); + else if (modename.equals_cs("regmoderated")) + cm = new ChannelMode(CMODE_REGMODERATED, "CMODE_REGMODERATED", modechar[0]); + else if (modename.equals_cs("secret")) + cm = new ChannelMode(CMODE_SECRET, "CMODE_SECRET", modechar[0]); + else if (modename.equals_cs("sslonly")) + cm = new ChannelMode(CMODE_SSL, "CMODE_SSL", modechar[0]); + else if (modename.equals_cs("stripcolor")) + cm = new ChannelMode(CMODE_STRIPCOLOR, "CMODE_STRIPCOLOR", modechar[0]); + else if (modename.equals_cs("topiclock")) + cm = new ChannelMode(CMODE_TOPIC, "CMODE_TOPIC", modechar[0]); + else if (modename.equals_cs("voice")) + cm = new ChannelModeStatus(CMODE_VOICE, "CMODE_VOICE", modechar[1], modechar[0]); + /* Unknown status mode, (customprefix) - add it */ + else if (modechar.length() == 2) + cm = new ChannelModeStatus(CMODE_END, "", modechar[1], modechar[0]); + + if (cm) + ModeManager::AddChannelMode(cm); + else + Log() << "Unrecognized mode string in CAPAB CHANMODES: " << capab; } - else if (capab.find("MAXMODES=") != Anope::string::npos) + } + if (params[0].equals_cs("USERMODES")) + { + spacesepstream ssep(params[1]); + Anope::string capab; + + while (ssep.GetToken(capab)) { - Anope::string maxmodes(capab.begin() + 9, capab.end()); - ircd->maxmodes = maxmodes.is_pos_number_only() ? convertTo<unsigned>(maxmodes) : 3; + Anope::string modename = capab.substr(0, capab.find('=')); + Anope::string modechar = capab.substr(capab.find('=') + 1); + UserMode *um = NULL; + + if (modename.equals_cs("bot")) + um = new UserMode(UMODE_BOT, "UMODE_BOT", modechar[0]); + else if (modename.equals_cs("callerid")) + um = new UserMode(UMODE_CALLERID, "UMODE_CALLERID", modechar[0]); + else if (modename.equals_cs("cloak")) + um = new UserMode(UMODE_CLOAK, "UMODE_CLOAK", modechar[0]); + else if (modename.equals_cs("deaf")) + um = new UserMode(UMODE_DEAF, "UMODE_DEAF", modechar[0]); + else if (modename.equals_cs("deaf_commonchan")) + um = new UserMode(UMODE_COMMONCHANS, "UMODE_COMMONCHANS", modechar[0]); + else if (modename.equals_cs("helpop")) + um = new UserMode(UMODE_HELPOP, "UMODE_HELPOP", modechar[0]); + else if (modename.equals_cs("hidechans")) + um = new UserMode(UMODE_PRIV, "UMODE_PRIV", modechar[0]); + else if (modename.equals_cs("hideoper")) + um = new UserMode(UMODE_HIDEOPER, "UMODE_HIDEOPER", modechar[0]); + else if (modename.equals_cs("invisible")) + um = new UserMode(UMODE_INVIS, "UMODE_INVIS", modechar[0]); + else if (modename.equals_cs("invis-oper")) + um = new UserMode(UMODE_INVISIBLE_OPER, "UMODE_INVISIBLE_OPER", modechar[0]); + else if (modename.equals_cs("oper")) + um = new UserMode(UMODE_OPER, "UMODE_OPER", modechar[0]); + else if (modename.equals_cs("regdeaf")) + um = new UserMode(UMODE_REGPRIV, "UMODE_REGPRIV", modechar[0]); + else if (modename.equals_cs("servprotect")) + um = new UserMode(UMODE_PROTECTED, "UMODE_PROTECTED", modechar[0]); + else if (modename.equals_cs("showwhois")) + um = new UserMode(UMODE_WHOIS, "UMODE_WHOIS", modechar[0]); + else if (modename.equals_cs("snomask")) + continue; // XXX + else if (modename.equals_cs("u_censor")) + um = new UserMode(UMODE_FILTER, "UMODE_FILTER", modechar[0]); + else if (modename.equals_cs("u_registered")) + um = new UserMode(UMODE_REGISTERED, "UMODE_REGISTERED", modechar[0]); + else if (modename.equals_cs("u_stripcolor")) + um = new UserMode(UMODE_STRIPCOLOR, "UMODE_STRIPCOLOR", modechar[0]); + else if (modename.equals_cs("wallops")) + um = new UserMode(UMODE_WALLOPS, "UMODE_WALLOPS", modechar[0]); + + if (um) + ModeManager::AddUserMode(um); + else + Log() << "Unrecognized mode string in CAPAB USERMODES: " << capab; } } - } - else if (params[0].equals_cs("END")) - { - if (!has_servicesmod) + else if (params[0].equals_cs("MODULES")) { - send_cmd("", "ERROR :m_services_account.so is not loaded. This is required by Anope"); - quitmsg = "ERROR: Remote server does not have the m_services_account module loaded, and this is required."; - quitting = true; - return MOD_STOP; + spacesepstream ssep(params[1]); + Anope::string module; + + while (ssep.GetToken(module)) + if (module.equals_cs("m_svshold.so")) + has_svsholdmod = true; } - if (!ModeManager::FindUserModeByName(UMODE_PRIV)) + else if (params[0].equals_cs("MODSUPPORT")) { - send_cmd("", "ERROR :m_hidechans.so is not loaded. This is required by Anope"); - quitmsg = "ERROR: Remote server does not have the m_hidechans module loaded, and this is required."; - quitting = true; - return MOD_STOP; + spacesepstream ssep(params[1]); + Anope::string module; + + while (ssep.GetToken(module)) + { + if (module.equals_cs("m_services_account.so")) + has_servicesmod = true; + else if (module.equals_cs("m_chghost.so")) + has_chghostmod = true; + else if (module.equals_cs("m_chgident.so")) + has_chgidentmod = true; + else if (module.equals_cs("m_servprotect.so")) + ircd->pseudoclient_mode = "+Ik"; + } } - if (!has_svsholdmod) - ircdproto->SendGlobops(OperServ, "SVSHOLD missing, Usage disabled until module is loaded."); - if (!has_chghostmod) - ircdproto->SendGlobops(OperServ, "CHGHOST missing, Usage disabled until module is loaded."); - if (!has_chgidentmod) - ircdproto->SendGlobops(OperServ, "CHGIDENT missing, Usage disabled until module is loaded."); - ircd->svshold = has_svsholdmod; - } + else if (params[0].equals_cs("CAPABILITIES")) + { + spacesepstream ssep(params[1]); + Anope::string capab; + while (ssep.GetToken(capab)) + { + if (capab.find("CHANMODES") != Anope::string::npos) + { + Anope::string modes(capab.begin() + 10, capab.end()); + commasepstream sep(modes); + Anope::string modebuf; - CapabParse(params); + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + if (ModeManager::FindChannelModeByChar(modebuf[t])) + continue; + // XXX list modes needs a bit of a rewrite + ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, "", modebuf[t])); + } + + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + if (ModeManager::FindChannelModeByChar(modebuf[t])) + continue; + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t])); + } - return true; -} + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + if (ModeManager::FindChannelModeByChar(modebuf[t])) + continue; + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t], true)); + } -bool event_endburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = prev_u_intro; - Server *s = Server::Find(source); + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + if (ModeManager::FindChannelModeByChar(modebuf[t])) + continue; + ModeManager::AddChannelMode(new ChannelMode(CMODE_END, "", modebuf[t])); + } + } + else if (capab.find("USERMODES") != Anope::string::npos) + { + Anope::string modes(capab.begin() + 10, capab.end()); + commasepstream sep(modes); + Anope::string modebuf; - if (!s) - throw CoreException("Got ENDBURST without a source"); + sep.GetToken(modebuf); + sep.GetToken(modebuf); - /* Check if the previously introduced user was Id'd for the nickgroup of the nick he s currently using. - * If not, validate the user. ~ Viper*/ - prev_u_intro = NULL; - if (u && !u->server->IsSynced()) - { - NickAlias *na = findnick(u->nick); + if (sep.GetToken(modebuf)) + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + ModeManager::AddUserMode(new UserModeParam(UMODE_END, "", modebuf[t])); - if (!na || na->nc != u->Account()) + if (sep.GetToken(modebuf)) + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + ModeManager::AddUserMode(new UserMode(UMODE_END, "", modebuf[t])); + } + 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; + } + } + } + else if (params[0].equals_cs("END")) { - validate_user(u); - if (u->HasMode(UMODE_REGISTERED)) - u->RemoveMode(NickServ, UMODE_REGISTERED); + if (!has_servicesmod) + { + send_cmd("", "ERROR :m_services_account.so is not loaded. This is required by Anope"); + quitmsg = "ERROR: Remote server does not have the m_services_account module loaded, and this is required."; + quitting = true; + return MOD_STOP; + } + if (!ModeManager::FindUserModeByName(UMODE_PRIV)) + { + send_cmd("", "ERROR :m_hidechans.so is not loaded. This is required by Anope"); + quitmsg = "ERROR: Remote server does not have the m_hidechans module loaded, and this is required."; + quitting = true; + return MOD_STOP; + } + if (!has_svsholdmod) + ircdproto->SendGlobops(OperServ, "SVSHOLD missing, Usage disabled until module is loaded."); + if (!has_chghostmod) + ircdproto->SendGlobops(OperServ, "CHGHOST missing, Usage disabled until module is loaded."); + if (!has_chgidentmod) + ircdproto->SendGlobops(OperServ, "CHGIDENT missing, Usage disabled until module is loaded."); + ircd->svshold = has_svsholdmod; } - else - /* Set them +r (to negate a possible -r on the stack) */ - u->SetMode(NickServ, UMODE_REGISTERED); - } - Log(LOG_DEBUG) << "Processed ENDBURST for " << s->GetName(); - - s->Sync(true); - return true; -} + IRCdMessage::OnCapab(source, params); + } +}; bool ChannelModeFlood::IsValid(const Anope::string &value) const { - //char *dp, *end; 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; @@ -1161,37 +689,36 @@ bool ChannelModeFlood::IsValid(const Anope::string &value) const class ProtoInspIRCd : public Module { - Message message_endburst, message_436, message_away, message_join, message_kick, message_kill, message_mode, message_motd, - message_nick, message_uid, message_capab, message_part, message_ping, message_time, message_privmsg, message_quit, - message_server, message_squit, message_rsquit, message_topic, message_whois, message_svsmode, message_fhost, + Message message_endburst, + message_uid, 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; + + InspIRCdProto ircd_proto; + Inspircd20IRCdMessage ircd_message; public: ProtoInspIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), - message_endburst("ENDBURST", event_endburst), message_436("436", event_436), message_away("AWAY", event_away), - message_join("JOIN", event_join), message_kick("KICK", event_kick), message_kill("KILL", event_kill), - message_mode("MODE", event_mode), message_motd("MOTD", event_motd), message_nick("NICK", event_nick), - message_uid("UID", event_uid), message_capab("CAPAB", event_capab), message_part("PART", event_part), - message_ping("PING", event_ping), message_time("TIME", event_time), message_privmsg("PRIVMSG", event_privmsg), - message_quit("QUIT", event_quit), message_server("SERVER", event_server), message_squit("SQUIT", event_squit), - message_rsquit("RSQUIT", event_rsquit), message_topic("TOPIC", event_topic), message_whois("WHOIS", event_whois), - message_svsmode("SVSMODE", event_mode), message_fhost("FHOST", event_chghost), + message_endburst("ENDBURST", event_endburst), message_uid("UID", event_uid), + 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_sethost("SETHOST", event_sethost), message_setident("SETIDENT", event_setident), - message_setname("SETNAME", event_setname), message_fjoin("FJOIN", event_fjoin), message_fmode("FMODE", event_fmode), - message_ftopic("FTOPIC", event_ftopic), message_opertype("OPERTYPE", event_opertype), message_idle("IDLE", event_idle), + 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) { this->SetAuthor("Anope"); this->SetType(PROTOCOL); - pmodule_ircd_var(myIrcd); - CapabType c[] = { CAPAB_NOQUIT, CAPAB_SSJ3, CAPAB_NICK2, CAPAB_VL, CAPAB_TLKEXT }; for (unsigned i = 0; i < 5; ++i) Capab.SetFlag(c[i]); - pmodule_ircd_proto(&ircd_proto); + pmodule_ircd_var(myIrcd); + pmodule_ircd_proto(&this->ircd_proto); + pmodule_ircd_message(&this->ircd_message); ModuleManager::Attach(I_OnUserNickChange, this); } diff --git a/modules/protocol/plexus.cpp b/modules/protocol/plexus.cpp index 551c025ae..797f2f09c 100644 --- a/modules/protocol/plexus.cpp +++ b/modules/protocol/plexus.cpp @@ -86,7 +86,7 @@ void plexus_cmd_pass(const Anope::string &pass) send_cmd("", "PASS %s TS 6 :%s", pass.c_str(), Config->Numeric.c_str()); } -class RatboxProto : public IRCDProto +class PlexusProto : public IRCDProto { void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf) { @@ -257,127 +257,45 @@ class RatboxProto : public IRCDProto u->Account()->Shrink("authenticationtoken"); u->Account()->Extend("authenticationtoken", new ExtensibleItemRegular<Anope::string>(svidbuf)); } -} ircd_proto; +}; -bool event_sjoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) +class PlexusIRCdMessage : public IRCdMessage { - Channel *c = findchan(params[1]); - time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; - bool keep_their_modes = true; - - if (!c) - { - c = new Channel(params[1], ts); - c->SetFlag(CH_SYNCING); - } - /* Our creation time is newer than what the server gave us */ - else if (c->creation_time > ts) - { - c->creation_time = ts; - c->Reset(); - - /* Reset mlock */ - check_modes(c); - } - /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ - else if (ts > c->creation_time) - keep_their_modes = false; - - /* If we need to keep their modes, and this SJOIN string contains modes */ - if (keep_their_modes && params.size() >= 3) - { - Anope::string modes; - for (unsigned i = 2; i < params.size() - 1; ++i) - modes += " " + params[i]; - if (!modes.empty()) - modes.erase(modes.begin()); - /* Set the modes internally */ - c->SetModesInternal(NULL, modes); - } - - spacesepstream sep(params[params.size() - 1]); - Anope::string buf; - while (sep.GetToken(buf)) + public: + bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - std::list<ChannelMode *> Status; - char ch; - - /* Get prefixes from the nick */ - while ((ch = ModeManager::GetStatusChar(buf[0]))) - { - buf.erase(buf.begin()); - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); - if (!cm) - { - Log() << "Received unknown mode prefix " << buf[0] << " in SJOIN string"; - continue; - } - - if (keep_their_modes) - Status.push_back(cm); - } + if (params.size() < 2) + return true; - User *u = finduser(buf); - if (!u) + if (params[0][0] == '#' || params[0][0] == '&') + do_cmode(source, params[0], params[2], params[1]); + else { - Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name; - continue; + User *u = finduser(source); + User *u2 = finduser(params[0]); + if (!u || !u2) + return true; + do_umode(u->nick, u2->nick, params[1]); } - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - - /* Add the user to the channel */ - c->JoinUser(u); - - /* Update their status internally on the channel - * 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(*it, buf); - - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1); - - /* 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)) - continue; - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); - } - - /* Channel is done syncing */ - if (c->HasFlag(CH_SYNCING)) - { - /* Unset the syncing flag */ - c->UnsetFlag(CH_SYNCING); - c->Sync(); + return true; } - 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 event_nick(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() == 11) + /* + 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) { /* Source is always the server */ 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, params[6], params[5], params[7], params[3]); @@ -392,139 +310,175 @@ bool event_nick(const Anope::string &source, const std::vector<Anope::string> &p else validate_user(user); } - } - else if (params.size() == 2) - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); - return true; -} -bool event_topic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Channel *c = findchan(params[0]); - if (!c) - { - Log() << "TOPIC for nonexistant channel " << params[0]; return true; } - if (params.size() == 4) + bool OnNick(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); + do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); + return true; } - else + + bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : "")); + 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], ""); + return true; } - return true; -} -bool event_tburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 4) - 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) + { + Channel *c = findchan(params[0]); + if (!c) + { + Log() << "TOPIC for nonexistant channel " << params[0]; + 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]); + 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] : "")); - if (!c) - { - Log() << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; return true; } - c->ChangeTopicInternal(setter, params.size() > 3 ? params[3] : "", topic_time); + bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) + { + Channel *c = findchan(params[1]); + time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; + bool keep_their_modes = true; - return true; -} + if (!c) + { + c = new Channel(params[1], ts); + c->SetFlag(CH_SYNCING); + } + /* Our creation time is newer than what the server gave us */ + else if (c->creation_time > ts) + { + c->creation_time = ts; + c->Reset(); -bool event_436(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 1) - return true; + /* Reset mlock */ + check_modes(c); + } + /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ + else if (ts > c->creation_time) + keep_their_modes = false; - m_nickcoll(params[0]); - return true; -} + /* If we need to keep their modes, and this SJOIN string contains modes */ + if (keep_their_modes && params.size() >= 3) + { + Anope::string modes; + for (unsigned i = 2; i < params.size() - 1; ++i) + modes += " " + params[i]; + if (!modes.empty()) + modes.erase(modes.begin()); + /* Set the modes internally */ + c->SetModesInternal(NULL, modes); + } -bool event_ping(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 1) - return true; - ircdproto->SendPong(params.size() > 1 ? params[1] : Config->ServerName, params[0]); - return true; -} + spacesepstream sep(params[params.size() - 1]); + Anope::string buf; + while (sep.GetToken(buf)) + { + std::list<ChannelMode *> Status; + char ch; -bool event_away(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - m_away(u ? u->nick : source, !params.empty() ? params[0] : ""); - return true; -} + /* Get prefixes from the nick */ + while ((ch = ModeManager::GetStatusChar(buf[0]))) + { + buf.erase(buf.begin()); + ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); + if (!cm) + { + Log() << "Received unknown mode prefix " << buf[0] << " in SJOIN string"; + continue; + } + + if (keep_their_modes) + Status.push_back(cm); + } -bool event_kill(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 1) - m_kill(params[0], params[1]); - return true; -} + User *u = finduser(buf); + if (!u) + { + Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name; + continue; + } -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; -} + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); -bool event_join(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - event_sjoin(source, params); - else - do_join(source, params[0], params[1]); - return true; -} + /* Add the user to the channel */ + c->JoinUser(u); -bool event_motd(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (source.empty()) - return true; + /* Update their status internally on the channel + * 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(*it, buf); - m_motd(source); - return true; -} + /* Now set whatever modes this user is allowed to have on the channel */ + chan_set_correct_modes(u, c, 1); -bool event_privmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 1) - m_privmsg(source, params[0], params[1]); - return 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)) + continue; -bool event_part(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_part(source, params[0], params.size() > 1 ? params[1] : ""); + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); + } - return true; -} + /* Channel is done syncing */ + if (c->HasFlag(CH_SYNCING)) + { + /* Unset the syncing flag */ + c->UnsetFlag(CH_SYNCING); + c->Sync(); + } + + return true; + } +}; -bool event_whois(const Anope::string &source, const std::vector<Anope::string> ¶ms) +bool event_tburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - if (!source.empty() && !params.empty()) + 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]); + + if (!c) { - m_whois(source, params[0]); + Log() << "TOPIC " << params[3] << " for nonexistent channel " << params[0]; + return true; } - return true; -} -/* EVENT: SERVER */ -bool event_server(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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], ""); + c->ChangeTopicInternal(setter, params.size() > 3 ? params[3] : "", topic_time); + return true; } @@ -537,21 +491,6 @@ bool event_sid(const Anope::string &source, const std::vector<Anope::string> &pa return true; } -bool event_squit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_squit(source, params[0]); - return true; -} - -bool event_quit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - do_quit(u ? u->nick : source, !params.empty() ? params[0] : ""); - return true; -} - bool event_mode(const Anope::string &source, const std::vector<Anope::string> ¶ms) { if (params.size() < 2) @@ -582,13 +521,6 @@ bool event_tmode(const Anope::string &source, const std::vector<Anope::string> & return true; } -/* Event: PROTOCTL */ -bool event_capab(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - CapabParse(params); - return true; -} - bool event_pass(const Anope::string &source, const std::vector<Anope::string> ¶ms) { TS6UPLINK = params[3]; @@ -622,13 +554,6 @@ bool event_bmask(const Anope::string &source, const std::vector<Anope::string> & return true; } -bool event_error(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - Log(LOG_DEBUG) << params[0]; - return true; -} - static void AddModes() { /* Add user modes */ @@ -683,34 +608,29 @@ static void AddModes() class ProtoPlexus : public Module { - Message message_436, message_away, message_join, message_kick, message_kill, message_mode, message_tmode, message_motd, - message_nick, message_bmask, message_uid, message_part, message_pass, message_ping, message_privmsg, message_quit, - message_server, message_squit, message_topic, message_tb, message_whois, message_capab, message_sjoin, message_error, - message_sid; + Message message_tmode, message_bmask, message_pass, + message_tb, message_sid; + + PlexusProto ircd_proto; + PlexusIRCdMessage ircd_message; public: ProtoPlexus(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), - message_436("436", event_436), message_away("AWAY", event_away), message_join("JOIN", event_join), - message_kick("KICK", event_kick), message_kill("KILL", event_kill), message_mode("MODE", event_mode), - message_tmode("TMODE", event_tmode), message_motd("MOTD", event_motd), message_nick("NICK", event_nick), - message_bmask("BMASK", event_bmask), message_uid("UID", event_nick), message_part("PART", event_part), - message_pass("PASS", event_pass), message_ping("PING", event_ping), message_privmsg("PRIVMSG", event_privmsg), - message_quit("QUIT", event_quit), message_server("SERVER", event_server), message_squit("SQUIT", event_squit), - message_topic("TOPIC", event_topic), message_tb("TB", event_tburst), message_whois("WHOIS", event_whois), - message_capab("CAPAB", event_capab), message_sjoin("SJOIN", event_sjoin), message_error("ERROR", event_error), + 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) { this->SetAuthor("Anope"); this->SetType(PROTOCOL); - pmodule_ircd_var(myIrcd); - CapabType c[] = { CAPAB_ZIP, CAPAB_TS5, CAPAB_QS, CAPAB_UID, CAPAB_KNOCK }; for (unsigned i = 0; i < 5; ++i) Capab.SetFlag(c[i]); AddModes(); - pmodule_ircd_proto(&ircd_proto); + pmodule_ircd_var(myIrcd); + pmodule_ircd_proto(&this->ircd_proto); + pmodule_ircd_message(&this->ircd_message); } }; diff --git a/modules/protocol/ratbox.cpp b/modules/protocol/ratbox.cpp index 9190d75cd..a1172fa40 100644 --- a/modules/protocol/ratbox.cpp +++ b/modules/protocol/ratbox.cpp @@ -271,136 +271,31 @@ class RatboxProto : public IRCDProto u->Account()->Shrink("authenticationtoken"); u->Account()->Extend("authenticationtoken", new ExtensibleItemRegular<Anope::string>(svidbuf)); } -} ircd_proto; +}; -bool event_sjoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) +class RatboxIRCdMessage : public IRCdMessage { - Channel *c = findchan(params[1]); - time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; - bool keep_their_modes = true; - - if (!c) - { - c = new Channel(params[1], ts); - c->SetFlag(CH_SYNCING); - } - /* Our creation time is newer than what the server gave us */ - else if (c->creation_time > ts) - { - c->creation_time = ts; - c->Reset(); - - /* Reset mlock */ - check_modes(c); - } - /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ - else if (ts > c->creation_time) - keep_their_modes = false; - - /* If we need to keep their modes, and this SJOIN string contains modes */ - if (keep_their_modes && params.size() >= 3) - { - Anope::string modes; - for (unsigned i = 2; i < params.size() - 1; ++i) - modes += " " + params[i]; - if (!modes.empty()) - modes.erase(modes.begin()); - /* Set the modes internally */ - c->SetModesInternal(NULL, modes); - } - - spacesepstream sep(params[params.size() - 1]); - Anope::string buf; - while (sep.GetToken(buf)) + public: + bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - std::list<ChannelMode *> Status; - char ch; - - /* Get prefixes from the nick */ - while ((ch = ModeManager::GetStatusChar(buf[0]))) - { - buf.erase(buf.begin()); - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); - if (!cm) - { - Log() << "Received unknown mode prefix " << buf[0] << " in SJOIN string"; - continue; - } - - if (keep_their_modes) - Status.push_back(cm); - } + if (params.size() < 2) + return true; - User *u = finduser(buf); - if (!u) + if (params[0][0] == '#' || params[0][0] == '&') + do_cmode(source, params[0], params[2], params[1]); + else { - Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name; - continue; + User *u = finduser(source); + User *u2 = finduser(params[0]); + if (!u || !u2) + return true; + do_umode(u->nick, u2->nick, params[1]); } - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - - /* Add the user to the channel */ - c->JoinUser(u); - - /* Update their status internally on the channel - * 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(*it, buf); - - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1); - - /* 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)) - continue; - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); - } - - /* Channel is done syncing */ - if (c->HasFlag(CH_SYNCING)) - { - /* Unset the syncing flag */ - c->UnsetFlag(CH_SYNCING); - c->Sync(); + return true; } - return true; -} - -/* - Non TS6 - - params[0] = nick - params[1] = hop - params[2] = ts - params[3] = modes - params[4] = user - params[5] = host - params[6] = server - params[7] = info - - 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] = info - -*/ -bool event_nick(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() == 9) + bool OnUID(const Anope::string &source, const std::vector<Anope::string> ¶ms) { Server *s = Server::Find(source); /* Source is always the server */ @@ -416,31 +311,158 @@ bool event_nick(const Anope::string &source, const std::vector<Anope::string> &p else validate_user(user); } + + return true; } - else if (params.size() == 2) + + /* + 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) + { do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); - return true; -} -bool event_topic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Channel *c = findchan(params[0]); - if (!c) + return true; + } + + bool OnServer(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - Log() << "TOPIC for nonexistant channel " << params[0]; + 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], ""); return true; } - if (params.size() == 4) + bool OnTopic(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - c->ChangeTopicInternal(params[1], params[3], Anope::string(params[2]).is_pos_number_only() ? convertTo<time_t>(params[2]) : Anope::CurTime); + Channel *c = findchan(params[0]); + if (!c) + { + Log() << "TOPIC for nonexistant channel " << 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] : "")); + } + return true; } - else + + bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - c->ChangeTopicInternal(source, (params.size() > 1 ? params[1] : "")); + Channel *c = findchan(params[1]); + time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; + bool keep_their_modes = true; + + if (!c) + { + c = new Channel(params[1], ts); + c->SetFlag(CH_SYNCING); + } + /* Our creation time is newer than what the server gave us */ + else if (c->creation_time > ts) + { + c->creation_time = ts; + c->Reset(); + + /* Reset mlock */ + check_modes(c); + } + /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ + else if (ts > c->creation_time) + keep_their_modes = false; + + /* If we need to keep their modes, and this SJOIN string contains modes */ + if (keep_their_modes && params.size() >= 3) + { + Anope::string modes; + for (unsigned i = 2; i < params.size() - 1; ++i) + modes += " " + params[i]; + if (!modes.empty()) + modes.erase(modes.begin()); + /* Set the modes internally */ + c->SetModesInternal(NULL, modes); + } + + spacesepstream sep(params[params.size() - 1]); + Anope::string buf; + while (sep.GetToken(buf)) + { + std::list<ChannelMode *> Status; + char ch; + + /* Get prefixes from the nick */ + while ((ch = ModeManager::GetStatusChar(buf[0]))) + { + buf.erase(buf.begin()); + ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); + if (!cm) + { + Log() << "Received unknown mode prefix " << buf[0] << " in SJOIN string"; + continue; + } + + if (keep_their_modes) + Status.push_back(cm); + } + + User *u = finduser(buf); + if (!u) + { + Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name; + continue; + } + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); + + /* Add the user to the channel */ + c->JoinUser(u); + + /* Update their status internally on the channel + * 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(*it, buf); + + /* Now set whatever modes this user is allowed to have on the channel */ + chan_set_correct_modes(u, c, 1); + + /* 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)) + continue; + + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); + } + + /* Channel is done syncing */ + if (c->HasFlag(CH_SYNCING)) + { + /* Unset the syncing flag */ + c->UnsetFlag(CH_SYNCING); + c->Sync(); + } + + return true; } - return true; -} +}; bool event_tburst(const Anope::string &source, const std::vector<Anope::string> ¶ms) { @@ -462,37 +484,6 @@ bool event_tburst(const Anope::string &source, const std::vector<Anope::string> return true; } -bool event_436(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 1) - return true; - - m_nickcoll(params[0]); - return true; -} - -bool event_ping(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() < 1) - return true; - ircdproto->SendPong(params.size() > 1 ? params[1] : Config->ServerName, params[0]); - return true; -} - -bool event_away(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - m_away(u ? u->nick : source, !params.empty() ? params[0] : ""); - return true; -} - -bool event_kill(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 1) - m_kill(params[0], params[1]); - return true; -} - bool event_kick(const Anope::string &source, const std::vector<Anope::string> ¶ms) { if (params.size() > 2) @@ -500,59 +491,6 @@ bool event_kick(const Anope::string &source, const std::vector<Anope::string> &p return true; } -bool event_join(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 1) - event_sjoin(source, params); - else - do_join(source, params[0], params[1]); - return true; -} - -bool event_motd(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (source.empty()) - return true; - - m_motd(source); - return true; -} - -bool event_privmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - // XXX: this is really the same as charybdis - if (params.size() > 1) - m_privmsg(source, params[0], params[1]); - return true; -} - -bool event_part(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_part(source, params[0], params.size() > 1 ? params[1] : ""); - - return true; -} - -bool event_whois(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!source.empty() && !params.empty()) - { - m_whois(source, params[0]); - } - return true; -} - -/* EVENT: SERVER */ -bool event_server(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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], ""); - return true; -} - bool event_sid(const Anope::string &source, const std::vector<Anope::string> ¶ms) { /* :42X SID trystan.nomadirc.net 2 43X :ircd-ratbox test server */ @@ -562,39 +500,6 @@ bool event_sid(const Anope::string &source, const std::vector<Anope::string> &pa return true; } -bool event_squit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_squit(source, params[0]); - return true; -} - -bool event_quit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - User *u = finduser(source); - - do_quit(u ? u->nick : source, !params.empty() ? params[0] : ""); - return true; -} - -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 - { - User *u = finduser(source); - User *u2 = finduser(params[0]); - if (!u || !u2) - return true; - do_umode(u->nick, u2->nick, params[1]); - } - return true; -} - bool event_tmode(const Anope::string &source, const std::vector<Anope::string> ¶ms) { if (params[1][0] == '#' || params[1][0] == '&') @@ -602,13 +507,6 @@ bool event_tmode(const Anope::string &source, const std::vector<Anope::string> & return true; } -/* Event: PROTOCTL */ -bool event_capab(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - CapabParse(params); - return true; -} - bool event_pass(const Anope::string &source, const std::vector<Anope::string> ¶ms) { TS6UPLINK = params[3]; @@ -642,13 +540,6 @@ bool event_bmask(const Anope::string &source, const std::vector<Anope::string> & return true; } -bool event_error(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - Log(LOG_DEBUG) << params[0]; - return true; -} - static void AddModes() { /* Add user modes */ @@ -680,34 +571,28 @@ static void AddModes() class ProtoRatbox : public Module { - Message message_436, message_away, message_join, message_kick, message_kill, message_mode, message_tmode, message_motd, - message_nick, message_bmask, message_uid, message_part, message_pass, message_ping, message_privmsg, message_quit, - message_server, message_squit, message_topic, message_tb, message_whois, message_capab, message_sjoin, message_error, - message_sid; + Message message_kick, message_tmode, message_bmask, message_pass, message_tb, message_sid; + + RatboxProto ircd_proto; + RatboxIRCdMessage ircd_message; public: ProtoRatbox(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), - message_436("436", event_436), message_away("AWAY", event_away), message_join("JOIN", event_join), - message_kick("KICK", event_kick), message_kill("KILL", event_kill), message_mode("MODE", event_mode), - message_tmode("TMODE", event_tmode), message_motd("MOTD", event_motd), message_nick("NICK", event_nick), - message_bmask("BMASK", event_bmask), message_uid("UID", event_nick), message_part("PART", event_part), - message_pass("PASS", event_pass), message_ping("PING", event_ping), message_privmsg("PRIVMSG", event_privmsg), - message_quit("QUIT", event_quit), message_server("SERVER", event_server), message_squit("SQUIT", event_squit), - message_topic("TOPIC", event_topic), message_tb("TB", event_tburst), message_whois("WHOIS", event_whois), - message_capab("CAPAB", event_capab), message_sjoin("SJOIN", event_sjoin), message_error("ERROR", event_error), - message_sid("SID", event_sid) + 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) { this->SetAuthor("Anope"); this->SetType(PROTOCOL); - pmodule_ircd_var(myIrcd); - CapabType c[] = { CAPAB_ZIP, CAPAB_TS5, CAPAB_QS, CAPAB_UID, CAPAB_KNOCK, CAPAB_TSMODE }; for (unsigned i = 0; i < 6; ++i) Capab.SetFlag(c[i]); AddModes(); - pmodule_ircd_proto(&ircd_proto); + pmodule_ircd_var(myIrcd); + pmodule_ircd_proto(&this->ircd_proto); + pmodule_ircd_message(&this->ircd_message); } }; diff --git a/modules/protocol/unreal32.cpp b/modules/protocol/unreal32.cpp index 80d1ab08d..bf3d178ce 100644 --- a/modules/protocol/unreal32.cpp +++ b/modules/protocol/unreal32.cpp @@ -382,174 +382,445 @@ class UnrealIRCdProto : public IRCDProto { ircdproto->SendMode(NickServ, u, "+d 1"); } -} ircd_proto; +}; -/* Event: PROTOCTL */ -bool event_capab(const Anope::string &source, const std::vector<Anope::string> ¶ms) +class Unreal32IRCdMessage : public IRCdMessage { - for (unsigned i = 0; i < params.size(); ++i) + public: + bool OnMode(const Anope::string &source, const std::vector<Anope::string> ¶ms) { - Anope::string capab = params[i]; + 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(source, params[0], modes); + + return true; + } - if (capab.find("CHANMODES") != Anope::string::npos) + /* + ** 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) + { + 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 modes(capab.begin() + 10, capab.end()); - commasepstream sep(modes); - Anope::string modebuf; + Anope::string decoded_ip; + b64_decode(params[9], decoded_ip); + + sockaddrs ip; + ip.ntop(params[9].length() == 8 ? AF_INET : AF_INET6, decoded_ip.c_str()); - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) + 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) { - switch (modebuf[t]) + NickAlias *na = findnick(user->nick); + + if (na && user->timestamp == convertTo<time_t>(params[6])) { - case 'b': - ModeManager::AddChannelMode(new ChannelModeBan('b')); - continue; - case 'e': - ModeManager::AddChannelMode(new ChannelModeExcept('e')); - continue; - case 'I': - ModeManager::AddChannelMode(new ChannelModeInvex('I')); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, "", modebuf[t])); + user->Login(na->nc); + user->SetMode(NickServ, UMODE_REGISTERED); } + else + validate_user(user); } + } + else if (params.size() != 2) + { + Anope::string vhost = params[8]; + if (vhost.equals_cs("*")) + vhost.clear(); - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) + /* 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) { - switch (modebuf[t]) + NickAlias *na = findnick(user->nick); + + if (na && user->timestamp == convertTo<time_t>(params[6])) { - case 'k': - ModeManager::AddChannelMode(new ChannelModeKey('k')); - continue; - case 'f': - ModeManager::AddChannelMode(new ChannelModeFlood('f')); - continue; - case 'L': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_REDIRECT, "CMODE_REDIRECT", 'L')); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t])); + user->Login(na->nc); + user->SetMode(NickServ, UMODE_REGISTERED); } + else + validate_user(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) + { + 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], ""); - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) + 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) + { + 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) + { + for (unsigned i = 0; i < params.size(); ++i) + { + Anope::string capab = params[i]; + + if (capab.find("CHANMODES") != Anope::string::npos) { - switch (modebuf[t]) + Anope::string modes(capab.begin() + 10, capab.end()); + commasepstream sep(modes); + Anope::string modebuf; + + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) { - case 'l': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, "CMODE_LIMIT", 'l', true)); - continue; - case 'j': - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_JOINFLOOD, "CMODE_JOINFLOOD", 'j', true)); - continue; - default: - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t], true)); + switch (modebuf[t]) + { + case 'b': + ModeManager::AddChannelMode(new ChannelModeBan('b')); + continue; + case 'e': + ModeManager::AddChannelMode(new ChannelModeExcept('e')); + continue; + case 'I': + ModeManager::AddChannelMode(new ChannelModeInvex('I')); + continue; + default: + ModeManager::AddChannelMode(new ChannelModeList(CMODE_END, "", modebuf[t])); + } + } + + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + switch (modebuf[t]) + { + case 'k': + ModeManager::AddChannelMode(new ChannelModeKey('k')); + continue; + case 'f': + ModeManager::AddChannelMode(new ChannelModeFlood('f')); + continue; + case 'L': + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_REDIRECT, "CMODE_REDIRECT", 'L')); + continue; + default: + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t])); + } + } + + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + switch (modebuf[t]) + { + case 'l': + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, "CMODE_LIMIT", 'l', true)); + continue; + case 'j': + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_JOINFLOOD, "CMODE_JOINFLOOD", 'j', true)); + continue; + default: + ModeManager::AddChannelMode(new ChannelModeParam(CMODE_END, "", modebuf[t], true)); + } + } + + sep.GetToken(modebuf); + for (size_t t = 0, end = modebuf.length(); t < end; ++t) + { + switch (modebuf[t]) + { + case 'p': + ModeManager::AddChannelMode(new ChannelMode(CMODE_PRIVATE, "CMODE_PRIVATE", 'p')); + continue; + case 's': + ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, "CMODE_SECRET", 's')); + continue; + case 'm': + ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, "CMODE_MODERATED", 'm')); + continue; + case 'n': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, "CMODE_NOEXTERNAL", 'n')); + continue; + case 't': + ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, "CMODE_TOPIC", 't')); + continue; + case 'i': + ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, "CMODE_INVITE", 'i')); + continue; + case 'r': + ModeManager::AddChannelMode(new ChannelModeRegistered('r')); + continue; + case 'R': + ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, "CMODE_REGISTEREDONLY", 'R')); + continue; + case 'c': + ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, "CMODE_BLOCKCOLOR", 'c')); + continue; + case 'O': + ModeManager::AddChannelMode(new ChannelModeOper('O')); + continue; + case 'A': + ModeManager::AddChannelMode(new ChannelModeAdmin('A')); + continue; + case 'Q': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKICK, "CMODE_NOKICK", 'Q')); + continue; + case 'K': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKNOCK, "CMODE_NOKNOCK", 'K')); + continue; + case 'V': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOINVITE, "CMODE_NOINVITE", 'V')); + continue; + case 'C': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NOCTCP, "CMODE_NOCTCP", 'C')); + continue; + case 'u': + ModeManager::AddChannelMode(new ChannelMode(CMODE_AUDITORIUM, "CMODE_AUDITORIUM", 'u')); + continue; + case 'z': + ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, "CMODE_SSL", 'z')); + continue; + case 'N': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NONICK, "CMODE_NONICK", 'N')); + continue; + case 'S': + ModeManager::AddChannelMode(new ChannelMode(CMODE_STRIPCOLOR, "CMODE_STRIPCOLOR", 'S')); + continue; + case 'M': + ModeManager::AddChannelMode(new ChannelMode(CMODE_REGMODERATED, "CMODE_REGMODERATED", 'M')); + continue; + case 'T': + ModeManager::AddChannelMode(new ChannelMode(CMODE_NONOTICE, "CMODE_NONOTICE", 'T')); + continue; + case 'G': + ModeManager::AddChannelMode(new ChannelMode(CMODE_FILTER, "CMODE_FILTER", 'G')); + continue; + default: + ModeManager::AddChannelMode(new ChannelMode(CMODE_END, "", modebuf[t])); + } } } + } + + IRCdMessage::OnCapab(source, params); + + return true; + } + + bool OnSJoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) + { + Channel *c = findchan(params[1]); + time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; + bool keep_their_modes = true; - sep.GetToken(modebuf); - for (size_t t = 0, end = modebuf.length(); t < end; ++t) + if (!c) + { + c = new Channel(params[1], ts); + c->SetFlag(CH_SYNCING); + } + /* Our creation time is newer than what the server gave us */ + else if (c->creation_time > ts) + { + c->creation_time = ts; + c->Reset(); + + /* Reset mlock */ + check_modes(c); + } + /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ + else if (ts > c->creation_time) + keep_their_modes = false; + + /* If we need to keep their modes, and this SJOIN string contains modes */ + if (keep_their_modes && params.size() >= 4) + { + Anope::string modes; + for (unsigned i = 2; i < params.size() - 1; ++i) + modes += " " + params[i]; + if (!modes.empty()) + modes.erase(modes.begin()); + /* Set the modes internally */ + c->SetModesInternal(NULL, modes); + } + + ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), + *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), + *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); + spacesepstream sep(params[params.size() - 1]); + Anope::string buf; + while (sep.GetToken(buf)) + { + /* Ban */ + if (keep_their_modes && ban && buf[0] == '&') + { + buf.erase(buf.begin()); + c->SetModeInternal(ban, buf); + } + /* Except */ + else if (keep_their_modes && except && buf[0] == '"') + { + buf.erase(buf.begin()); + c->SetModeInternal(except, buf); + } + /* Invex */ + else if (keep_their_modes && invex && buf[0] == '\'') + { + buf.erase(buf.begin()); + c->SetModeInternal(invex, buf); + } + else { - switch (modebuf[t]) + std::list<ChannelMode *> Status; + char ch; + + /* Get prefixes from the nick */ + while ((ch = ModeManager::GetStatusChar(buf[0]))) { - case 'p': - ModeManager::AddChannelMode(new ChannelMode(CMODE_PRIVATE, "CMODE_PRIVATE", 'p')); - continue; - case 's': - ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, "CMODE_SECRET", 's')); - continue; - case 'm': - ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, "CMODE_MODERATED", 'm')); - continue; - case 'n': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, "CMODE_NOEXTERNAL", 'n')); - continue; - case 't': - ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, "CMODE_TOPIC", 't')); - continue; - case 'i': - ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, "CMODE_INVITE", 'i')); - continue; - case 'r': - ModeManager::AddChannelMode(new ChannelModeRegistered('r')); - continue; - case 'R': - ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, "CMODE_REGISTEREDONLY", 'R')); - continue; - case 'c': - ModeManager::AddChannelMode(new ChannelMode(CMODE_BLOCKCOLOR, "CMODE_BLOCKCOLOR", 'c')); - continue; - case 'O': - ModeManager::AddChannelMode(new ChannelModeOper('O')); - continue; - case 'A': - ModeManager::AddChannelMode(new ChannelModeAdmin('A')); - continue; - case 'Q': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKICK, "CMODE_NOKICK", 'Q')); - continue; - case 'K': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOKNOCK, "CMODE_NOKNOCK", 'K')); - continue; - case 'V': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOINVITE, "CMODE_NOINVITE", 'V')); - continue; - case 'C': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOCTCP, "CMODE_NOCTCP", 'C')); - continue; - case 'u': - ModeManager::AddChannelMode(new ChannelMode(CMODE_AUDITORIUM, "CMODE_AUDITORIUM", 'u')); - continue; - case 'z': - ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, "CMODE_SSL", 'z')); - continue; - case 'N': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NONICK, "CMODE_NONICK", 'N')); - continue; - case 'S': - ModeManager::AddChannelMode(new ChannelMode(CMODE_STRIPCOLOR, "CMODE_STRIPCOLOR", 'S')); + buf.erase(buf.begin()); + ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); + if (!cm) + { + Log() << "Received unknown mode prefix " << buf[0] << " in SJOIN string"; continue; - case 'M': - ModeManager::AddChannelMode(new ChannelMode(CMODE_REGMODERATED, "CMODE_REGMODERATED", 'M')); - continue; - case 'T': - ModeManager::AddChannelMode(new ChannelMode(CMODE_NONOTICE, "CMODE_NONOTICE", 'T')); - continue; - case 'G': - ModeManager::AddChannelMode(new ChannelMode(CMODE_FILTER, "CMODE_FILTER", 'G')); - continue; - default: - ModeManager::AddChannelMode(new ChannelMode(CMODE_END, "", modebuf[t])); + } + + if (keep_their_modes) + Status.push_back(cm); + } + + User *u = finduser(buf); + if (!u) + { + Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name; + continue; } + + EventReturn MOD_RESULT; + FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); + + /* Add the user to the channel */ + c->JoinUser(u); + + /* Update their status internally on the channel + * 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(*it, buf); + + /* Now set whatever modes this user is allowed to have on the channel */ + chan_set_correct_modes(u, c, 1); + + /* 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)) + continue; + + FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); } } - } - CapabParse(params); + /* Channel is done syncing */ + if (c->HasFlag(CH_SYNCING)) + { + /* Unset the syncing flag */ + c->UnsetFlag(CH_SYNCING); + c->Sync(); + } - return true; -} + return true; + } +}; -/* Events */ -bool event_ping(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - ircdproto->SendPong(params.size() > 1 ? params[1] : Config->ServerName, params[0]); - return true; -} /** This is here because: * - * If we had servers three servers, A, B & C linked like so: A<->B<->C + * 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 immediatly when receiving a new server - * and then finish sync once we get a pong back from that server + * 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) { @@ -575,82 +846,6 @@ bool event_netinfo(const Anope::string &source, const std::vector<Anope::string> return true; } -bool event_436(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - m_nickcoll(params[0]); - return true; -} - -/* -** away -** parv[0] = sender prefix -** parv[1] = away message -*/ -bool event_away(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (source.empty()) - return true; - m_away(source, !params.empty() ? params[0] : ""); - return true; -} - -/* -** m_topic -** source = sender prefix -** parv[0] = channel name -** parv[1] = topic nickname -** parv[2] = topic time -** parv[3] = topic text -*/ -bool event_topic(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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 event_squit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 2) - do_squit(source, params[0]); - return true; -} - -bool event_quit(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_quit(source, params[0]); - return true; -} - -bool event_mode(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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(source, params[0], modes); - return true; -} - /* Unreal sends USER modes with this */ /* umode2 @@ -666,36 +861,6 @@ bool event_umode2(const Anope::string &source, const std::vector<Anope::string> return true; } -bool event_kill(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 2) - return true; - - m_kill(params[0], params[1]); - return true; -} - -bool event_kick(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() != 3) - return true; - do_kick(source, params[0], params[1], params[2]); - return true; -} - -bool event_join(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_join(source, params[0], ""); - return true; -} - -bool event_motd(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!source.empty()) - m_motd(source); - return true; -} bool event_setname(const Anope::string &source, const std::vector<Anope::string> ¶ms) { @@ -782,96 +947,6 @@ bool event_sethost(const Anope::string &source, const std::vector<Anope::string> 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 event_nick(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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; - b64_decode(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) - { - NickAlias *na = findnick(user->nick); - - if (na && user->timestamp == convertTo<time_t>(params[6])) - { - user->Login(na->nc); - user->SetMode(NickServ, UMODE_REGISTERED); - } - else - validate_user(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) - { - NickAlias *na = findnick(user->nick); - - if (na && user->timestamp == convertTo<time_t>(params[6])) - { - user->Login(na->nc); - user->SetMode(NickServ, UMODE_REGISTERED); - } - else - validate_user(user); - } - } - else - do_nick(source, params[0], "", "", "", "", Anope::string(params[1]).is_pos_number_only() ? convertTo<time_t>(params[1]) : 0, "", "", "", ""); - return true; -} - bool event_chghost(const Anope::string &source, const std::vector<Anope::string> ¶ms) { if (params.size() != 2) @@ -888,55 +963,6 @@ bool event_chghost(const Anope::string &source, const std::vector<Anope::string> return true; } -/* EVENT: SERVER */ -bool event_server(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - 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], ""); - ircdproto->SendPing(Config->ServerName, params[0]); - - return true; -} - -bool event_privmsg(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (params.size() > 1) - m_privmsg(source, params[0], params[1]); - return true; -} - -bool event_part(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - do_part(source, params[0], params.size() > 1 ? params[1] : ""); - return true; -} - -bool event_whois(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!source.empty() && !params.empty()) - m_whois(source, params[0]); - return true; -} - -bool event_error(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - if (!params.empty()) - { - Log(LOG_DEBUG) << params[0]; - if (params[0].find("No matching link configuration") != Anope::string::npos) - Log() << "Error: Your IRCD's link block may not be setup correctly, please check unrealircd.conf"; - } - return true; -} - bool event_sdesc(const Anope::string &source, const std::vector<Anope::string> ¶ms) { Server *s = Server::Find(source); @@ -947,131 +973,6 @@ bool event_sdesc(const Anope::string &source, const std::vector<Anope::string> & return true; } -bool event_sjoin(const Anope::string &source, const std::vector<Anope::string> ¶ms) -{ - Channel *c = findchan(params[1]); - time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo<time_t>(params[0]) : 0; - bool keep_their_modes = true; - - if (!c) - { - c = new Channel(params[1], ts); - c->SetFlag(CH_SYNCING); - } - /* Our creation time is newer than what the server gave us */ - else if (c->creation_time > ts) - { - c->creation_time = ts; - c->Reset(); - - /* Reset mlock */ - check_modes(c); - } - /* Their TS is newer than ours, our modes > theirs, unset their modes if need be */ - else if (ts > c->creation_time) - keep_their_modes = false; - - /* If we need to keep their modes, and this SJOIN string contains modes */ - if (keep_their_modes && params.size() >= 4) - { - Anope::string modes; - for (unsigned i = 2; i < params.size() - 1; ++i) - modes += " " + params[i]; - if (!modes.empty()) - modes.erase(modes.begin()); - /* Set the modes internally */ - c->SetModesInternal(NULL, modes); - } - - ChannelMode *ban = ModeManager::FindChannelModeByName(CMODE_BAN), - *except = ModeManager::FindChannelModeByName(CMODE_EXCEPT), - *invex = ModeManager::FindChannelModeByName(CMODE_INVITEOVERRIDE); - spacesepstream sep(params[params.size() - 1]); - Anope::string buf; - while (sep.GetToken(buf)) - { - /* Ban */ - if (keep_their_modes && ban && buf[0] == '&') - { - buf.erase(buf.begin()); - c->SetModeInternal(ban, buf); - } - /* Except */ - else if (keep_their_modes && except && buf[0] == '"') - { - buf.erase(buf.begin()); - c->SetModeInternal(except, buf); - } - /* Invex */ - else if (keep_their_modes && invex && buf[0] == '\'') - { - buf.erase(buf.begin()); - c->SetModeInternal(invex, buf); - } - else - { - std::list<ChannelMode *> Status; - char ch; - - /* Get prefixes from the nick */ - while ((ch = ModeManager::GetStatusChar(buf[0]))) - { - buf.erase(buf.begin()); - ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); - if (!cm) - { - Log() << "Received unknown mode prefix " << buf[0] << " in SJOIN string"; - continue; - } - - if (keep_their_modes) - Status.push_back(cm); - } - - User *u = finduser(buf); - if (!u) - { - Log(LOG_DEBUG) << "SJOIN for nonexistant user " << buf << " on " << c->name; - continue; - } - - EventReturn MOD_RESULT; - FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); - - /* Add the user to the channel */ - c->JoinUser(u); - - /* Update their status internally on the channel - * 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(*it, buf); - - /* Now set whatever modes this user is allowed to have on the channel */ - chan_set_correct_modes(u, c, 1); - - /* 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)) - continue; - - FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); - } - } - - /* Channel is done syncing */ - if (c->HasFlag(CH_SYNCING)) - { - /* Unset the syncing flag */ - c->UnsetFlag(CH_SYNCING); - c->Sync(); - } - - return true; -} - /* Borrowed part of this check from UnrealIRCd */ bool ChannelModeFlood::IsValid(const Anope::string &value) const { @@ -1148,57 +1049,60 @@ static void AddModes() class ProtoUnreal : public Module { - Message message_436, message_away, message_away2, message_join, message_join2, message_kick, message_kick2, - message_kill, message_kill2, message_mode, message_mode2, message_nick, message_nick2, message_part, - message_part2, message_ping, message_ping2, message_pong, message_pong2, message_privmsg, message_privmsg2, - message_quit, message_quit2, message_server, message_server2, message_squit, message_squit2, message_topic, - message_topic2, message_svsmode, message_svsmode2, message_svs2mode, message_svs2mode2, message_whois, message_whois2, + 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_error2, - message_umode2, message_umode22, message_sjoin, message_sjoin2, message_sdesc, message_sdesc2; + 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; public: ProtoUnreal(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), - message_436("436", event_436), message_away("AWAY", event_away), message_away2("6", event_away), - message_join("JOIN", event_join), message_join2("C", event_join), message_kick("KICK", event_kick), - message_kick2("H", event_kick), message_kill("KILL", event_kill), message_kill2(".", event_kill), - message_mode("MODE", event_mode), message_mode2("G", event_mode), message_nick("NICK", event_nick), - message_nick2("&", event_nick), message_part("PART", event_part), message_part2("D", event_part), - message_ping("PING", event_ping), message_ping2("8", event_ping), message_pong("PONG", event_pong), - message_pong2("9", event_pong), message_privmsg("PRIVMSG", event_privmsg), message_privmsg2("!", event_privmsg), - message_quit("QUIT", event_quit), message_quit2(",", event_quit), message_server("SERVER", event_server), - message_server2("'", event_server), message_squit("SQUIT", event_squit), message_squit2("-", event_squit), - message_topic("TOPIC", event_topic), message_topic2(")", event_topic), message_svsmode("SVSMODE", event_mode), - message_svsmode2("n", event_mode), message_svs2mode("SVS2MODE", event_mode), message_svs2mode2("v", event_mode), - message_whois("WHOIS", event_whois), message_whois2("#", event_whois), message_capab("PROTOCTL", event_capab), - message_capab2("_", event_capab), message_chghost("CHGHOST", event_chghost), message_chghost2("AL", event_chghost), + 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("ERROR", event_error), message_error2("5", event_error), message_umode2("UMODE2", event_umode2), - message_umode22("|", event_umode2), message_sjoin("SJOIN", event_sjoin), message_sjoin2("~", event_sjoin), + 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", m_stats), message_time(">", m_time), message_version("+", m_version) + message_stats("2", OnStats), message_time(">", OnTime), message_version("+", OnVersion) { this->SetAuthor("Anope"); this->SetType(PROTOCOL); - pmodule_ircd_var(myIrcd); - CapabType c[] = { CAPAB_NOQUIT, CAPAB_NICKIP, CAPAB_ZIP, CAPAB_TOKEN, CAPAB_SSJ3, CAPAB_NICK2, CAPAB_VL, CAPAB_TLKEXT, CAPAB_CHANMODE, CAPAB_NICKCHARS }; for (unsigned i = 0; i < 10; ++i) Capab.SetFlag(c[i]); AddModes(); - pmodule_ircd_proto(&ircd_proto); + pmodule_ircd_var(myIrcd); + pmodule_ircd_proto(&this->ircd_proto); + pmodule_ircd_message(&this->ircd_message); ModuleManager::Attach(I_OnUserNickChange, this); } |