From aed53dbb47822a79eb9a6b61095ad04ec3d67818 Mon Sep 17 00:00:00 2001 From: Adam Date: Mon, 6 Dec 2010 17:06:57 -0500 Subject: 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. --- include/extern.h | 55 +- include/servers.h | 3 - include/services.h | 25 + include/users.h | 6 +- modules/core/cs_forbid.cpp | 2 +- modules/core/cs_info.cpp | 2 +- modules/core/cs_list.cpp | 2 +- modules/core/cs_suspend.cpp | 2 +- modules/core/cs_unban.cpp | 2 +- modules/core/ns_ghost.cpp | 2 +- modules/core/ns_group.cpp | 2 +- modules/core/ns_info.cpp | 2 +- modules/core/ns_list.cpp | 2 +- modules/core/ns_register.cpp | 4 +- modules/core/os_chankill.cpp | 2 +- modules/core/os_defcon.cpp | 6 +- modules/core/os_noop.cpp | 4 +- modules/extra/cs_entrymsg.cpp | 2 +- modules/extra/cs_set_misc.cpp | 2 +- modules/extra/m_alias.cpp | 2 +- modules/extra/m_xmlrpc_main.cpp | 2 +- modules/extra/ns_set_misc.cpp | 2 +- modules/protocol/bahamut.cpp | 512 +++++++---------- modules/protocol/inspircd-ts6.h | 413 ++++++++++++++ modules/protocol/inspircd11.cpp | 908 ++++++++++++++----------------- modules/protocol/inspircd12.cpp | 1149 ++++++++++++--------------------------- modules/protocol/inspircd20.cpp | 1147 ++++++++++++-------------------------- modules/protocol/plexus.cpp | 436 ++++++--------- modules/protocol/ratbox.cpp | 449 ++++++--------- modules/protocol/unreal32.cpp | 960 +++++++++++++++----------------- src/actions.cpp | 29 +- src/botserv.cpp | 59 +- src/command.cpp | 6 +- src/commands.cpp | 2 +- src/ircd.cpp | 34 -- src/messages.cpp | 316 +++-------- src/misc.cpp | 64 +-- src/modes.cpp | 4 +- src/operserv.cpp | 14 +- src/process.cpp | 2 +- src/protocol.cpp | 329 +++++++++++ src/regchannel.cpp | 2 +- src/servers.cpp | 61 --- src/sessions.cpp | 29 +- src/users.cpp | 70 +-- 45 files changed, 3041 insertions(+), 4087 deletions(-) create mode 100644 modules/protocol/inspircd-ts6.h delete mode 100644 src/ircd.cpp diff --git a/include/extern.h b/include/extern.h index 24f12a84f..c30914c9e 100644 --- a/include/extern.h +++ b/include/extern.h @@ -23,12 +23,13 @@ E void ModuleRunTimeDirCleanUp(); E IRCDVar *ircd; E IRCDProto *ircdproto; +E IRCdMessage *ircdmessage; /**** actions.c ****/ -E void kill_user(const Anope::string &source, const Anope::string &user, const Anope::string &reason); +E void kill_user(const Anope::string &source, User *user, const Anope::string &reason); E bool bad_password(User *u); -E void common_unban(ChannelInfo *ci, const Anope::string &nick); +E void common_unban(ChannelInfo *ci, User *u); E BotInfo *BotServ; E BotInfo *ChanServ; @@ -53,7 +54,6 @@ E Anope::string normalizeBuffer(const Anope::string &); E void bot_raw_ban(User *requester, ChannelInfo *ci, const Anope::string &nick, const Anope::string &reason); E void bot_raw_kick(User *requester, ChannelInfo *ci, const Anope::string &nick, const Anope::string &reason); -E void bot_raw_mode(User *requester, ChannelInfo *ci, const Anope::string &mode, const Anope::string &nick); /**** channels.c ****/ @@ -133,6 +133,7 @@ E Uplink *uplink_server; /**** ircd.c ****/ E void pmodule_ircd_proto(IRCDProto *); E void pmodule_ircd_var(IRCDVar *ircdvar); +E void pmodule_ircd_message(IRCdMessage *message); /**** language.cpp ****/ E std::vector languages; @@ -191,32 +192,45 @@ E void check_memos(User *u); E MemoInfo *getmemoinfo(const Anope::string &name, bool &ischan, bool &isforbid); E void memo_send(CommandSource &source, const Anope::string &name, const Anope::string &text, int z); -/**** messages.c ****/ - -E int m_nickcoll(const Anope::string &user); -E int m_away(const Anope::string &source, const Anope::string &msg); -E int m_kill(const Anope::string &nick, const Anope::string &msg); -E int m_motd(const Anope::string &source); -E int m_privmsg(const Anope::string &source, const Anope::string &receiver, const Anope::string &message); -E bool m_stats(const Anope::string &source, const std::vector &); -E int m_whois(const Anope::string &source, const Anope::string &who); -E bool m_time(const Anope::string &source, const std::vector &); -E bool m_version(const Anope::string &source, const std::vector &); +/**** messages.cpp ****/ + E void init_core_messages(); +E bool OnStats(const Anope::string &source, const std::vector &); +E bool OnTime(const Anope::string &source, const std::vector &); +E bool OnVersion(const Anope::string &source, const std::vector &); + +E bool On436(const Anope::string &, const std::vector &); +E bool OnAway(const Anope::string &, const std::vector &); +E bool OnJoin(const Anope::string &, const std::vector &); +E bool OnKick(const Anope::string &, const std::vector &); +E bool OnKill(const Anope::string &, const std::vector &); +E bool OnMode(const Anope::string &, const std::vector &); +E bool OnNick(const Anope::string &, const std::vector &); +E bool OnUID(const Anope::string &, const std::vector &); +E bool OnPart(const Anope::string &, const std::vector &); +E bool OnPing(const Anope::string &, const std::vector &); +E bool OnPrivmsg(const Anope::string &, const std::vector &); +E bool OnQuit(const Anope::string &, const std::vector &); +E bool OnServer(const Anope::string &, const std::vector &); +E bool OnSQuit(const Anope::string &, const std::vector &); +E bool OnTopic(const Anope::string &, const std::vector &); +E bool OnWhois(const Anope::string &, const std::vector &); +E bool OnCapab(const Anope::string &, const std::vector &); +E bool OnSJoin(const Anope::string &, const std::vector &); +E bool OnError(const Anope::string &, const std::vector &); + /**** misc.c ****/ E bool IsFile(const Anope::string &filename); E int toupper(char); E int tolower(char); -E char *strscpy(char *d, const char *s, size_t len); #ifndef HAVE_STRLCPY E size_t strlcpy(char *, const char *, size_t); #endif #ifndef HAVE_STRLCAT E size_t strlcat(char *, const char *, size_t); #endif -E char *strnrepl(char *s, int32 size, const char *old, const char *nstr); E const char *merge_args(int argc, char **argv); E const char *merge_args(int argc, const char **argv); @@ -302,8 +316,8 @@ E std::vector exceptions; E void get_session_stats(long &count, long &mem); E void get_exception_stats(long &count, long &mem); -E void add_session(const Anope::string &nick, const Anope::string &host, const Anope::string &hostip); -E void del_session(const Anope::string &host); +E void add_session(User *u); +E void del_session(User *u); E void expire_exceptions(); @@ -333,10 +347,7 @@ E User *finduser(const Anope::string &nick); E User *do_nick(const Anope::string &source, const Anope::string &nick, const Anope::string &username, const Anope::string &host, const Anope::string &server, const Anope::string &realname, time_t ts, const Anope::string &ip, const Anope::string &vhost, const Anope::string &uid, const Anope::string &modes); E void do_umode(const Anope::string &, const Anope::string &user, const Anope::string &modes); -E void do_quit(const Anope::string &source, const Anope::string &reason); -E void do_kill(const Anope::string &source, const Anope::string &reason); - -E bool is_oper(User *user); +E void do_kill(User *user, const Anope::string &reason); E bool is_excepted(ChannelInfo *ci, User *user); E bool is_excepted_mask(ChannelInfo *ci, const Anope::string &mask); diff --git a/include/servers.h b/include/servers.h index 43f3dc659..d22ab05ac 100644 --- a/include/servers.h +++ b/include/servers.h @@ -4,10 +4,7 @@ /* Anope */ extern CoreExport Server *Me; -extern CoreExport void CapabParse(const std::vector ¶ms); - extern CoreExport void do_server(const Anope::string &source, const Anope::string &servername, unsigned int hops, const Anope::string &descript, const Anope::string &numeric); -extern CoreExport void do_squit(const Anope::string &source, const Anope::string &server); extern CoreExport const char *ts6_uid_retrieve(); extern CoreExport const char *ts6_sid_retrieve(); diff --git a/include/services.h b/include/services.h index 2b4c13f7c..75aa4905c 100644 --- a/include/services.h +++ b/include/services.h @@ -897,6 +897,7 @@ enum DefconLevel * Forward declaration reqired, because the base IRCDProto class uses some crap from in here. */ class IRCDProto; +class IRCdMessage; struct Uplink; class ServerConfig; @@ -999,6 +1000,30 @@ class CoreExport IRCDProto virtual void SetAutoIdentificationToken(User *u) { } }; +class CoreExport IRCdMessage +{ + public: + virtual bool On436(const Anope::string &, const std::vector &); + virtual bool OnAway(const Anope::string &, const std::vector &); + virtual bool OnJoin(const Anope::string &, const std::vector &); + virtual bool OnKick(const Anope::string &, const std::vector &); + virtual bool OnKill(const Anope::string &, const std::vector &); + virtual bool OnMode(const Anope::string &, const std::vector &) = 0; + virtual bool OnUID(const Anope::string &, const std::vector &); + virtual bool OnNick(const Anope::string &, const std::vector &) = 0; + virtual bool OnPart(const Anope::string &, const std::vector &); + virtual bool OnPing(const Anope::string &, const std::vector &); + virtual bool OnPrivmsg(const Anope::string &, const std::vector &); + virtual bool OnQuit(const Anope::string &, const std::vector &); + virtual bool OnServer(const Anope::string &, const std::vector &) = 0; + virtual bool OnSQuit(const Anope::string &, const std::vector &); + virtual bool OnTopic(const Anope::string &, const std::vector &) = 0; + virtual bool OnWhois(const Anope::string &, const std::vector &); + virtual bool OnCapab(const Anope::string &, const std::vector &); + virtual bool OnSJoin(const Anope::string &, const std::vector &) = 0; + virtual bool OnError(const Anope::string &, const std::vector &); +}; + /*************************************************************************/ struct Uplink diff --git a/include/users.h b/include/users.h index 26ee5f33e..e06c5c5a5 100644 --- a/include/users.h +++ b/include/users.h @@ -149,12 +149,12 @@ class CoreExport User : public Extensible /** * Send a message (notice or privmsg, depending on settings) to a user - * @param source Sender nick + * @param source Sender * @param fmt Format of the Message * @param ... any number of parameters */ - void SendMessage(const Anope::string &source, const char *fmt, ...); - virtual void SendMessage(const Anope::string &source, const Anope::string &msg); + void SendMessage(BotInfo *source, const char *fmt, ...); + virtual void SendMessage(BotInfo *source, const Anope::string &msg); /** Send a language string message to a user * @param source Sender diff --git a/modules/core/cs_forbid.cpp b/modules/core/cs_forbid.cpp index 19f4b6f04..d3976929d 100644 --- a/modules/core/cs_forbid.cpp +++ b/modules/core/cs_forbid.cpp @@ -71,7 +71,7 @@ class CommandCSForbid : public Command { UserContainer *uc = *it++; - if (is_oper(uc->user)) + if (uc->user->HasMode(UMODE_OPER)) continue; c->Kick(ChanServ, uc->user, "%s", !reason.empty() ? reason.c_str() : GetString(uc->user, CHAN_FORBID_REASON).c_str()); diff --git a/modules/core/cs_info.cpp b/modules/core/cs_info.cpp index 7f4784270..d842ad4ea 100644 --- a/modules/core/cs_info.cpp +++ b/modules/core/cs_info.cpp @@ -46,7 +46,7 @@ class CommandCSInfo : public Command if (ci->HasFlag(CI_FORBIDDEN)) { - if (is_oper(u) && !ci->forbidby.empty()) + if (u->HasMode(UMODE_OPER) && !ci->forbidby.empty()) source.Reply(CHAN_X_FORBIDDEN_OPER, chan.c_str(), ci->forbidby.c_str(), !ci->forbidreason.empty() ? ci->forbidreason.c_str() : GetString(u, NO_REASON).c_str()); else source.Reply(CHAN_X_FORBIDDEN, chan.c_str()); diff --git a/modules/core/cs_list.cpp b/modules/core/cs_list.cpp index 87d0afb79..73947c9de 100644 --- a/modules/core/cs_list.cpp +++ b/modules/core/cs_list.cpp @@ -33,7 +33,7 @@ public: int count = 0, from = 0, to = 0; bool forbidden = false, suspended = false, channoexpire = false; - if (Config->CSListOpersOnly && !is_oper(u)) + if (Config->CSListOpersOnly && !u->HasMode(UMODE_OPER)) { source.Reply(ACCESS_DENIED); return MOD_STOP; diff --git a/modules/core/cs_suspend.cpp b/modules/core/cs_suspend.cpp index ee0dd4d17..c2172dcb2 100644 --- a/modules/core/cs_suspend.cpp +++ b/modules/core/cs_suspend.cpp @@ -56,7 +56,7 @@ class CommandCSSuspend : public Command { UserContainer *uc = *it++; - if (is_oper(uc->user)) + if (uc->user->HasMode(UMODE_OPER)) continue; c->Kick(NULL, uc->user, "%s", !reason.empty() ? reason.c_str() : GetString(uc->user->Account(), CHAN_SUSPEND_REASON).c_str()); diff --git a/modules/core/cs_unban.cpp b/modules/core/cs_unban.cpp index f9b5908e0..df5d2877e 100644 --- a/modules/core/cs_unban.cpp +++ b/modules/core/cs_unban.cpp @@ -48,7 +48,7 @@ class CommandCSUnban : public Command return MOD_CONT; } - common_unban(ci, u2->nick); + common_unban(ci, u2); if (u2 == u) source.Reply(CHAN_UNBANNED, c->name.c_str()); else diff --git a/modules/core/ns_ghost.cpp b/modules/core/ns_ghost.cpp index 14796bc78..323b0378c 100644 --- a/modules/core/ns_ghost.cpp +++ b/modules/core/ns_ghost.cpp @@ -49,7 +49,7 @@ class CommandNSGhost : public Command { Log(LOG_COMMAND, u, this) << "for " << nick; Anope::string buf = "GHOST command used by " + u->nick; - kill_user(Config->s_NickServ, nick, buf); + kill_user(Config->s_NickServ, user, buf); source.Reply(NICK_GHOST_KILLED, nick.c_str()); } } diff --git a/modules/core/ns_group.cpp b/modules/core/ns_group.cpp index 697c29447..ebf6c74af 100644 --- a/modules/core/ns_group.cpp +++ b/modules/core/ns_group.cpp @@ -48,7 +48,7 @@ class CommandNSGroup : public Command if (Config->RestrictOperNicks) for (std::list >::iterator it = Config->Opers.begin(), it_end = Config->Opers.end(); it != it_end; ++it) - if (!is_oper(u) && u->nick.find_ci(it->first) != Anope::string::npos) + if (!u->HasMode(UMODE_OPER) && u->nick.find_ci(it->first) != Anope::string::npos) { source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); return MOD_CONT; diff --git a/modules/core/ns_info.cpp b/modules/core/ns_info.cpp index 32d8fe8f7..a3ee2f70f 100644 --- a/modules/core/ns_info.cpp +++ b/modules/core/ns_info.cpp @@ -57,7 +57,7 @@ class CommandNSInfo : public Command } else if (na->HasFlag(NS_FORBIDDEN)) { - if (is_oper(u) && !na->last_usermask.empty()) + if (u->HasMode(UMODE_OPER) && !na->last_usermask.empty()) source.Reply(NICK_X_FORBIDDEN_OPER, nick.c_str(), na->last_usermask.c_str(), !na->last_realname.empty() ? na->last_realname.c_str() : GetString(u, NO_REASON).c_str()); else source.Reply(NICK_X_FORBIDDEN, nick.c_str()); diff --git a/modules/core/ns_list.cpp b/modules/core/ns_list.cpp index 89fba90d8..bf7a0efbd 100644 --- a/modules/core/ns_list.cpp +++ b/modules/core/ns_list.cpp @@ -49,7 +49,7 @@ class CommandNSList : public Command suspended = nsnoexpire = forbidden = unconfirmed = false; - if (Config->NSListOpersOnly && !is_oper(u)) /* reverse the help logic */ + if (Config->NSListOpersOnly && !u->HasMode(UMODE_OPER)) /* reverse the help logic */ { source.Reply(ACCESS_DENIED); return MOD_STOP; diff --git a/modules/core/ns_register.cpp b/modules/core/ns_register.cpp index abcba133d..edf8181e5 100644 --- a/modules/core/ns_register.cpp +++ b/modules/core/ns_register.cpp @@ -196,7 +196,7 @@ class CommandNSRegister : public CommandNSConfirm return MOD_CONT; } - if (!is_oper(u) && Config->NickRegDelay && Anope::CurTime - u->my_signon < Config->NickRegDelay) + if (!u->HasMode(UMODE_OPER) && Config->NickRegDelay && Anope::CurTime - u->my_signon < Config->NickRegDelay) { source.Reply(NICK_REG_DELAY, Config->NickRegDelay); return MOD_CONT; @@ -230,7 +230,7 @@ class CommandNSRegister : public CommandNSConfirm { Anope::string nick = it->first; - if (u->nick.find_ci(nick) != Anope::string::npos && !is_oper(u)) + if (u->nick.find_ci(nick) != Anope::string::npos && !u->HasMode(UMODE_OPER)) { source.Reply(NICK_CANNOT_BE_REGISTERED, u->nick.c_str()); return MOD_CONT; diff --git a/modules/core/os_chankill.cpp b/modules/core/os_chankill.cpp index 3201858e7..506adbdfb 100644 --- a/modules/core/os_chankill.cpp +++ b/modules/core/os_chankill.cpp @@ -70,7 +70,7 @@ class CommandOSChanKill : public Command { UserContainer *uc = *it++; - if (is_oper(uc->user)) + if (uc->user->HasMode(UMODE_OPER)) continue; SGLine->Add(OperServ, u, "*@" + uc->user->host, expires, realreason); diff --git a/modules/core/os_defcon.cpp b/modules/core/os_defcon.cpp index 0dd9dcedb..cc8809586 100644 --- a/modules/core/os_defcon.cpp +++ b/modules/core/os_defcon.cpp @@ -164,7 +164,7 @@ class OSDefcon : public Module } if (CheckDefCon(DEFCON_NO_NEW_CLIENTS) || CheckDefCon(DEFCON_AKILL_NEW_CLIENTS)) - kill_user(Config->s_OperServ, u->nick, Config->DefConAkillReason); + kill_user(Config->s_OperServ, u, Config->DefConAkillReason); return EVENT_STOP; } @@ -208,7 +208,7 @@ class OSDefcon : public Module EventReturn OnPreCommandRun(User *u, BotInfo *bi, Anope::string &command, Anope::string &message, ChannelInfo *ci) { - if (!is_oper(u) && (CheckDefCon(DEFCON_OPER_ONLY) || CheckDefCon(DEFCON_SILENT_OPER_ONLY))) + if (!u->HasMode(UMODE_OPER) && (CheckDefCon(DEFCON_OPER_ONLY) || CheckDefCon(DEFCON_SILENT_OPER_ONLY))) { if (!CheckDefCon(DEFCON_SILENT_OPER_ONLY)) u->SendMessage(bi, OPER_DEFCON_DENIED); @@ -281,7 +281,7 @@ class OSDefcon : public Module if (!Config->SessionLimitDetailsLoc.empty()) ircdproto->SendMessage(OperServ, u->nick, "%s", Config->SessionLimitDetailsLoc.c_str()); - kill_user(Config->s_OperServ, u->nick, "Session limit exceeded"); + kill_user(Config->s_OperServ, u, "Session limit exceeded"); ++session->hits; if (Config->MaxSessionKill && session->hits >= Config->MaxSessionKill) { diff --git a/modules/core/os_noop.cpp b/modules/core/os_noop.cpp index 0d740d29a..1e799d4d3 100644 --- a/modules/core/os_noop.cpp +++ b/modules/core/os_noop.cpp @@ -44,8 +44,8 @@ class CommandOSNOOP : public Command User *u2 = *it; ++it; - if (u2 && is_oper(u2) && Anope::Match(u2->server->GetName(), server, true)) - kill_user(Config->s_OperServ, u2->nick, reason); + if (u2 && u2->HasMode(UMODE_OPER) && Anope::Match(u2->server->GetName(), server, true)) + kill_user(Config->s_OperServ, u2, reason); } } else if (cmd.equals_ci("REVOKE")) diff --git a/modules/extra/cs_entrymsg.cpp b/modules/extra/cs_entrymsg.cpp index aae1b5f0e..e44d21827 100644 --- a/modules/extra/cs_entrymsg.cpp +++ b/modules/extra/cs_entrymsg.cpp @@ -174,7 +174,7 @@ class CSEntryMessage : public Module if (c->ci->GetExtRegular("cs_entrymsg", messages)) for (unsigned i = 0; i < messages.size(); ++i) - u->SendMessage(whosends(c->ci)->nick, "[%s] %s", c->ci->name.c_str(), messages[i].message.c_str()); + u->SendMessage(whosends(c->ci), "[%s] %s", c->ci->name.c_str(), messages[i].message.c_str()); } } diff --git a/modules/extra/cs_set_misc.cpp b/modules/extra/cs_set_misc.cpp index 9f4ade29c..2e5fa5965 100644 --- a/modules/extra/cs_set_misc.cpp +++ b/modules/extra/cs_set_misc.cpp @@ -173,7 +173,7 @@ class CSSetMisc : public Module Anope::string value; if (ci->GetExtRegular("chanserv:" + it->first, value)) - u->SendMessage(Config->s_ChanServ, " %s: %s", it->first.c_str(), value.c_str()); + u->SendMessage(ChanServ, " %s: %s", it->first.c_str(), value.c_str()); } } diff --git a/modules/extra/m_alias.cpp b/modules/extra/m_alias.cpp index de23557a3..3b9556772 100644 --- a/modules/extra/m_alias.cpp +++ b/modules/extra/m_alias.cpp @@ -66,7 +66,7 @@ class ModuleAlias : public Module if (fantasy != alias.fantasy) return EVENT_CONTINUE; - else if (!is_oper(u) && alias.operonly) + else if (!u->HasMode(UMODE_OPER) && alias.operonly) return EVENT_CONTINUE; else if (!fantasy && !bi->nick.equals_ci(alias.client)) return EVENT_CONTINUE; diff --git a/modules/extra/m_xmlrpc_main.cpp b/modules/extra/m_xmlrpc_main.cpp index 74b570ee2..59088792f 100644 --- a/modules/extra/m_xmlrpc_main.cpp +++ b/modules/extra/m_xmlrpc_main.cpp @@ -13,7 +13,7 @@ class XMLRPCUser : public User this->server = Me; } - void SendMessage(const Anope::string &source, const Anope::string &msg) + void SendMessage(BotInfo *, const Anope::string &msg) { this->out += msg + "\n"; } diff --git a/modules/extra/ns_set_misc.cpp b/modules/extra/ns_set_misc.cpp index 65dfadc2d..b38c98ae7 100644 --- a/modules/extra/ns_set_misc.cpp +++ b/modules/extra/ns_set_misc.cpp @@ -176,7 +176,7 @@ class NSSetMisc : public Module Anope::string value; if (na->nc->GetExtRegular("nickserv:" + it->first, value)) - u->SendMessage(Config->s_NickServ, " %s: %s", it->first.c_str(), value.c_str()); + u->SendMessage(NickServ, " %s: %s", it->first.c_str(), value.c_str()); } } 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 ¶ms) +class BahamutIRCdMessage : public IRCdMessage { - Channel *c = findchan(params[1]); - time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo(params[0]) : 0; - bool keep_their_modes = false; - - if (!c) + public: + bool OnMode(const Anope::string &source, const std::vector ¶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 ¶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(params[2]) : 0, params[8], "", "", params[3]); + if (user) + { + NickAlias *na; + if (user->timestamp == convertTo(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(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 ¶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(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 ¶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(params[2]) : Anope::CurTime); + + return true; + } - /* Add the user to the channel */ - c->JoinUser(u); + bool OnSJoin(const Anope::string &source, const std::vector ¶ms) + { + Channel *c = findchan(params[1]); + time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo(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 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 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::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::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 ¶ms) +static bool event_xs(BotInfo *bi, const Anope::string &source, const std::vector ¶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(params[2]) : 0, params[8], "", "", params[3]); - if (user) - { - NickAlias *na; - if (user->timestamp == convertTo(params[7]) && (na = findnick(user->nick))) - { - user->Login(na->nc); - user->SetMode(NickServ, UMODE_REGISTERED); - } - else - validate_user(user); - } + std::vector 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(params[1]) : 0, "", "", "", ""); - return true; -} -/* EVENT : CAPAB */ -bool event_capab(const Anope::string &source, const std::vector ¶ms) -{ - CapabParse(params); return true; } /* EVENT : OS */ bool event_os(const Anope::string &source, const std::vector ¶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 ¶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 ¶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 ¶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 ¶ms) { - if (!params.empty()) - m_privmsg(source, Config->s_ChanServ, params[0]); - return true; -} - -bool event_436(const Anope::string &source, const std::vector ¶ms) -{ - if (!params.empty()) - m_nickcoll(params[0]); - return true; -} - -/* EVENT : SERVER */ -bool event_server(const Anope::string &source, const std::vector ¶ms) -{ - do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0, params[2], ""); - return true; -} - -/* EVENT : PRIVMSG */ -bool event_privmsg(const Anope::string &source, const std::vector ¶ms) -{ - if (params.size() > 1) - m_privmsg(source, params[0], params[1]); - return true; -} - -bool event_part(const Anope::string &source, const std::vector ¶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 ¶ms) -{ - if (!source.empty() && params.size() > 0) - m_whois(source, params[0]); - return true; -} - -bool event_topic(const Anope::string &source, const std::vector ¶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(params[2]) : Anope::CurTime); - - return true; -} - -bool event_squit(const Anope::string &source, const std::vector ¶ms) -{ - if (params.size() > 0) - do_squit(source, params[0]); - return true; -} - -bool event_quit(const Anope::string &source, const std::vector ¶ms) -{ - if (params.size() > 0) - do_quit(source, params[0]); - return true; -} - -/* EVENT: MODE */ -bool event_mode(const Anope::string &source, const std::vector ¶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 ¶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 ¶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 ¶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 ¶ms) -{ - if (source.empty()) - return true; - - m_motd(source); - return true; -} - -bool event_away(const Anope::string &source, const std::vector ¶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 ¶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 ¶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 ¶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(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(Anope::CurTime), static_cast(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(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(u->timestamp), u->nick.c_str(), u->host.c_str(), u->host.c_str(), u->GetIdent().c_str(), static_cast(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(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(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(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(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(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(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 ¶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 ¶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 ¶ms) + { + do_server(source, params[0], Anope::string(params[2]).is_pos_number_only() ? convertTo(params[2]) : 0, params[4], params[3]); + return true; + } + + bool OnTopic(const Anope::string &source, const std::vector ¶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 &) = 0; + + bool OnSJoin(const Anope::string &source, const std::vector ¶ms) + { + Channel *c = findchan(params[0]); + time_t ts = Anope::string(params[1]).is_pos_number_only() ? convertTo(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 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::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(svidbuf)); } -} ircd_proto; +}; + +class InspircdIRCdMessage : public IRCdMessage +{ + public: + bool OnMode(const Anope::string &source, const std::vector ¶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 ¶ms) + { + if (params.size() == 8) + { + time_t ts = Anope::string(params[0]).is_pos_number_only() ? convertTo(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 ¶ms) + { + do_server(source, params[0], Anope::string(params[1]).is_pos_number_only() ? convertTo(params[1]) : 0, params[2], ""); + return true; + } + + bool OnTopic(const Anope::string &source, const std::vector ¶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 ¶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(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 miss