diff options
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/ |
